Wait? Why would you want to do this? I’ll tell you why, because writing the whole workflow in Visual Studio is lame. You’re better off writing an activity and letting some SharePoint admin put together and manage the workflows in SharePoint Designer.

Seriously, I can’t stress this enough. Write as little code as necessary in SharePoint, and let the built in tools and features do the rest of the work.

Creating the Solution

Ok, this is a little weird, but there isn’t a built in template for writing Activities. It almost seems like they didn’t expect people to be using them. Really, there is nothing built in for this. So, you have to do it all by hand.

  1. Create a new project, select “Empty SharePoint Project” as the template.
  2. Give the project a cool name and click “OK.”
  3. Select “Deploy as farm solution” in the wizard window.

     

  4. Click “Finish.”
  5. Add a reference to “Microsoft.SharePoint.WorkflowActions” from the .NET tab in the Add Reference dialog.
  6. 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
  7. Your references should look like this now:

     

Creating the Activity code

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.

  1. Add a new empty Class file to the project.
  2. Add the following using statements and inherit from Activity.


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

  1. Add a Property and Dependency Property for values that will come in from the Workflow.

     

When your activity starts, the Execute method is fired. This is where you will do the work in the Activity.

  1. Add an override for Execute to the class.

     

Adding the Activity to SharePoint

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…”

     

  2. From the folder list, select “TEMPLATE1033Workflow

     

  3. In the Solution Explorer, right-click on the new Workflow folder and add an XML file (Add -> New Item -> DataXML File).
  4. Name the file [project name].actions (obviously, substituting the actual name of your project, although it could be anything, as long as it is somewhat unique).

     

  5. Add the following XML to the File… Substituting the actual information for your project.
    1. By the way, the FieldBind and Parameter sections tie to the Dependency Property you put in the class. In the rule designer, that “%1” is the place holder for the value of the first FieldBind node. You can have more than one of those.
    2. Here is the schema for this XML file, http://msdn.microsoft.com/en-us/library/bb897833.aspx
    3. You’ve probably noticed you need the fully qualified name for your assembly. If you’ve never had to get the Public Key Token before, it can be a little confusing. Do yourself a favor and add this to your tools:
      1. Go to “Tools” and select “External Tools
      2. Then click “Add…

        Title: “Get &PublicKeyToken”

        Command: “C:Program Files(x86)Microsoft SDKsWindowsv7.0ABinsn.exe”

        Arguments: “-Tp $(TargetPath)”

      3. Check “Use Output Window” then click “OK
      4. Now you can run this and it will write the key info into your output window

Turning this into a Feature and fixing up the Web.Config

Since you started with a blank SharePoint project, you’re going to need to add a Feature to it so this can be turned on and off – but, more importantly, because you need to add some things to the web.config for this to work. Luckily, having a Feature means you can add an Event Receiver that fires when the feature is activated/deactivated – which means handling the web.config properly isn’t that bad.

  1. In the Solution Explorer, right-click on Features and select “Add Feature
  2. Rename the Feature to something more sensible than Feature1.
  3. Open the Feature Designer (double clicking the feature will do this) and switch the Feature Scope to “WebApplication
  4. Right-click on the Feature in the Solution Explorer and select “Add Event Receiver
  5. Open the new class and uncomment the FeatureActivated and FeatureDeactivated methods
  6. Add using statements for Microsoft.SharePoint.Administration, System.Collections.Generic and System.Linq
  7. Add the following code to the FeatureActivated method (you can copy and paste this time):
    1. Don’t forget to change the assembly information to match your assembly. The things to change are in CAPS.
    2. P.S. The value for Owner should really be put in a “const string” at the top of the class. It has to be exactly the same when we go to remove the entry.

    SPSecurity.RunWithElevatedPrivileges(() =>
                {
                    SPWebService service = SPWebService.ContentService;
                    SPWebConfigModification mod = new SPWebConfigModification();
                    mod.Path = “configuration/System.Workflow.ComponentModel.WorkflowCompiler/authorizedTypes”;
                    mod.Name = “authorizedType[@Assembly=’YOURASSEMBLYNAME, Version=1.0.0.0, Culture=neutral, PublicKeyToken=YOURKEY’][@Namespace=’YOURNAMESPACE’][@TypeName=’*’][@Authorized=’True’]”;
                    mod.Sequence = 0;
                    mod.Owner = “THE NAME OF YOUR PROJECT”;
                    mod.Type = SPWebConfigModification.SPWebConfigModificationType.EnsureChildNode;
                    mod.Value = “<authorizedType Assembly=’ YOURASSEMBLYNAME, Version=1.0.0.0, Culture=neutral, PublicKeyToken=YOURKEY’ Namespace=’YOURNAMESPACE’ TypeName=’*’ Authorized=’True’ />”;
                    service.WebConfigModifications.Add(mod);
                    service.Update();
                    service.ApplyWebConfigModifications();
                });

  1. Add the following code to the FeatureDeactivated method:
    1. Same notes as above + Notice the “ToList()” when looking up the config mods. This is because removing items from the collection while looping through it causes problems.

    SPSecurity.RunWithElevatedPrivileges(() =>

                {

                    SPWebApplication webApplication = properties.Feature.Parent as SPWebApplication;

                    var mods = webApplication.WebConfigModifications;

                var items = mods.Where(m => m.Owner == “SAME NAME FROM BEFORE”).ToList();
                foreach (var item in items)
    {
    mods.Remove(item);
    }

                });

Conclusion

That about wraps it up. You should be able to deploy this sucker to SharePoint now – and then see it in SharePoint Designer.