I better start off by explaining a high level overview of what I'm trying to do (just in case I'm going about this horribly wrong): In TFS, we have a "Story" workitem that includes a "priority" field. At any given time we have maybe 20-30 stories that have a priority. As an example, we might have 20 perfectly prioritized stories (1 through 20), and then want to create a new story that should be our new top priority. So, I want to be able to give it a priority of 1, and then have a server-side plugin that will update the priority on all of the other stories so that I end up with 1 through 21 (1 being the new story we just created).
To this end, I've created a server-side plugin for TFS 2010 that subscribes to WorkItemChangedEvent. It's smart enough to figure out if the priority was updated, so it only changes workitems in this case. The problem I run into is that if I alter the priority and run WorkItem.Save(), it triggers WorkItemChangedEvent again, and the priority has changed, so the logic is true, and it updates and saves again.
Earlier, I had created a server-side plugin that updated the time on one of the datetime fields to 00:00:00 (in the case that it wasn't already 00:00:00) and noticed this behavior. It wasn't TOO big of a problem, because on the second run through, nothing would happen because the time would already be 00:00:00. But in this case of trying to update the priorities on a whole bunch of work items, it's a deal-breaker. Is there a way to stop WorkItem.Save() from triggering a WorkItemChangedEvent? Maybe another way to go about doing this altogether?
Easiest way I know would solve this is to add a specific comment and then to to check the comment/history item of the work item to see that you last updated it as part of the change you're doing.
Also, check out the following post for pointers on how to create your service so that it remains stable.
I solved this issue in my own extension by checking if the changer identity is the service identity. If it is then the logic is skipped.
This seems like a slightly more elegant solution then tagging the data.
var workItemChangedArgs = notificationEventArgs as WorkItemChangedEvent;
var identityService = requestContext.GetService<IdentityService>();
var changerIdentity = identityService.ReadIdentities(
requestContext,
new List<IdentityDescriptor> {
IdentityHelper.CreateDescriptorFromSid(workItemChangedArgs.ChangerSid)
},
QueryMembership.Expanded,
null).Single();
if (!IdentityHelper.IsServiceIdentity(requestContext, changerIdentity)) {
// Do stuff….
}