Skip to main content

How to add a custom visual studio workflow to SharePoint designer

This article explains step by step guide line to add a custom visual studio work flow to the SharePoint designer. In here I'm using   VS 2010 and SharePoint 2010.

  • Create  a Empty Sequence Work Flow project.

image

then select .Net Framework 3.5 and select the Sequential Workflow Project.

image 

in this sample we are going to add custom string functionality to the SharePoint designer. after creating the project you will get a blank activity as follows.

image

then delete that activity and add the Activity item to the project as above. I named that as subStringAfterText.cs

image

after that you will get a blank Sequence Activity.

Add references to the Project

After that you need to add Microsoft.SharePoint.dll and Microsoft.SharePoint.WorkflowActions.dll to the project. those dlls can be found in the following paths.

  • C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\ISAPI\Microsoft.SharePoint.dll
  • C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\ISAPI\Microsoft.SharePoint.WorkflowActions.dll

Cording

My task to develop a simple string function it will return the text after the search text. This is so simple but you can use this method to develop any Custom SPD workflows. 

   1: using System;
   2: using System.ComponentModel;
   3: using System.ComponentModel.Design;
   4: using System.Collections;
   5: using System.Linq;
   6: using System.Workflow.ComponentModel;
   7: using System.Workflow.ComponentModel.Design;
   8: using System.Workflow.ComponentModel.Compiler;
   9: using System.Workflow.ComponentModel.Serialization;
  10: using System.Workflow.Runtime;
  11: using System.Workflow.Activities;
  12: using System.Workflow.Activities.Rules;
  13: using System.Diagnostics;
  14: using Microsoft.SharePoint;
  15: using Microsoft.SharePoint.WorkflowActions;
  16: using Microsoft.SharePoint.Workflow;
  17:  
  18: namespace getSubStringAfter
  19: {
  20: public partial class subStringAfterText : SequenceActivity
  21: {
  22: // Declare event log
  23: private EventLog eventLog;
  24:  
  25:  
  26: // Declare dependency propoerties to get and set values to the activity
  27:  
  28: public static DependencyProperty SourceStringProperty = System.Workflow.ComponentModel.DependencyProperty.Register("SourceString", typeof(string), typeof(subStringAfterText));
  29: public static DependencyProperty SearchStringProperty = System.Workflow.ComponentModel.DependencyProperty.Register("SearchString", typeof(string), typeof(subStringAfterText));
  30: public static DependencyProperty FoundStringProperty = System.Workflow.ComponentModel.DependencyProperty.Register("FoundString", typeof(string), typeof(subStringAfterText));
  31: // Specify validations to validate inputs
  32: [Description("")]
  33: [ValidationOption(ValidationOption.Required)]
  34: [Browsable(true)]
  35: [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
  36: public string SourceString
  37: {
  38: get
  39: {
  40: return (string)base.GetValue(SourceStringProperty);
  41: }
  42: set
  43: {
  44: base.SetValue(SourceStringProperty, value);
  45: }
  46: }
  47:  
  48: [Description("")]
  49: [ValidationOption(ValidationOption.Required)]
  50: [Browsable(true)]
  51: [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
  52: public string SearchString
  53: {
  54: get
  55: {
  56: return (string)base.GetValue(SearchStringProperty);
  57: }
  58: set
  59: {
  60: base.SetValue(SearchStringProperty, value);
  61: }
  62: }
  63:  
  64: [Browsable(true)]
  65: [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
  66: public string FoundString
  67: {
  68: get
  69: {
  70: return (string)base.GetValue(FoundStringProperty);
  71: }
  72: set
  73: {
  74: base.SetValue(FoundStringProperty, value);
  75: }
  76: }
  77:  
  78: //The SharePoint workflow properties activation object
  79: public static DependencyProperty __ActivationPropertiesProperty = DependencyProperty.Register("__ActivationProperties", typeof(SPWorkflowActivationProperties), typeof(subStringAfterText));
  80:  
  81: // Using a DependencyProperty as the backing store for WorkflowInstanceIdProperty. This enables animation, styling, binding, etc...
  82: public static DependencyProperty WorkflowInstanceIdVariableProperty = DependencyProperty.Register("WorkflowInstanceIdVariable", typeof(string), typeof(subStringAfterText));
  83:  
  84: // Using a DependencyProperty as the backing store for WorkflowInstanceIdProperty. This enables animation, styling, binding, etc...
  85: public static DependencyProperty __ContextProperty = DependencyProperty.Register("__Context", typeof(WorkflowContext), typeof(subStringAfterText));
  86:  
  87: [Description("The WorkflowInstanceId for the workflow.")]
  88: [ValidationOption(ValidationOption.Required)]
  89: public string WorkflowInstanceIdVariable
  90: {
  91: get { return (string)(base.GetValue(WorkflowInstanceIdVariableProperty)); }
  92: set { base.SetValue(WorkflowInstanceIdVariableProperty, value); }
  93: }
  94:  
  95: [Description("The Workflow Properties")]
  96: [ValidationOption(ValidationOption.Required)]
  97: public SPWorkflowActivationProperties __ActivationProperties
  98: {
  99: get { return (SPWorkflowActivationProperties)(base.GetValue(__ActivationPropertiesProperty)); }
 100: set { base.SetValue(__ActivationPropertiesProperty, value); }
 101: }
 102:  
 103: [Description("The Workflow Context object")]
 104: [ValidationOption(ValidationOption.Optional)]
 105: [Browsable(false)]
 106: [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
 107: public WorkflowContext __Context
 108: {
 109: get
 110: {
 111: return (WorkflowContext)(base.GetValue(__ContextProperty));
 112: }
 113:  
 114: set
 115: {
 116: base.SetValue(__ContextProperty, value);
 117: }
 118: }
 119:  
 120: // Override the activity execution
 121: protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
 122: { 
 123: //Set up the Event Logging object 
 124: eventLog = new EventLog("Workflow");
 125: eventLog.Source = "SharePoint Workflow";
 126:  
 127: try
 128: {
 129: // Your Method
 130: getTheString();
 131: }
 132: finally
 133: {
 134: //Dispose of the Event Logging object 
 135: eventLog.Dispose();
 136: }
 137:  
 138: //Indicate the activity has closed 
 139: return ActivityExecutionStatus.Closed;
 140: }
 141:  
 142:  
 143: private void getTheString()
 144: {
 145: this.FoundString = SourceString.Substring(SourceString.IndexOf(SearchString) + SearchString.Length -1);
 146: }
 147:  
 148: }
 149: }


Code Explanation

dependency properties are used to exchange data from work flow instance. therefore following properties needed to exchange primary data.



//The SharePoint workflow properties activation object
// Using a DependencyProperty as the backing store for WorkflowInstanceIdProperty. This enables animation, styling, binding, etc...



public static DependencyProperty __ActivationPropertiesProperty = DependencyProperty.Register("__ActivationProperties", typeof(SPWorkflowActivationProperties), typeof(subStringAfterText));


public static DependencyProperty WorkflowInstanceIdVariableProperty = DependencyProperty.Register("WorkflowInstanceIdVariable", typeof(string), typeof(subStringAfterText));

// Using a DependencyProperty as the backing store for WorkflowInstanceIdProperty. This enables animation, styling, binding, etc...
public static DependencyProperty __ContextProperty = DependencyProperty.Register("__Context", typeof(WorkflowContext), typeof(subStringAfterText));

//These properties should have getter setter methods. attributes define the visibility , validation and etc..
Ex :-



[Description("The WorkflowInstanceId for the workflow.")]
[ValidationOption(ValidationOption.Required)]
public string WorkflowInstanceIdVariable
{
get { return (string)(base.GetValue(WorkflowInstanceIdVariableProperty)); }
set { base.SetValue(WorkflowInstanceIdVariableProperty, value); }
}



// Then you need your own properties and getters setters



public staticDependencyProperty SourceStringProperty = System.Workflow.ComponentModel.DependencyProperty.Register("SourceString",typeof(string),typeof(subStringAfterText));



public static DependencyPropertySearchStringProperty = System.Workflow.ComponentModel.DependencyProperty.Register("SearchString",typeof(string),typeof(subStringAfterText));



public static DependencyPropertyFoundStringProperty = System.Workflow.ComponentModel.DependencyProperty.Register("FoundString",typeof(string),typeof(subStringAfterText));

// Override the activity execution
protected overrideActivityExecutionStatus Execute(ActivityExecutionContext executionContext)

           //Set up the Event Logging object
           
eventLog =new EventLog("Workflow");
            eventLog.Source ="SharePoint Workflow";

            try
           
{
               // Your Method
               
getTheString();
            }
           finally
           
{
               //Dispose of the Event Logging object
               
eventLog.Dispose();
            }

            //Indicate the activity has closed
           
returnActivityExecutionStatus.Closed;
}


Sign the application.



After that you should sing the application using a strong key. Thus you can go to project properties and sing the application as follows.



image



image 



Build your application. and place the assembly to the GAC. In here there are are two GAC maintaining with framework 4.0





  • C:\Windows\Microsoft.NET\assembly

  • C:\Windows\assembly



To work the assembly this should be registered under “C:\Windows\assembly” if you use Target Framework as 4.0 then it will register the assembly in C:\Windows\Microsoft.NET\assembly. Therefore use target framework as 3.5 



Register Assembly Under “C:\Windows\assembly



image



Make sure the target framework is 3.5 of the project. if so it will get add to the location “C:\Windows\assembly



For that





  • Go to the Visual Studio Command Prompt as administrator

  • Go to your bin/debug folder (place where the dll is build)

  • Type gacutil /i getSubStringAfter.dll


if you did it correctly you can see your assembly in the GAC. to view the GAC you can type “C:\Windows\assembly” in the Run Window.image Creating work flow template actions file.

Then you need to create .ACTIONS file. This is the file that used by the SPD to get the workflow information.  Therefore create a file named getSubStringAfter.ACTIONS and put the following code there. you need to put correct public key token, namespace and class name. 









image 





   1: <?xml version="1.0" encoding="utf-8"?>
   2: <WorkflowInfo Language="en-us" >
   3:   <Actions Sequential="then" Parallel="and">
   4:     <Action Name="get the substring after the text"
   5:         ClassName="getSubStringAfter.subStringAfterText"
   6:         Assembly="getSubStringAfter, Version=1.0.0.0, Culture=neutral, PublicKeyToken=d98a44afbf8ccb86"
   7:         AppliesTo="all"
   8:         Category="Custom String Actions">
   9:       <RuleDesigner Sentence="Search %1 from %2 and store in %3.">
  10:         <FieldBind Field="SearchString" Text="this text" DesignerType="stringbuilder" Id="1"/>
  11:         <FieldBind Field="SourceString" Text="this address" Id="2" DesignerType="stringbuilder" />
  12:         <FieldBind Field="FoundString" Text="variable" Id="3" DesignerType="ParameterNames" />
  13:       </RuleDesigner>
  14:       <Parameters>
  15:         <Parameter Name="SearchString" Type="System.String, mscorlib" Direction="In" />
  16:         <Parameter Name="SourceString" Type="System.String, mscorlib" Direction="In" />
  17:         <Parameter Name="FoundString" Type="System.String, mscorlib" Direction="Out" />
  18:       </Parameters>
  19:     </Action>
  20:   </Actions>
  21: </WorkflowInfo>


then copy this file and put in to the following SharePoint server location
C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\TEMPLATE\1033\Workflow



Modify the web Config



Then you need to modify the web.config of your site. you need to put SafeControl and authorizedType in here also please make sure public key token , namespace , version and class is correct other wise it will not work for an example it may not show in the SPD , or it will not get added to the work flow step though it showed in the SPD.



image



<authorizedTypeAssembly="getSubStringAfter, Version=1.0.0.0, Culture=neutral, PublicKeyToken=d98a44afbf8ccb86"Namespace="getSubStringAfter"TypeName="subStringAfterText"Authorized="True"/>
<SafeControlAssembly="getSubStringAfter, Version=1.0.0.0, Culture=neutral, PublicKeyToken=d98a44afbf8ccb86"Namespace="getSubStringAfter"TypeName="*"Safe="True"/>



Finally ..





  • reset the IIS

  • Now open the SPDimage image








I took nearly one week to do figure this out. anyway finally i got a solution. :-)  

Comments

Popular posts from this blog

How to Customize New Item Form to take parameters from Query String in the SharePoint 2010

In here I'm going to explain how to customize the SharePoint Item From to take parameters from Query String and set them as default values using SharePoint designer. Using this you can open a new Item From by providing parameters as query string. For an example you can customize one item Display form and taking query String Parameter from that and view New Item view for another list by providing default values using the Query String.     Steps Open the SharePoint designer and go to list and libraries and open the list that you want. Click the New and create a New Insert View by providing the name of the view.   Then created one will come to the list. then click and open the view. Then default New Item Screen will be loaded as follows. Then Delete the default list view and make that empty. You can delete the controls by selecting the area in the design view, If it fully cleared you can view the following message from the designer. Then go to SharePoint...

How to Link Two List and Create a combine view in the SharePoint 2010

In this way you can join multiple list together and can create a combine view. for an example assume that you are managing a list for some events. And also you are having a participants in separate list. Thus you want to join the two list and create a composite view. SharePoint 2010 allows you to create this kind of view using  Linked Data Source. in this approach you can create your own custom list in the SharePoint. How to Create a Linked Data source Go to SharePoint designer and  go to the link called data sources. And Click the Linked Data Source button in the ribbon. Then SharePoint designer will prompt following kind of a dialog. In there add two list, that you wan to linked together. I'm adding airline schedule and booking list. those are the two list that i wan to merge. then click next. And it will guide you another screen. it will ask you to select either Merge Merge use to combine list which are having same columns definition. for and example we can s...

Complete guide to Install SharePoint in a Three Server Farm using AutpSPInstaller

This article will be divided to three sections Setting up the Environment and Service Accounts Getting Ready with AutoSPInstaller Online Configuring the XML using Online Editor and Installation Setting up the Environment and Service Accounts AutoSPInstaller Online is one of a great project that facilitate Automated SharePoint installation including Sharepoint 2010, 2013 and 2016. Auto SP Installer provides a powerful way to deploy and configure a single-server development environment to multiple-server SharePoint farm. Reference: https://autospinstaller.com/ Before doing anything we will set up the environment for SharePoint three server Farm. Will name these servers as SPWFE - Share Point Front End Server SPAPP - Share Point App server SPDB - DB server Please find the reference for SharePoint minimum requirement and practices from https://docs.microsoft.com/en-us/SharePoint/install/install-sharepoint-server-2016-across-multiple-servers For the the medium segregation, we have to create...