11

I have a SharePoint workflow which is running whenever the item changes. The workflow communicates with an external REST service. If the service returns a string, I want to update one of the field values with that string. Unfortunately, this update will trigger another instance of the workflow for this item once the current workflow terminates. I end up with an infinite loop!

How I can prevent this from happening? SPListItem has Update(), UpdateOverwriteVersion(), and SystemUpdate() methods but none of them seem to prevent subsequent workflows from being triggered.

I could inspect the last modified timestamp of the item and terminate the workflow if the last update happened within a certain timespan, but I am looking for a more robust solution.

Philipp Schmid
  • 5,778
  • 5
  • 44
  • 66

5 Answers5

18

You could use some extension method to update item silently.

public static class SPListItemExtensions
{
/// <summary>
/// Provides ability to update list item without firing event receiver.
/// </summary>
/// <param name="item"></param>
/// <param name="doNotFireEvents">Disables firing event receiver while updating item.</param>
public static void Update(this SPListItem item, bool doNotFireEvents)
{
    SPItemEventReceiverHandling rh = new SPItemEventReceiverHandling();
    if (doNotFireEvents)
    {
        try
        {
            rh.DisableEventFiring();
            item.Update();
        }
        finally
        {
            rh.EnableEventFiring();
        }
    }
    else
    {
        item.Update();
    }
}

/// <summary>
/// Provides ability to update list item without firing event receiver.
/// </summary>
/// <param name="item"></param>
/// <param name="incrementListItemVersion"></param>
/// <param name="doNotFireEvents">Disables firing event receiver while updating item.</param>
public static void SystemUpdate(this SPListItem item, bool incrementListItemVersion, bool doNotFireEvents)
{
    SPItemEventReceiverHandling rh = new SPItemEventReceiverHandling();
    if (doNotFireEvents)
    {
        try
        {
            rh.DisableEventFiring();
            item.SystemUpdate(incrementListItemVersion);
        }
        finally
        {
            rh.EnableEventFiring();
        }
    }
    else
    {
        item.SystemUpdate(incrementListItemVersion);
    }
}

/// <summary>
/// Provides ability to update list item without firing event receiver.
/// </summary>
/// <param name="item"></param>
/// <param name="doNotFireEvents">Disables firing event receiver while updating item.</param>
public static void SystemUpdate(this SPListItem item, bool doNotFireEvents)
{
    SPItemEventReceiverHandling rh = new SPItemEventReceiverHandling();
    if (doNotFireEvents)
    {
        try
        {
            rh.DisableEventFiring();
            item.SystemUpdate();
        }
        finally
        {
            rh.EnableEventFiring();
        }
    }
    else
    {
        item.SystemUpdate();
    }
}

private class SPItemEventReceiverHandling : SPItemEventReceiver
{
    public SPItemEventReceiverHandling() { }

    new public void DisableEventFiring()
    {
        base.DisableEventFiring();
    }

    new public void EnableEventFiring()
    {
        base.EnableEventFiring();
    }


   }
}
Janis Veinbergs
  • 6,907
  • 5
  • 48
  • 78
  • 1
    A suggestion: Implement SPItemEventReceiverHandling using the "using" pattern, see http://adrianhenke.wordpress.com/2010/01/29/disable-item-events-firing-during-item-update/ – driAn May 07 '10 at 08:35
  • 1
    See answers below for more examples and code that works for SP2010 – Dennis G Jun 28 '11 at 17:04
8

Some more links because the above solution is not working for 2010:

The best solution:

Dennis G
  • 21,405
  • 19
  • 96
  • 133
2

It seems Microsoft have reworked this in SharePoint 2010, the EventFiringEnabled and EventFiringDisabled have been made obsolete.

Instead use a boolean Property named EventFiringEnabled.

Adam Carr
  • 21
  • 1
0

Could you add a step to the beginning of the workflow that terminates the workflow if an update was triggered by a change to that field? (The one that is updated by using the service.)

You could have a hidden boolean field on the list item that you set to true when you update the list using the service. Then, at the beginning of the workflow, you could check to see if this field is set to true.

UnhipGlint
  • 339
  • 3
  • 10
-3

you can use set field in current item instud of update list item.

Set field update the list item with out triggering new event

Hojo
  • 935
  • 1
  • 7
  • 13
  • do you can explain what you mean with example? – gdbdable Mar 27 '13 at 17:50
  • Bizarrely, nearly 10 years later, I'm having this issue touching up a legacy SP2013 workflow and this answer is exactly what I was after (despite being out of context of the OP's question). – James Love Jun 21 '22 at 09:08