Tuesday, September 18, 2012

Sharepoint Custom Workflow Activity


Dear Friends,

           This blog is regarding creating "Sharepoint Custom Workflow Activity" through visual studio 2010. First, lets us have look on what is Custom Workflow Activity, what is need to create custom workflow activity?

          When creating workflow, Sharepoint designer supports out-of-box actions which can be easily used. Examples are Sending email, Creating item in List of same site, Log to history list, etc. Below are set of actions provided in Sharepoint designer:


Workflow Actions Out-of-box
          SharePoint Designer supports only a subset of the workflow activities available from the workflow foundation. The two most notable workflow activities that SharePoint does not support are the WhileActivity, which is responsible for looping, and the ReplicatorActivity, which is responsible for iterating through a collection. Other activities, though supported, have limited functionality. For instance, the LogToHistoryActivity, which is used to log messages to the Workflow History list, cannot write to the
Other Data field; therefore, messages from a SharePoint Designer–created workflow sent to the Workflow History list are capped at 256 characters. 


           If the limitations of SharePoint Designer are too restrictive, Visual Studio is the answer. With Visual Studio, you have complete access to the capabilities of the SharePoint Workflow host and workflow runtime. The designer in Visual Studio allows for looping and iteration—the two key reasons why most solutions require a Visual Studio workflow. 

           We need to go for creating Sharepoint Custom Workflow activity when Sharepoint designer does not support out-of-box inbuilt actions for workflow. We had requirement to add/create new item in sub site's list when workflow is triggered. Sharepoint designer workflow actions support adding item in same site list but when it comes to adding item in sub site list it doesn't support, so we need to create Sharepoint Custom Workflow activity. 

   Let's see how can we create Custom Workflow Activity:

  1.    Create a new project, select “Empty SharePoint Project” as the template.
  2. Creating Empty Sharepoint Project

    2. Give the project a cool name and click “OK.”
    3.  Select “Deploy as farm solution” in the wizard window.

    Sharepoint Deployment as Farm Solution

    4.   Add a reference to “Microsoft.SharePoint.WorkflowActions” from the .NET tab in the Add Reference dialog. 
     Add a reference to “System.Workflow.Activities”, “System.Workflow.ComponentModel” and “System.Workflow.Runtime” under “Browse” in the folder “Program Files (x86) Reference AssembliesMicrosoftFrameworkv3.0“

    Sharepoint Adding Reference


Once the project is configured, we will create the activity code as shown below:


Creating the Activity Code

  1. You now have a SharePoint solution with the proper references set so that you can write an Activity. It is time to add the class and the first bit of code.
  2. Add a new empty Class file to the project.                                                               In my case I given Class Name is “CustomSubsSiteAction” and that class Inherit with “Activity” Class.
Sharepoint Creating Custom Activity



   In order to allow properties to be passed in from SharePoint designer, you have to set up Dependency Properties.

2. Add a Property and Dependency Property for values that will come in from the Workflow. Below is code: 



public static DependencyProperty DepartMentsProperty = DependencyProperty.Register("DepartMents", typeof(string), typeof(CustomSubsSiteAction));
        [Category("Cross-Site Actions"), Browsable(true)]
        [DesignerSerializationVisibility
          (DesignerSerializationVisibility.Visible)]
        public string DepartMents
        {
            get
            {
                return Convert.ToString(base.GetValue(DepartMentsProperty));
            }
            set
            {
                base.SetValue(DepartMentsProperty, value);
            }
        }
 

When your activity starts, the Execute method is fired. This is where you will do the work in the Activity. So when can override Execute Method and Perform ours Operation.


protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
        {
             // do stuff here.
            return ActivityExecutionStatus.Closed;
        }



But If we want to Access Current Item Like: List ID, List Item, Current Web than add Dependency Property for that. Access current site Context then Register Property as shown in code below:

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

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

  Same as Current List Item’s List ID:


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

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


For Current ListItem’s ID:

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

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

Also,Register Workflow Activationproperties for Action.

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



        [ValidationOption(ValidationOption.Required)]

        public Microsoft.SharePoint.Workflow.SPWorkflowActivationProperties __ActivationProperties

        {

            get

            {

                return (Microsoft.SharePoint.Workflow.SPWorkflowActivationProperties)base.GetValue(CrossSubSiteAction.__ActivationPropertiesProperty);

            }

            set

            {

                base.SetValue(CrossSubSiteAction.__ActivationPropertiesProperty, value);

            }


        }


Override Execute Method & have custom action code as shown below:


Sharepoint - Override Execute method of Action














 In order for SharePoint designer to know about the Activity, we have to add a special XML file to the Workflow folder in the SharePoint hive.


    1. Right-click on the Project and select Add -> SharePoint Mapped Folder…”

Adding Action to Sharepoint
                           
                   From the folder list, select “TEMPLATE/1033/Workflow“

Sharepoint Mapped Folder


In the Solution Explorer, right-click on the new Workflow folder and add an XML file (Add -> New Item -> DataXML File). And File name and file extension Must be “.actions”

 


Custom Actions XML
 Open CrossSiteAction.actions File and Add RuleDesigner,Parameter


Action Name :  Name="Access Cross Subs-Sites List"

Action showing In category  :  Category="Cross Sub-Site List"

In my case .actions file is



xml version="1.0" encoding="utf-8" ?>

<WorkflowInfo>

  <Actions>

    <Action Name="Access Cross Subs-Sites List"

    ClassName="CustomSubsSiteAction.CustomSubsSiteAction"

    Assembly="CustomSubsSiteAction, Version=1.0.0.0, Culture=neutral, PublicKeyToken=7341b1706fa0e582"

   AppliesTo="all" Category="Cross Sub-Site List">

      <RuleDesigner Sentence="Add Current-Listitem to DepartMentName = %1 Task Listitem">       

        <FieldBind Field="DepartMents" DesignerType="TextArea" Id="1" />    

      </RuleDesigner>

      <Parameters>       

        <Parameter Name="__Context" Type="Microsoft.SharePoint.WorkflowActions.WorkflowContext" Direction="In" />

        <Parameter Name="__ListId" Type="System.String, mscorlib" Direction="In" />

        <Parameter Name="__ItemID" Type="System.Int32, mscorlib" Direction="In" />

 <Parameter Name="DepartMents" Type="System.String, mscorlib"  Direction="In" /> 
<Parameter Name="__ActivationPropertiesType="Microsoft.SharePoint.Workflow.SPWorkflowActivationProperties, Microsoft.SharePoint" Direction="Out" />
      </Parameters>
    </Action>
  </Actions>
</WorkflowInfo>


Deploying & Register your Namespace for Authorization 

Deploy the solution & to register Custom Activites to Webapplication's Web.Config File

between tab


Web config




Than Restart IIS.

Open run and just write IISreset and Ok.

Now Open Sharepoint Designer 2010 & Go to workflow

Sharepoint Custom workflow Action

Please let me know if anyone has any queries.


Thanks & Regards, 

Paras Sanghani

Source Code