Answered [TFS API] Edit work-item field when marked as read-only?

  • Tuesday, July 31, 2012 1:19 PM
     
     

    I am trying to update a field of a work-item using the TFS API.

    However, certain states mark the field as read-only (for example, the Done state) and at that point I'm not able to modify the field, even when using the TFS API. I noticed that the IsEditable field returns false, but I cannot set it.

    As my code works for every state in which the field is editable I'm fairly confident it works. When checking the work-item using the Team Explorer UI I can see my changes are applied and tracked in the history of the work-item.

    How can I modify the field after it has been marked as read-only? Is it even possible? (I could switch the state back so the field is editable, but that's something I'd like to avoid.)

All Replies

  • Thursday, August 02, 2012 7:06 AM
    Moderator
     
     

    Hi Jensen,

    Thank you for your post.

    Read-only is field rule, tfs api cannot edit it. Please try to let administrator to remove this rule.

    regards,


    Lily Wu [MSFT]
    MSDN Community Support | Feedback to us

    • Marked As Answer by Jensen Somers Thursday, August 02, 2012 1:19 PM
    • Unmarked As Answer by Jensen Somers Thursday, August 02, 2012 1:19 PM
    •  
  • Thursday, August 02, 2012 1:32 PM
     
     Answered Has Code

    I tried removing the READONLY rule on the field, as suggested by Lily_Wu, but that still did not allow me to modify the field for all existing items.

    After a few-other searches I stumbled upon the webservice API and the BypassRules property. This property is not available when only using the managed API, so the webservice has to be called.

    First, connect to the server and collection like we'd normally do:

    var tpc = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(new Uri(SERVER_URI), new UICredentialsProvider());
    tpc.EnsureAuthenticated();
    
    var store = tpc.GetService<WorkItemStore>();
    var server = tpc.GetService<WorkItemServer>();

    Next, after creating a list with all the work-item id's I need, I create the XML package and use the UpdateWorkItem type.

    private static StringBuilder GetXmlPackage(WorkItemStore store, IEnumerable<int> workItemIds)
    {
    	var sb = new StringBuilder();
    	sb.Append("<Package>");
    
    	foreach (var id in workItemIds)
    	{
    		var item = store.GetWorkItem(id);
    		var effort = Convert.ToSingle(item.Fields["Effort"].Value) / 2.0f;
    
    		sb.AppendFormat("<UpdateWorkItem ObjectType='WorkItem' BypassRules='1' WorkItemID='{0}' Revision='{1}'>", item.Id, item.Rev.ToString());
    		sb.Append("<Columns>");
    		sb.AppendFormat("<Column Column='Microsoft.VSTS.Scheduling.Effort' Type='Double'><Value>{0}</Value></Column>", XmlConvert.ToString(effort));
    		sb.Append("</Columns>");
    		sb.Append("<InsertText FieldName='System.History' FieldDisplayName='History'>Updated effort.</InsertText>");
    		sb.Append("</UpdateWorkItem>");
    	}
    
    	sb.Append("</Package>");
    	return sb;
    }

    And finally, I call the BulkUpdate function to modify all work-items.

    private static void UpdateWorkItems(WorkItemStore store, WorkItemServer server, IEnumerable<int> workItemIds)
    {
    	var sb = GetXmlPackage(store, workItemIds);
    
    	var mthe = new MetadataTableHaveEntry[0];
    	string dbStamp;
    	IMetadataRowSets rowSets;
    	XmlElement outElement;
    
    	var doc = new XmlDocument();
    	doc.LoadXml(sb.ToString());
    
    	server.BulkUpdate(
    		WorkItemServer.NewRequestId(),
    		doc.DocumentElement,
    		out outElement,
    		mthe,
    		out dbStamp,
    		out rowSets);
    }
    • Marked As Answer by Jensen Somers Thursday, August 02, 2012 1:32 PM
    •