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>