Datapolis Process System SDK

Search:

Contents
:
IndexBookmarkPrint
Home > Activities > Creating Activity Tutorial

Creating Activity Tutorial

 

 

This walkthrough will guide you through creating a custom activity. The assumed functional requirement for an activity created in this walkthrough is to create list.

The input parameters of the activity will be as follows:

  • Parent web that contains a new created list
  • List title
  • List description
  • Template which the list based on
  • The parameter that indicates if the link to the list should be placed into quick launch

The following parameters are returned by the activity:

  • Error status. If everything goes all right, error status returns 0 otherwise the message of an occurred error is returned
  • Return list url. If the list is created, the parameter returns the absolute list url otherwise the empty value is returned

Prerequisites


Before creating a custom activity, be sure you have installed all of the necessary components and Visual Studio templates.

Create an Activity Project

  1. Open a new Visual Studio project (File | New | Project)
  2. Create a new class library project.
  3. Name the project appropriately. In this case it might be Datapolis.WorkBox.Sdk.Samples. Set the other project properties (Location, Solution Name etc.)
  4. Sign the assembly.
  5. Add references to Datapolis.WorkBox.Common and Datapolis.WorkBox.Activities - they should be available in GAC.
  6. Add references to System.Workflow.ComponentModel and Microsoft.SharePoint.
  7. Add a new class by right clicking on the project node in Solution Explorer and select Add | Class.... Name it WBCreateListActivity.cs
  8. Extend WBCreateListActivity class namespace to Datapolis.WorkBox.Sdk.Samples.Activities
  9. Add the resources file. Right click on the project node in Solution Explorer and select Add | New Items... from the project contect menu. Select Resources Files from Templates window. Name the resources file e.g. Datapolis.WorkBox.Sdk.Samples.Activities.resx
  10. Add an xml file. Name it WBCreateListActivity.xml.

Modify Post Built Events

  1. Right click on the project node in Solution Explorer and select Properties. Select Build Events tab. Click on Edit Post-build ... button.
  2. Convert *.resx resource file to *.resource format. Use the .NET Framework 4.5 tool by adding the following script to the Post-build Event Command Line window: ResGen.exe Datapolis.WorkBox.Sdk.Samples.Activities.resx Datapolis.WorkBox.Sdk.Samples.Activities.resources
  3. Copy the generated *.resource file by adding the following script: xcopy *.resources "%CommonProgramW6432%\microsoft shared\web server extensions\15\WorkBox\Activities\" /y
    Note
    If you encounter errors when building your project please see "Environment Variables" section in Visual Studio Integration. Errors are probably caused by unspecified path to building tools.

Prepare xml files


Define the parameters in markup. Open WBCreateListActivity.xml and insert definition of the activity parameters.

 

  <Activity Name="WBCreateListActivity" IsCallExternalActivity="False"
    NamespaceName="clr-namespace:Datapolis.WorkBox.Sdk.Samples.Activities;Assembly=Datapolis.WorkBox.Sdk.Samples, Version=1.0.0.0, Culture=neutral, PublicKeyToken=0a68baededa28155"
    Title="$Resources:Datapolis.WorkBox.Sdk.Samples.Activities,WBCreateListActivity_ActivityTitle;"
    Description="$Resources:Datapolis.WorkBox.Sdk.Samples.Activities,WBCreateListActivity_ActivityDescription;" >
    <Parameters>
      <Parameter Name="ParentWebUrl" Required="True" Type="String" DataType="OneLookup"
        ParametersToEraseAfterChange="ListTemplate"
        AllowChildrenTypes="Current SharePoint SiteCollection Site WebCollection Web" SelectableTypes="Web"
        Title="$Resources:Datapolis.WorkBox.Sdk.Samples.Activities,WBCreateListActivity_ParentWebUrl_Title;"
        Description="$Resources:Datapolis.WorkBox.Sdk.Samples.Activities,WBCreateListActivity_ParentWebUrl_Description;"/>
      <Parameter Name="ListTitle" Type="String" Required="True"
        Title="$Resources:Datapolis.WorkBox.Sdk.Samples.Activities,WBCreateListActivity_ListTitle_Title;"
        Description="$Resources:Datapolis.WorkBox.Sdk.Samples.Activities,WBCreateListActivity_ListTitle_Description;"/>
      <Parameter Name="ListDescription" StringLines="4" Type="String"
        Title="$Resources:Datapolis.WorkBox.Sdk.Samples.Activities,WBCreateListActivity_ListDescription_Title;"
        Description="$Resources:Datapolis.WorkBox.Sdk.Samples.Activities,WBCreateListActivity_ListDescription_Description;"/>
      <Parameter Name="ListTemplate" DataType="OneLookup" Type="String"
        RootPath="@ParentWebUrl/WebParameterCollection/ListTemplateCollection/"
        AllowChildrenTypes="ListTemplate" SelectableTypes="ListTemplate" Required="True"
        Title="$Resources:Datapolis.WorkBox.Sdk.Samples.Activities,WBCreateListActivity_ListTemplate_Title;"
        Description="$Resources:Datapolis.WorkBox.Sdk.Samples.Activities,WBCreateListActivity_ListTemplate_Description;" />
      <Parameter Name="IsQuickLuanch" Value="True" Type="Bool"
        Title="$Resources:Datapolis.WorkBox.Sdk.Samples.Activities,WBCreateListActivity_IsQuickLuanch_Title;"
        Description="$Resources:Datapolis.WorkBox.Sdk.Samples.Activities,WBCreateListActivity_IsQuickLuanch_Description;">
        <ValueOptions>
          <ValueOption Title="$Resources:Datapolis.WorkBox.Sdk.Samples.Activities,WBCreateListActivity_IsQuickLuanch_True;" Value="True" />
          <ValueOption Title="$Resources:Datapolis.WorkBox.Sdk.Samples.Activities,WBCreateListActivity_IsQuickLuanch_False;" Value="False" />
        </ValueOptions>
      </Parameter>
      <Parameter Name="ErrorStatus" Type="String" Direction="Output"
        Title="$Resources:Datapolis.WorkBox.Sdk.Samples.Activities,WBCreateListActivity_ErrorStatus_Title;"
        Description="$Resources:Datapolis.WorkBox.Sdk.Samples.Activities,WBCreateListActivity_ErrorStatus_Description;" />
      <Parameter Name="ReturnListUrl"  Type="String" Direction="Output"
        Title="$Resources:Datapolis.WorkBox.Sdk.Samples.Activities,WBCreateListActivity_ReturnListUrl_Title;"
        Description="$Resources:Datapolis.WorkBox.Sdk.Samples.Activities,WBCreateListActivity_ReturnListUrl_Description;"/>
    </Parameters>
    <Graph></Graph>
  </Activity>
</Activities>

 

Note
The parametr: IsQuickLuanch is implemented as the enum list with two items: Yes/No. When the node: ValueOptions is removed then the enum list is changed to the checkbox in Datapolis Process System Designer.

Set the activity translation.


Right click on the resource file (Datapolis.WorkBox.Sdk.Samples.Activities.resx) and select Open With... context menu. Pick XML Editor and click OK button. Just before the node: </root> insert the following xml translation:

 

<data name="WBCreateListActivity_ActivityDescription" xml:space="preserve">
  <value>Add a new list or library to the selected web</value>
</data>
<data name="WBCreateListActivity_ActivityTitle" xml:space="preserve">
  <value>Code Sample: Create List</value>
</data>
<data name="WBCreateListActivity_ErrorStatus_Description" xml:space="preserve">
  <value>When a list is created successfully the error status returns 0 otherwise an error message is returned</value>
</data>
<data name="WBCreateListActivity_ErrorStatus_Title" xml:space="preserve">
  <value>Error Status</value>
</data>
<data name="WBCreateListActivity_IsQuickLuanch_Description" xml:space="preserve">
  <value>Specify whether a link to this document library appears in the Quick Launch.</value>
</data>
<data name="WBCreateListActivity_IsQuickLuanch_False" xml:space="preserve">
  <value>No</value>
</data>
<data name="WBCreateListActivity_IsQuickLuanch_Title" xml:space="preserve">
  <value>Navigation</value>
</data>
<data name="WBCreateListActivity_IsQuickLuanch_True" xml:space="preserve">
  <value>Yes</value>
</data>
<data name="WBCreateListActivity_ListDescription_Description" xml:space="preserve">
  <value>Type descriptive text that will help site visitors use this document library or list.</value>
</data>
<data name="WBCreateListActivity_ListDescription_Title" xml:space="preserve">
  <value>Description</value>
</data>
<data name="WBCreateListActivity_ListTemplate_Description" xml:space="preserve">
  <value>Type a template for example: Events</value>
</data>
<data name="WBCreateListActivity_ListTemplate_Title" xml:space="preserve">
  <value>Template</value>
</data>
<data name="WBCreateListActivity_ListTitle_Description" xml:space="preserve">
  <value>Type a new name as you want it to appear in headings and links throughout the site</value>
</data>
<data name="WBCreateListActivity_ListTitle_Title" xml:space="preserve">
  <value>Name</value>
</data>
<data name="WBCreateListActivity_ParentWebUrl_Description" xml:space="preserve">
  <value>Select a parent web</value>
</data>
<data name="WBCreateListActivity_ParentWebUrl_Title" xml:space="preserve">
  <value>Parent Web</value>
</data>
<data name="WBCreateListActivity_ReturnListUrl_Description" xml:space="preserve">
  <value>The list default view url. When the value is empty see Error Status</value>
</data>
<data name="WBCreateListActivity_ReturnListUrl_Title" xml:space="preserve">
  <value>List Url</value>
</data>

 

Develop code


Register the parameters defined in markup. Right click on the activity code behind WBCreateListActivity.cs in Solution Explorer and select View Code. Insert the following code into the Register Parameters region:

 

private static readonly Type createListType = typeof(WBCreateListActivity);
public static DependencyProperty ParentWebUrlProperty = DependencyProperty.Register("ParentWebUrl", typeof(string), createListType);
public static DependencyProperty ListTitleProperty = DependencyProperty.Register("ListTitle", typeof(string), createListType);
public static DependencyProperty ListDescriptionProperty = DependencyProperty.Register("ListDescription", typeof(string), createListType);
public static DependencyProperty ListTemplateProperty = DependencyProperty.Register("ListTemplate", typeof(string), createListType);
public static DependencyProperty IsQuickLuanchProperty = DependencyProperty.Register("IsQuickLuanch", typeof(bool?), createListType);
public static DependencyProperty ErrorStatusProperty = DependencyProperty.Register("ErrorStatus", typeof(string), createListType);
public static DependencyProperty ReturnListUrlProperty = DependencyProperty.Register("ReturnListUrl", typeof(string), createListType);

 

When the parameters have been registered the next step is to issue them as properties. Copy and paste the code below into the file WBCreateListActivity.cs in the Properties region:

 

[ValidationOption(ValidationOption.Required)]
public string ParentWebUrl
{
    get { return (string)base.GetValue(ParentWebUrlProperty); }
    set { base.SetValue(ParentWebUrlProperty, value); }
}
 
[ValidationOption(ValidationOption.Required)]
public string ListTitle
{
    get { return (string)base.GetValue(ListTitleProperty); }
    set { base.SetValue(ListTitleProperty, value); }
}
 
[ValidationOption(ValidationOption.Optional)]
public string ListDescription
{
    get { return (string)base.GetValue(ListDescriptionProperty); }
    set { base.SetValue(ListDescriptionProperty, value); }
}
 
[ValidationOption(ValidationOption.Required)]
public string ListTemplate
{
    get { return (string)base.GetValue(ListTemplateProperty); }
    set { base.SetValue(ListTemplateProperty, value); }
}
 
[ValidationOption(ValidationOption.Optional)]
public bool IsQuickLuanch
{
    get
    {
        bool? quickLaunch = (bool?)base.GetValue(IsQuickLuanchProperty);
        if (quickLaunch != null && quickLaunch.HasValue)
            return quickLaunch.Value;
        return false;
    }
    set { base.SetValue(IsQuickLuanchProperty, value); }
}
 
[ValidationOption(ValidationOption.Optional)]
public string ErrorStatus
{
    get { return (string)base.GetValue(ErrorStatusProperty); }
    set { base.SetValue(ErrorStatusProperty, value); }
}
[ValidationOption(ValidationOption.Optional)]
public string ReturnListUrl
{
    get { return (string)base.GetValue(ReturnListUrlProperty); }
    set { base.SetValue(ReturnListUrlProperty, value); }
}
 
public SPListTemplate.QuickLaunchOptions QuickLaunch
{
    get
    {
        if (this.IsQuickLuanch)
            return SPListTemplate.QuickLaunchOptions.On;
        return SPListTemplate.QuickLaunchOptions.Off;
    }
}

 

Now, create function CreateList that is responsible for business logic of this activity

Note
This example contains the trace logging functionality that allows of tracing each aspect related to the activity development. For more details about logging see Trace Logging

When a list is created successfully the absolute list URL is returned as the output ReturnListUrl parameter and the activity error status is set to 0.

 

private void CreateList()
{
    SPSecurity.RunWithElevatedPrivileges(delegate
    {
        using (var site = new SPSite(this.ParentWebUrl))
        {
            using (var parentWeb = site.OpenWeb())
            {
                this.Logger.Medium("Parameters: ParentWebUrl: '{0}',  ListTitle: '{1}',  ListDescription: '{2}', ListTemplate: '{3}', IsQuickLuanch: '{4}'",
                this.ParentWebUrl, this.ListTitle, this.ListDescription, this.ListTemplate, this.IsQuickLuanch);
 
                var spListTemplate = WBWebHelper.GetListTemplate(parentWeb, this.ListTemplate);
                if (spListTemplate == null)
                {
                    var msg = string.Format("The list that title should be: '{0}' cannot be created as the template list (InternalName: '{1}') has not be found, ParentWebUrl: '{2}'",
                    this.ListTitle, this.ListTemplate, this.ParentWebUrl);
                    this.ErrorStatus = msg;
                    this.ReturnListUrl = msg;
                    this.Logger.Unexpected(msg);
                    return;
                }
 
                var listId = parentWeb.Lists.Add(this.ListTitle, this.ListDescription, spListTemplate);
                if (listId == Guid.Empty)
                {
                    var msg = string.Format("The list that title should be: '{0}' could not be created as the list Id is empty, ParentWebUrl: '{1}', ListTemplate: '{2}'",
                    this.ListTitle, this.ParentWebUrl, this.ListTemplate);
                    this.ErrorStatus = msg;
                    this.ReturnListUrl = msg;
                    this.Logger.Unexpected(msg);
                    return;
                }
                else
                {
                    var list = parentWeb.Lists[listId];
                    list.OnQuickLaunch = this.IsQuickLuanch;
                    list.Update();
                    this.ReturnListUrl = parentWeb.Url + list.DefaultViewUrl;
                    this.ErrorStatus = "0";
                    this.Logger.Medium("The list that title is: '{0}' has been created successfully, ReturnListUrl: '{1}', ErrorStatus: '{2}'", this.ListTitle, this.ReturnListUrl, this.ErrorStatus);
                }
            }
        }
    });
}

 

Override ExecuteBody method by invoking the above CreateList function:

 

Note
When the list is not created for some reasons the output parameters are set appropriately and the workflow is not stopped by a potential exception.

protected override ActivityExecutionStatus ExecuteBody(ActivityExecutionContext c)
{
    this.Logger.Verbose("Starting ExecuteBody function of the create list activity");
    try
    {
        this.CreateList();
    }
    catch (Exception e)
    {
        this.ErrorStatus = e.Message;
        this.ReturnListUrl = string.Empty;
        this.Logger.Unexpected("An error occured during creation a new list", e);
    }
 
    this.Logger.Verbose("Ending ExecuteBody function of the create list activity");
    return ActivityExecutionStatus.Closed;
}

 

Build the project

 

Modify web.config


  1. Browse to the web.config file of web application where the activity will be used. By default it's in \\Inetpub\wwwroot\wss\VirtualDirectories\Port_Number

  2. Open the the web.config file and find the section: <System.Workflow.ComponentModel.WorkflowCompiler><authorizedTypes><targetFx version="v4.0">

  3. Insert the following node:

    <authorizedType Assembly="Datapolis.WorkBox.Sdk.Samples, Version=1.0.0.0, Culture=neutral, PublicKeyToken=0a68baededa28155" Namespace="Datapolis.WorkBox.Sdk.Samples.Activities" TypeName="*" Authorized="True" />

  4. Save and close web.config

 

Next Step


Optionally, after reading this walkthrough you can see the same activity code attached in SDK Samples in Download section.

‚Äč