0

I have a document library that should replace the Name column with the value from an Employee column.

Code:

public override void ItemUpdated(SPItemEventProperties properties)
{
    base.ItemUpdated(properties);
    try
    {
        SPListItem item = properties.ListItem;
        SPFieldUser employee = item.Fields.GetField("Employee") as SPFieldUser;
        SPFieldUserValue current = employee.GetFieldValue(item["Employee"].ToString()) as SPFieldUserValue;
        if (!item.Name.StartsWith(item.DisplayName))
        {
            item["Name"] = current.User.Name.Replace(", ", "_");
            item["Letter"] = current.User.Name.Substring(0, 1);
        }
        item.Update();
    }
    catch(SPException error)
    {
        throw new SPException(error.Message);
    }
}

The when a new document is uploaded and the Employee field is entered, the Name field is correctly set. However, if you go back and edit the item the Name field doesn't change.

Why would this code only work on creation and not update? Better yet, what is missing to get the code to work on both creation and edit?

8
  • A sidenote: Wouldn't this cause an endless loop?
    – eirikb
    Commented Nov 17, 2014 at 21:09
  • I'm not sure exactly how it would.
    – psdpainter
    Commented Nov 17, 2014 at 21:15
  • 1) fired after the item is updated, EventFiringEnabled is not set to false. 2) Same item is updated. 3) Triggers an updated event; go to 1)...
    – eirikb
    Commented Nov 17, 2014 at 21:19
  • Yeah, you need to disable the event firing Commented Nov 17, 2014 at 21:20
  • @Colbs so are you saying that is the answer? Better yet...where to disable event firing?
    – psdpainter
    Commented Nov 17, 2014 at 21:21

2 Answers 2

2

Some remarks that may help:

  1. You may have an endless loop since the call to .Update triggers itself a new update and then the Event Receiver... You may not notice it immediately since SharePoint 2013 has now a protection that stops the re-entrance after 10 occurrences... Simply add EventFiringEnabled = false; at the begin of your ItemUpdated method and then EventFiringEnabled = true; in a finally block at the end.

  2. AllowUnsafeUpdates is most probably not needed here since you work on the contextual SPWeb object (i.e. you did not create it explicitely), issued from a POST request. In this case, you don't have to bother with AllowUnsafeUpdates.

  3. The column 'Name' is the standard Text field from a document Library, right?

  4. You should add some null checks, for instance item["Employee"] may be null and raise an exception with item["Employee"].ToString().

  5. I don't understand your if (!item.Name.StartsWith(item.DisplayName))... What's the point?

  6. To progress on this problem, you definitely need to attach the Visual Studio debugger to w3wp while running the test. This will allow you to ensure:

    • The event receiver is called on an properties update (I guess it is, according to your description)
    • Where it fails, and what's the error message.
1
  • I got my issue fixed, but this is an outstanding answer.
    – psdpainter
    Commented Nov 30, 2014 at 19:08
2

Few changes here...Add the DisabledEvents class and allow unsafe updates. Also if you set the properties.ErrorMessage, it will show in the UI if there is an issue.

public override void ItemUpdated(SPItemEventProperties properties)
{
    base.ItemUpdated(properties);
    try
    {
        using (DisabledEventsScope scope = new DisabledEventsScope())
        {
            SPListItem item = properties.ListItem;
            SPFieldUser employee = item.Fields.GetField("Employee") as SPFieldUser;
            SPFieldUserValue current = employee.GetFieldValue(item["Employee"].ToString()) as SPFieldUserValue;
            if (!item.Name.StartsWith(item.DisplayName))
            {
                item["Name"] = current.User;
                item["Letter"] = current.User.Name.Substring(0, 1);
            }
            item.Web.AllowUnsafeUpdates = true;
            item.Update();
            item.Web.AllowUnsafeUpdates = false;
        }
    }
    catch(Exception error)
    {
        properties.ErrorMessage = error.Message;
    }
}


class DisabledEventsScope : SPItemEventReceiver, IDisposable
{
    // Boolean to hold the original value of the EventFiringEnabled property 
    bool _originalValue;

    public DisabledEventsScope()
    {
        // Save off the original value of EventFiringEnabled 
        _originalValue = base.EventFiringEnabled;

        // Set EventFiringEnabled to false to disable it 
        base.EventFiringEnabled = false;
    }

    public void Dispose()
    {
        // Set EventFiringEnabled back to its original value 
        base.EventFiringEnabled = _originalValue;
    }
}
6
  • Unfortunately this doesn't work.
    – psdpainter
    Commented Nov 17, 2014 at 22:31
  • Can you break and step through it in VS? These things can be hard to reattach sometimes. It may have to do with your casting and field types Commented Nov 17, 2014 at 22:43
  • Yeah that's what I'm doing now. Thanks for the help by the way...
    – psdpainter
    Commented Nov 17, 2014 at 23:35
  • Yes, Np. Is the "Name" field a Single line of text? Commented Nov 18, 2014 at 15:19
  • No, it's of type Person or Group.
    – psdpainter
    Commented Nov 18, 2014 at 23:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.