Как получить элемент контекста в работе Workflow (SharePoint)

Я пишу пользовательскую активность для рабочего процесса sharepoint, и я не знаю, как я могу использовать текущий элемент рабочего процесса, SPWeb или SPSite.

Я вижу http://blogs.microsoft.co.il/blogs/davidbi/archive/2008/07/21/How-to-get-the-context-item-in-workflow-activity-sharepoint.aspx, но xml-процедуры этого решения для меня слишком плохи.

Возможно, существует еще одно решение только для кода, чтобы получить контекстный элемент в деятельности Workflow?

Ответ 1

Ответ на этот вопрос состоит в двух шагах:

  • Добавить свойства в пользовательскую активность .cs
  • Свяжите свойства в вашем файле .actions(поэтому SPD знает, как сопоставлять ваши свойства)
  • Используйте свойства в вашем коде

ШАГ 1. Вот код для свойств (мой класс называется GetEmails, который вам нужно будет переименовать в ваш класс):

public static DependencyProperty __ContextProperty = System.Workflow.ComponentModel.DependencyProperty.Register("__Context", typeof(WorkflowContext), typeof(GetEmails));

[Description("The site context")]
[Category("User")]
[Browsable(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public WorkflowContext __Context
{
    get
    {
        return ((WorkflowContext)(base.GetValue(GetEmails.__ContextProperty)));
    }
    set
    {
        base.SetValue(GetEmails.__ContextProperty, value);
    }
}

public static DependencyProperty __ListIdProperty = System.Workflow.ComponentModel.DependencyProperty.Register("__ListId", typeof(string), typeof(GetEmails));

[ValidationOption(ValidationOption.Required)]
public string __ListId
{
    get
    {
        return ((string)(base.GetValue(GetEmails.__ListIdProperty)));
    }
    set
    {
        base.SetValue(GetEmails.__ListIdProperty, value);
    }
}

public static DependencyProperty __ListItemProperty = System.Workflow.ComponentModel.DependencyProperty.Register("__ListItem", typeof(int), typeof(GetEmails));

[ValidationOption(ValidationOption.Required)]
public int __ListItem
{
    get
    {
        return ((int)(base.GetValue(GetEmails.__ListItemProperty)));
    }
    set
    {
        base.SetValue(GetEmails.__ListItemProperty, value);
    }
}

public static DependencyProperty __ActivationPropertiesProperty = DependencyProperty.Register("__ActivationProperties", typeof(Microsoft.SharePoint.Workflow.SPWorkflowActivationProperties), typeof(GetEmails));

[ValidationOption(ValidationOption.Required)]
public Microsoft.SharePoint.Workflow.SPWorkflowActivationProperties __ActivationProperties
{
    get
    {
        return (Microsoft.SharePoint.Workflow.SPWorkflowActivationProperties)base.GetValue(GetEmails.__ActivationPropertiesProperty);
    }
    set
    {
        base.SetValue(GetEmails.__ActivationPropertiesProperty, value);
    }
}

ШАГ 2. Затем в вашем файле .actions добавьте в свой блок сопоставления для этих свойств (обратите внимание на записи для __ListID, __ListItem, __Context и __ActivationProperties):

<Action Name="[DESCRIPTION OF YOUR ACTION]"
  ClassName="[Your.Namespace.Goes.Here].GetEmails"
  Assembly="[yourDLLName], Version=1.0.0.0, Culture=neutral, PublicKeyToken=0bfc6fa4c4aa913b"
  AppliesTo="all"
  Category="[Your Category Goes Here]">
  <RuleDesigner Sentence="[blah blah blah]">
    <FieldBind Field="PeopleFieldName" Text="people field" Id="1"/>
    <FieldBind Field="Output" Text="emailAddress" Id="2" DesignerType="parameterNames" />
  </RuleDesigner>
  <Parameters>
    <Parameter Name="__Context" Type="Microsoft.SharePoint.WorkflowActions.WorkflowContext" Direction="In" />
    <Parameter Name="__ListId" Type="System.String, mscorlib" Direction="In" />
    <Parameter Name="__ListItem" Type="System.Int32, mscorlib" Direction="In" />
    <Parameter Name="PeopleFieldName" Type="System.String, mscorlib" Direction="In" />
    <Parameter Name="Output" Type="System.String, mscorlib" Direction="Out" />
    <Parameter Name="__ActivationProperties" Type="Microsoft.SharePoint.Workflow.SPWorkflowActivationProperties, Microsoft.SharePoint" Direction="Out" />
  </Parameters>
</Action>

ШАГ 3: Вот пример выполнения функции:

protected override ActivityExecutionStatus Execute(ActivityExecutionContext provider)
{
    Output = string.Empty;

    try
    {
        SPWeb web = __Context.Web;
        // get all of the information we currently have about the item
        // that this workflow is running on
        Guid listGuid = new Guid(__ListId);
        SPList myList = web.Lists[listGuid];
        SPListItem myItem = myList.GetItemById(__ListItem);

        //...
    }
    catch (Exception e)
    {
        //...
    }

    return ActivityExecutionStatus.Closed;
}

Ответ 2

Я не уверен, что это изменение в API 2010, но свойство __Context предоставляет все необходимые элементы, включая список и элемент. Пример ниже включает предложение @davek для отказа от контекста безопасности:

            var contextWeb = __Context.Web;
            var site = new SPSite(contextWeb.Url);
            var web = site.OpenWeb();

            var list = web.Lists[new Guid(__Context.ListId)];
            var item = list.GetItemById( __Context.ItemId);

Ответ 3

Ответ Kit Menke очень всеобъемлющий и охватывает практически все, что вам нужно: я бы добавил только следующее...

Если вы это сделаете:

SPWeb tmpweb = __Context.Web;
SPSite site = new SPSite(tmpweb.Url);
SPWeb web = site.OpenWeb();

вместо этого:

SPWeb web = __Context.Web;
...

тогда вы свободны от контекста безопасности, переданного в рабочий процесс человеком, который его вызвал.

Ответ 5

Я пробую этот код и запускаю, как и bat, contex objet всегда имеет значение null. кто-то знает почему?

protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
    {


        //return base.Execute(executionContext);
        int IdRetorno = -1;



        try {
            SPSecurity.RunWithElevatedPrivileges(delegate
            {
                LogExceptionToWorkflowHistory("Inicio:", executionContext, WorkflowInstanceId);
                using (SPSite sitio = new SPSite(this.__Context.Site.ID))
                {

                    using (SPWeb web = sitio.AllWebs[this.__Context.Site.ID])
                    {


                        SPList sourceList = web.Lists[new Guid(ListId)];
                        LogExceptionToWorkflowHistory(ListId, executionContext, WorkflowInstanceId);
                        SPList destinoList = web.Lists[new Guid(SourceListId)];
                        LogExceptionToWorkflowHistory(SourceListId, executionContext, WorkflowInstanceId);
                        SPListItem sourceItem = sourceList.Items.GetItemById(ListItem);
                        LogExceptionToWorkflowHistory(ListItem.ToString(), executionContext, WorkflowInstanceId);

                        SPListItem destinoItem = destinoList.Items.Add();
                        CopyFieldValues(sourceItem, destinoItem);
                        destinoItem.SystemUpdate();

                        sourceItem.Delete();
                        IdRetorno = destinoItem.ID;
                    }
                }

            });

        }
        catch (Exception ex) {
            if (!System.Diagnostics.EventLog.SourceExists("MyApp1"))
                System.Diagnostics.EventLog.CreateEventSource(
                   "MyApp1", "Application");

            EventLog EventLog1 = new EventLog();
            EventLog1.Source = "MyApp1";
            EventLog1.WriteEntry(ex.Message,EventLogEntryType.FailureAudit);

            LogExceptionToWorkflowHistory(ex.Message, executionContext, WorkflowInstanceId);
        }


        OutListItemID = IdRetorno;




        return base.Execute(executionContext);

    }

спасибо

Ответ 6

Я не знаю, слишком ли это легко, но я использовал:

objCurrentItem = workflowProperties.Item

чтобы получить элемент в рабочем процессе (список), а затем изменить элементы в списке