SharePoint Custom Workflow action to get a list item as an attachment in another list

Using SharePoint Designer, what if we want to have a create a workflow that gets a list item as an attachment in another list based on the item ID of the item that's created.  This is not possible using OOB actions in SPD.  We can create custom action using Visual studio and then integrate it in SPD workflow.

To achieve this task, we need to follow these steps.

1. Write code that has the dependency properties and code to handle the logic

2. Create .action file that can be integrated in SPD.

3. Add entries in web.config file to add authorizedTypes.

 

1) Write code that has the dependency properties and code to handle the logic ( Sample cs file ) and then deploy the dll.

    1: namespace GetAttachment
    2: {
    3:     public partial class Activity1 : SequenceActivity
    4:     {
    5:         public Activity1()
    6:         {
    7:             InitializeComponent();
    8:         }
    9:  
   10:         #region DependencyProperties
   11:  
   12:  
   13:         public static DependencyProperty ListIdProperty = DependencyProperty.Register("ListId", typeof(string), typeof(Activity1));
   14:  
   15:         [Category("Cross Site Actions"), Browsable(true)]
   16:         [DesignerSerializationVisibility
   17:           (DesignerSerializationVisibility.Visible)]
   18:         public string ListId
   19:         {
   20:             get
   21:             {
   22:                 return ((string)(base.GetValue(Activity1.ListIdProperty)));
   23:             }
   24:             set
   25:             {
   26:                 base.SetValue(Activity1.ListIdProperty, value);
   27:             }
   28:         }
   29:  
   30:         public static DependencyProperty ListItemProperty = DependencyProperty.Register("ListItem", typeof(Int32), typeof(Activity1));
   31:  
   32:         [Category("Cross Site Actions"), Browsable(true)]
   33:         [DesignerSerializationVisibility
   34:           (DesignerSerializationVisibility.Visible)]
   35:         public int ListItem
   36:         {
   37:             get
   38:             {
   39:                 return ((int)(base.GetValue(Activity1.ListItemProperty)));
   40:             }
   41:             set
   42:             {
   43:                 base.SetValue(Activity1.ListItemProperty, value);
   44:             }
   45:         }
   46:  
   47:         public static DependencyProperty DestinationListProperty = DependencyProperty.Register("DestinationList", typeof(string), typeof(Activity1));
   48:  
   49:         [Category("Cross Site Actions"), Browsable(true)]
   50:         [DesignerSerializationVisibility
   51:           (DesignerSerializationVisibility.Visible)]
   52:         public string DestinationList
   53:         {
   54:             get
   55:             {
   56:                 return ((string)(base.GetValue(Activity1.DestinationListProperty)));
   57:             }
   58:             set
   59:             {
   60:                 base.SetValue(Activity1.DestinationListProperty, value);
   61:             }
   62:         }
   63:  
   66:         public static DependencyProperty __ContextProperty = DependencyProperty.Register("__Context",
   67:                                                                                         typeof(WorkflowContext),
   70:                                                                                             ));
   71:         [ValidationOption(ValidationOption.Required)]
   72:         [Browsable(true)]
   73:         [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
   74:         public WorkflowContext __Context
   75:         {
   76:             get { return ((WorkflowContext)(base.GetValue(Activity1.__ContextProperty))); }
   77:             set { base.SetValue(Activity1.__ContextProperty, value); }
   78:         }
   79:  
   80:  
   81:         #endregion
   82:  
   83:         protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
   84:         {
   85:             string str = null;
   86:             using (SPSite oSPSite = new SPSite(__Context.Site.ID))
   87:             {
   88:                 using (SPWeb oSPWeb = oSPSite.RootWeb)
   89:                 {
   90:                     SPList list = oSPWeb.Lists[new Guid(ListId)];
   91:                     SPFile oFile = list.Items.GetItemById(ListItem).File;
   92:  
   93:                     SPList oList = oSPWeb.Lists[new Guid(DestinationList)];
   94:  
   95:                     SPListItemCollection listColl = oList.Items;
   96:                     Guid oguid = new Guid();
   97:                     foreach (SPListItem itm in listColl)
   98:                     {
   99:                         if (itm.Name == ListItem.ToString())
  100:                         {
  101:                             oguid = itm.UniqueId;
  102:                             break;
  103:                         }
  104:  
  105:                     }
  106:                     SPListItem oListItem = oList.Items[oguid];
  107:                     SPAttachmentCollection collAttachments = oListItem.Attachments;
  108:  
  109:                     string strFileName = oFile.Name;
  110:  
  111:                     byte[] binFile = oFile.OpenBinary();
  112:                     collAttachments.Add(strFileName, binFile);
  113:                     oListItem.Update();
  114:  
  115:                 }
  116:             }
  117:             Console.WriteLine(str);
  118:  
  119:             return ActivityExecutionStatus.Closed;
  120:         }
  121:     }
  122: }

2) Create .action file that can be integrated in SPD

    1: <WorkflowInfo>
    2:   <Actions>
    3:     <Action Name="Get item from one list as an attachment"
    4:    ClassName="GetAttachment.Activity1"
    5:    Assembly="GetAttachment, Version=1.0.0.0, Culture=neutral, PublicKeyToken=3893e024533a9d94"
    6:    AppliesTo="all" Category="Cross Site Actions">
    7:       <RuleDesigner
    8:                   Sentence="Get item in %1 as an attachment to the list %2 ">
    9:         <FieldBind Field="ListId,ListItem" Text="this list" Id="1" DesignerType="ChooseDoclibItem" />
   10:         <FieldBind Field="DestinationList" DesignerType="ListNames" Id="2"/>
   11:  
   12:       </RuleDesigner>
   13:       <Parameters>
   14:         <Parameter Name="__Context" Type="Microsoft.SharePoint.WorkflowActions.WorkflowContext" Direction="In" />
   15:         <Parameter Name="ListId" Type="System.String, mscorlib" Direction="In" />
   16:         <Parameter Name="ListItem" Type="System.Int32, mscorlib" Direction="In"  />
   17:         <Parameter Name="DestinationList" Type="System.String, mscorlib" Direction="In" />
   18:       </Parameters>
   19:     </Action>
   20:   </Actions>
   21: </WorkflowInfo>

3) Add entries in web.config file to add authorizedTypes.

    1: <System.Workflow.ComponentModel.WorkflowCompiler>
    2:  
    3:   <authorizedTypes>
    4:     ...
    5:     <authorizedType Assembly="GetAttachment, Version=1.0.0.0, Culture=neutral, PublicKeyToken=3893e024533a9d94" Namespace="GetAttachment" TypeName="*"   Authorized="True" />
    6:   </authorizedTypes>
    7:  
    8: </System.Workflow.ComponentModel.WorkflowCompiler>