As it turns out, this cannot be done directly when using the managed API. When using the web-service API, there is a BypassRules
property which can be set.
The web-service API requires an XML package, so the difficulty lies in creating it.
First, connect to the server and collection like you'd normally would.
var tpc = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(
new Uri(SERVER_URI), new UICredentialsProvider());
tpc.EnsureAuthenticated();
var store = tpc.GetService<WorkItemStore>();
var server = tpc.GetService<WorkItemServer>();
After I made the connection, I assembled a list of work-item ID's I wanted to modify. In my case, I needed to divide all work-item Efforts
by 2.
The XML package syntax is fairly straight forward. One thing to note is that I explicitly needed to convert my effort value (a float) to a string, even though the internal type is double. (I might have done something wrong here, but the end result was what I wanted.)
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;
}
The last thing to do is call the web-server and do a bulk update 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);
}