代码之家  ›  专栏  ›  技术社区  ›  user656

如何获取工作流活动(SharePoint)中的上下文项

  •  11
  • user656  · 技术社区  · 15 年前

    我正在为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例程对我来说太糟糕了。

    也许还有另一个只提供代码的解决方案来获取工作流活动中的上下文项?

    6 回复  |  直到 11 年前
        1
  •  18
  •   Kit Menke    15 年前

    答案是几个步骤:

    1. 将属性添加到自定义活动.cs
    2. 链接.actions文件中的属性(以便spd知道如何映射到属性)
    3. 使用代码中的属性

    步骤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文件中,将这些属性的映射添加到块中(注意u listid、u listem、u context和u 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
  •  3
  •   David Clarke    11 年前

    我不确定这是否是2010 API中的一个更改,但是uuContext属性提供了所有必要的部分,包括列表和项。下面的示例包括@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
  •  2
  •   davek    15 年前

    Kit Menke的回答非常全面,涵盖了你所需要的一切:我只想补充以下内容…

    如果你这样做:

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

    而不是这个:

    SPWeb web = __Context.Web;
    ...
    

    然后,您将不受触发工作流的人传递给工作流的安全上下文的约束。

        4
  •  1
  •   user4531    15 年前

    看看 SPWorkflowActivationProperties.Item Property

    获取正在其上运行工作流实例的列表项。

        5
  •  1
  •   Pablo    14 年前

    我尝试了这段代码并运行它,因为Contex对象总是空的。有人知道为什么?

    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
  •  1
  •   GMD    13 年前

    我不知道这是否太简单,但我用了:

    objCurrentItem = workflowProperties.Item
    

    获取工作流(列表)中的项目,然后更改列表中的项目