Create Sharepoint Site By Template in Code - Workflow Custom Activity

This post documents the steps I took in order to build a custom activity that creates a Sharepoint site by template. This post also talks about the steps needed in order to add this custom activity into the Sharepoint designer.
1. Create The Custom Activity

In Visual Studio 2005, I created a new Activity Library Project for my new activity. I created a new activity that derives from Activity (and not from the default SequentialActivity).

namespace Bursteg.CustomActivities

{

public partial class CreateSiteFromTemplate : Activity

{

public CreateSiteFromTemplate()

{

InitializeComponent();

}

}

This custom activity creates the new site based on an input template name, and according to the value of a selected column in the item who triggered the workflow. To name this action I'd say: Creates a new site by template X, and calls it like the value of field Y.
In order for the activity to receive both values, 2 dependency properties should be created: SiteNameField and TemplateName, both of type string. (You can use the wdp code snippet in order to create them.)

public static DependencyProperty SiteNameFieldProperty = DependencyProperty.Register("SiteNameField", typeof(string), typeof(CreateSiteFromTemplate));



[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]

[ValidationOption(ValidationOption.Required)]

public string SiteNameField

{

get { return ((string)(base.GetValue(CreateSiteFromTemplate.SiteNameFieldProperty))); }

set { base.SetValue(CreateSiteFromTemplate.SiteNameFieldProperty, value); }

}



public static DependencyProperty TemplateNameProperty = DependencyProperty.Register("TemplateName", typeof(string), typeof(CreateSiteFromTemplate));



[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]

[ValidationOption(ValidationOption.Required)]

public string TemplateName

{

get { return ((string)(base.GetValue(CreateSiteFromTemplate.TemplateNameProperty))); }

set { base.SetValue(CreateSiteFromTemplate.TemplateNameProperty, value); }

}

Since the activity has to perform some actions on the list item that has triggered the workflow, get its values and etc., it must receive some additional properties that gives the context to the activity: __Context, __ListId and __ListItem:

public static DependencyProperty __ContextProperty = DependencyProperty.Register("__Context", typeof(WorkflowContext), typeof(CreateSiteFromTemplate));



[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]

[ValidationOption(ValidationOption.Required)]

public WorkflowContext __Context

{

get { return ((WorkflowContext)(base.GetValue(CreateSiteFromTemplate.__ContextProperty))); }

set { base.SetValue(CreateSiteFromTemplate.__ContextProperty, value); }

}



public static DependencyProperty __ListItemProperty = DependencyProperty.Register("__ListItem", typeof(int), typeof(CreateSiteFromTemplate));



[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]

[ValidationOption(ValidationOption.Required)]

public int __ListItem

{

get { return ((int)(base.GetValue(CreateSiteFromTemplate.__ListItemProperty))); }

set { base.SetValue(CreateSiteFromTemplate.__ListItemProperty, value); }

}



public static DependencyProperty __ListIdProperty = DependencyProperty.Register("__ListId", typeof(string), typeof(CreateSiteFromTemplate));



[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]

[ValidationOption(ValidationOption.Required)]

public string __ListId

{

get { return ((string)(base.GetValue(CreateSiteFromTemplate.__ListIdProperty))); }

set { base.SetValue(CreateSiteFromTemplate.__ListIdProperty, value); }

}

Notice that the __Context Property is of type WorkflowContext. This property is the most important for the implementation of this activity.

As for the implementation of the activity, we have to override the Execute method. In the following code I am using the WorkflowContext to get a reference to the list of custom templates in my site and creating the new site based on the input template. As for the name of the site, I am taking the value of the input field name for the current item. Notice the usage of all the input properties.

protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)

{

// Get the list of custom templates in this site

SPWebTemplateCollection templates = __Context.Site.GetCustomWebTemplates(1037);



// Find the input template.

SPWebTemplate template = templates[this.TemplateName];



// Get the list in which this workflow was started

SPList list = __Context.Web.Lists[new Guid(__ListId)];



// Get the item that has triggered the workflow

SPListItem item = list.Items[__ListItem - 1];



// Get the value of the selected field

string siteName = (string)item[this.SiteNameField];



// Create the new site

SPWeb newWeb = __Context.Web.Webs.Add(siteName, siteName, siteName, 1037, template, false, false);



// This activity has finished its job.

return ActivityExecutionStatus.Closed;

}



You can download a sample project with the custom activity I created.
2. Register the activity with Sharepoint

In order to use this custom activity in Sharepoint, the assembly must be signed and registered to the GAC. You should use a new or existing strong name key file and assign it the the custom activity project. (Simply go to the project properties, select the Signing pane and check the "Sign the assembly" checkbox.)
You can register the assembly to the GAC by dragging it from the bin\debug\ directory to the c:\windows\assembly directory or you can use the command line tool:

"C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\Bin\gacutil.exe" -i c:\....\bin\debug\MyAssembly.dll /f.

A better approach (which I took) is to use the command line tool in the post-build event of the project. Simply go to the project properties, select the Build Events pane, and use the following command:

"C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\Bin\gacutil.exe" -i $(TargetPath) /f.

In this way, after every build, the new assembly will be registered to the GAC.

Now that Sharepoint can use the assembly, you have to add its types as authorized types for Sharepiont. You can do that by editing the web.config of your site (For example: C:\Inetpub\wwwroot\wss\VirtualDirectories\8080\web.config). At the bottom of the file, locate the tag and under the add a new authorized type with the assembly details:











I used .Net Reflector in order to get the full assembly name including the version, culture and public key token.
3. Register the custom activity to Sharepoint Designer

Sharepoint Designer has a simple and easy-to-use user interface for creating workflows. It allows selecting actions from a list of available actions and supplying parameters. You can add the new activity to that list and make it just like any other out-of-the-box activities.

To do this, open the wss.actions file located in C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\1033\Workflow. Under the tag, locate the tag and add a new action like the following:



























There are few things you should notice about this action declaration. The action name will appear in the list of actions in the Sharepoint Designer. The AppliesTo = "list" and UsesCurrentItem="true" attributes will cause the workflow to pass the values of the list id and list item properties to the activity. The Sentence will appear in the design surface when you add the action, and the %1 and %2 will be replaced with the designers that match the FieldBinding tags by the Id attribute.
4. Testing the Custom Activity

Create Sharepoint Site By TemplateIn order to test this activity create a site and save it as a template. Create a new list with a column that will hold the name of the site to create. For example, you can have a list of courses in which the course code will be the site name.

In Sharepoint Designer create a new workflow, select the relevant list and select a start option (Start when item is created). In Step 2 of the designer, create a new step and add the Create Site by Template action from the Custom category. Choose the column from which to take the name of the site to create, and supply the name of the site template (should be something that ends with .stp).

Click Finish to apply the workflow to the site.

Now, go to the list and create a new item. The workflow should start and create the new site. You can find it the list of sites under your site collection.

I hope this tutorial helps, and I'd love to hear any feedback, comments and questions about it.

You can download a sample project with the custom activity I created.

Enjoy!
source:blogs.microsoft.co.i

0 nhận xét:

Post a Comment

thanks comment