ItemUpdated not changing field values
-
30-09-2020 - |
题
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?
解决方案
Some remarks that may help:
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 yourItemUpdated
method and thenEventFiringEnabled = true;
in afinally
block at the end.AllowUnsafeUpdates
is most probably not needed here since you work on the contextualSPWeb
object (i.e. you did not create it explicitely), issued from a POST request. In this case, you don't have to bother withAllowUnsafeUpdates
.The column 'Name' is the standard Text field from a document Library, right?
You should add some
null
checks, for instanceitem["Employee"]
may be null and raise an exception withitem["Employee"].ToString()
.I don't understand your
if (!item.Name.StartsWith(item.DisplayName))
... What's the point?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.
其他提示
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;
}
}