3 minute read

One of the new features in SharePoint 2010 was the possibility to create Sandbox solutions. Sandbox solutions are custom build solutions that run in another process with another CAS policy.

Sandbox solutions allow you to do the following:

  • Deploy custom code to you site collection when you do not have access to Central Administration.
  • Sandbox solutions cannot jeopardize the stability of your farm.
  • With SharePoint in a hosted environment you will be able to deploy Sandboxed solutions.

With the ability to deploy Sandbox solutions you also have some important restrictions:

  • A certain part off the SharePoint API is not available.
  • You cannot read/write to the file system.
  • You cannot call assemblies deployed out of Global Assembly Cache.

After all Sandbox solutions are a powerful feature of SharePoint. SharePoint designer gives you the possibility to develop Custom actions. But when you try to develop those for the sandbox it is totally different.

Let’s start of by creating a empty SharePoint project. When you created a empty project add a new Class file. Mark the class public and add a method that returns a Hashtable that has a SPUserCodeWorkflowContext object as parameter. The Hashtable will give you the ability to return values in the workflow. The SPUserCodeWorkflowContext on the other hand is a ‘In’ parameter.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using Microsoft.SharePoint.UserCode;
using Microsoft.SharePoint;

namespace Motion10.SharePoint.Sandbox.Designer
{
    public class SPCreateSubSiteAction
    {
        public Hashtable CreateSubSite(SPUserCodeWorkflowContext context)
        {
        }
    }
}

In the above code example you see that I created a method called ‘CreateSubSite’ within this method you can add the logic of your custom action. In the upcoming examples we will create a action that creates a sub site.

To add the custom action to SharePoint you have to create a new elements file in which you have  to specify the custom action.

<WorkflowActions>
  <Action Name="Create Sub Site"
          SandboxedFunction="true"
          Assembly="$SharePoint.Project.AssemblyFullName$"
          ClassName="Motion10.SharePoint.Sandbox.Designer.SPCreateSubSiteAction"
          FunctionName="CreateSubSite"
          AppliesTo="all"
          Category="Motion10 Designer Actions">
  </Action>
</WorkflowActions>

To be able to add parameters to the method that you need to create a sub site we will have to define a ‘RuleDesigner’ section to enable users to fill in those parameters.

<RuleDesigner Sentence="Create sub site with the title: %1, url: %2 and description: %3.">
  <FieldBind Field="Title" Text="Title" Id="1" DesignerType="TextBox" />
  <FieldBind Field="Url" Text="Url" Id="2" DesignerType="TextBox" />
  <FieldBind Field="Description" Text="Description" Id="3" DesignerType="TextBox" />
</RuleDesigner>

The ‘RuleDesigner’ section has to be placed within the ‘Action’ section. In the ‘Action’ section you also have to place a ‘Parameters’ section to pass the actual values in the workflow action.

<Parameters>
  <Parameter Name="__Context" Type="Microsoft.SharePoint.WorkflowActions.WorkflowContext, Microsoft.SharePoint.WorkflowActions" Direction="In" DesignerType="Hide" />
  <Parameter Name="Title" Type="System.String, mscorlib" Direction="In" DesignerType="ParameterNames" />
  <Parameter Name="Url" Type="System.String, mscorlib" Direction="In" DesignerType="ParameterNames" />
  <Parameter Name="Description" Type="System.String, mscorlib" Direction="In" DesignerType="ParameterNames" />
</Parameters>

With all of this in place we can extend our method with the correct parameters and create a simple action to create a sub site.

public Hashtable CreateSubSite(SPUserCodeWorkflowContext context, string Title, string Url, string Description)
{
    //hashtable that will be returned can be used for return values.
    Hashtable retVal = new Hashtable();

    using (SPSite site = new SPSite(context.CurrentWebUrl))
    {
        using (SPWeb web = site.OpenWeb())
        {
            try
            {
                using (SPWeb newWeb = web.Webs.Add(Url, Title, Title, 1033, web.WebTemplate, false, false))
                {
                    SPWorkflow.CreateHistoryEvent(web, context.WorkflowInstanceId, 0, web.CurrentUser, TimeSpan.Zero, "Information", "Sub site created from a Sandbox activity", string.Empty);
                }
            }
            catch (Exception ex)
            {
                SPWorkflow.CreateHistoryEvent(web, context.WorkflowInstanceId, 0, web.CurrentUser, TimeSpan.Zero, "Error", ex.Message,string.Empty );
            }
        }
    }
    return retVal;
}

Make sure you add the elements file to feature that is scoped to ‘Site’ and deploy the Sandbox solution. Open SharePoint Designer and you will see that you have the action available!