Как программно изменить разрешения на уровне предмета до первого сохранения?
Вопрос
У меня есть ситуация, когда существуют строгие требования к разрешениям в список которых я уже написал пользовательскую форму. Требование заключается в том, что при создании на основе метаданных только определенные пользователи имеют доступ к чтению и записи товара.
Моя первая попытка в этом было поставить это в приемник событий в списке, чтобы убедиться, что разрешения обновляются при добавлении элемента. Я поставил элемент в добавленном элементе событие, поскольку во время добавления элемента у меня нет способа поднять привилегии и получить повышенный экземпляр элемента (который я знаю). Это вызвало нежелательную задержку, хотя короче, между тем, когда был создан элемент, и время, когда код на самом деле управляет.
Следующая вещь, которую я пытался, должен был поставить настроить разрешения элемента в виде сразу после того, как элемент создан, поскольку я бы тогда имел удостоверение личности для элемента, чтобы я мог получить его в приподнятом контексте (я хочу, чтобы элемент был создан под контекстом текущего пользователя). Это проблематично, потому что, как только этот подход был реализован, около 50% случаев, когда мы получаем ошибку в рабочем процессе, который работает на элементе, создавая поговорку: «Не удалось запустить рабочий процесс. Рабочий процесс не может получить доступ к элементу, который был применен к. " (Вероятно, стоит отметить, что это рабочий процесс Nintex) - я предполагаю, что проблема связана с некоторыми гоночными условиями, где в середине элемента .Update () установить разрешения, рабочий процесс пытается начать одновременно. .
В идеале я хотел бы, чтобы иметь возможность обновлять разрешения на саму первое обновление товара (создать) или во время события itemAdding, но я не уверен, как это сделать без повышения целого процесса, так что товар затем создается Системный счет, а не пользователь, который фактически создал элемент.
Какие варианты у меня есть доступны для меня?
Решение
То, как вы изначально использовали его, используя ItemAdded Event, было правильным.Тем не менее, есть только один шаг - вы можете сделать событие немедленно, изменив его, чтобы запустить синхронно, а не асинхронно.
Детали того, как переключать синхронный режим здесь: http://blogs.technet.com/b/stefan_gossner/archive/2011/11/10/using-synchronous-quot-af-quot-events-eg-itempdated-in-sharepoint-2010.aspx
Другие советы
Один подход, который вы можете попробовать, включает в себя одобрение контента в этом списке.Это будет означать, что всякий раз, когда создается новый элемент, он останется в
Я надеюсь, что это поможет вам в вашем конкретном сценарии.
Вы должны быть в состоянии подражать пользователю, который создал элемент или сделал изменение в вашем коде.
public override void ItemUpdating(SPItemEventProperties properties)
{
base.ItemUpdating(properties);
SPUserToken objSPUserToken = properties.OriginatingUserToken;
if (objSPUserToken != null)
{
using (SPSite objSPSite = new SPSite(properties.SiteId, objSPUserToken))
{
using (SPWeb objSPWeb = objSPSite.OpenWeb())
{
//You can perform user context specific changes here...
}
}
}
}
.
Что я сделал, чтобы обойти эту проблему, это вместо автоматического запуска рабочего процесса через настройки рабочего процесса, мы находимся «вручную», удававшись от рабочего процесса через код после обновления.
string workflowId = "{...}"; //dynamically retrieve workflow id
SPWorkflowManager workflowManager = item.Web.Site.WorkflowManager;
SPWorkflowAssociationCollection workflowCollection = item.ParentList.WorkflowAssociations;
foreach (SPWorkflowAssociation workflow in workflowCollection)
{
if (String.Compare(workflow.BaseId.ToString("B"), workflowId, true) == 0)
{
workflowManager.StartWorkflow(item, workflow, workflow.AssociationData, true);
break;
}
}
.