ItemUpdated не меняет значения поля
-
30-09-2020 - |
Вопрос
У меня есть библиотека документов, которая должна заменить столбец Name
значением из столбца Employee
.
Код:
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);
}
}
При загрузке нового документа и вводе поля Employee
поле Name
установлено правильно.Однако, если вы вернетесь и отредактируете элемент, поле Name
не изменится.
Почему этот код будет работать только при создании, а не при обновлении?А еще лучше, чего не хватает, чтобы заставить код работать как при создании, так и при редактировании?
Решение
Некоторые замечания, которые могут помочь:
У вас может быть бесконечный цикл, так как вызов .Update запускает новое обновление, а затем приемник событий... Вы можете не заметить этого сразу, поскольку в SharePoint 2013 теперь есть защита, которая останавливает повторный вход после 10 вхождений... Просто добавьте
EventFiringEnabled = false;
в начале вашего методаItemUpdated
, а затемEventFiringEnabled = true;
в блокеfinally
в конце.AllowUnsafeUpdates
, скорее всего, здесь не нужен, так как вы работаете с контекстным объектомSPWeb
(т.е. вы не создавали его явно), полученным из POST-запроса.В этом случае вам не нужно заморачиваться сAllowUnsafeUpdates
.Столбец «Имя» — это стандартное текстовое поле из библиотеки документов, верно?
Вы должны добавить некоторые проверки
null
, например,item["Employee"]
может быть нулевым и вызвать исключение сitem["Employee"].ToString()
.Я не понимаю вашего
if (!item.Name.StartsWith(item.DisplayName))
... Какой смысл?
Чтобы решить эту проблему, вам обязательно нужно подключить отладчик Visual Studio к w3wp во время выполнения теста.Это позволит вам обеспечить:
Приемник событий вызывается при обновлении свойств (наверное, по вашему описанию)
Где это не удается, и какое сообщение об ошибке.
Другие советы
Здесь немного изменений... Добавьте класс DisabledEvents и разрешите небезопасные обновления.Также, если вы установите properties.ErrorMessage, оно будет отображаться в пользовательском интерфейсе, если есть проблема.
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;
}
}