One most commonly requested automated process is the creation of a site. For example: A team needs 28 sites using a template "A" for a project. I am sure this request will give the site owner or the SharePoint team a Heart attack!
Anyway, Just to add some spice to my blog, I am going to pen down an example scenario I recently worked on which required the automated process of creating sites. (This will help me too in my future if I have to deal with similar projects)
My company prefers to maintain separate sites for each Request for Proposal, but of course each request for a new site needs to be approved by the site owner (assuming SharePoint team is not involved as no customizations are needed). So.....
1. When a RFP is received, the team responsible for handling it submits a request to create a site with the corresponding RFP name (or any other criteria).
To achieve this, I built an Info Path form that collects all required information about the site from the user.
Anyway, Just to add some spice to my blog, I am going to pen down an example scenario I recently worked on which required the automated process of creating sites. (This will help me too in my future if I have to deal with similar projects)
My company prefers to maintain separate sites for each Request for Proposal, but of course each request for a new site needs to be approved by the site owner (assuming SharePoint team is not involved as no customizations are needed). So.....
1. When a RFP is received, the team responsible for handling it submits a request to create a site with the corresponding RFP name (or any other criteria).
To achieve this, I built an Info Path form that collects all required information about the site from the user.
3. When this request is approved, the workflow will create a site using the details entered in the form. This is achieved by developing (Coding arghhhh... ) a custom workflow action which uses the overload method of SPWebCollection.Add.
Frankly, to an extent this still sounds a bit manual to me as it is one form submission per site request, which I suppose is a hassle for the users. But looking at it from the maintenance side; this is a great way to keep track of each new site being built anywhere in the agency by anyone. All info about these requests and builds are stored in the data list
(Does that sound too complicated?! Feel free to post any workarounds :) )
Another simple scenario I found (This may be a more common one) Programmatically creating a SharePoint Site based on user input
Notes on the activity:
1. This activity is used to create a site.
2. This activity can span across site collections.
3. This activity (if set to yes) will inherit permissions from parent.
4. This activity (if set to yes) will inherit global navigation from parent.
5. This activity does not create the site if a predefined template is not specified. If a user requests a site to be built off of a new template, the workflow stops and notifies our team.
Initially I included the code for creating security groups and adding users to the security groups automatically as a part of this solution, but I felt it would make more sense in having a separate activity as the functionality may be used in other scenarios too.
Please see post:
Ok!! so not wasting any more time, lets get to work.Initially I included the code for creating security groups and adding users to the security groups automatically as a part of this solution, but I felt it would make more sense in having a separate activity as the functionality may be used in other scenarios too.
Please see post:
Please refer to my post on Custom workflow activity to move a file from one site to another and follow the same steps on how to create a visual studio solution.
Follow each step from 1-7.
(Name your project appropriately)
1. When you reach step 7, add the following code to your (ActivityName).cs file
using System;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Collections;
using System.Linq;
using System.Workflow.ComponentModel.Compiler;
using System.Workflow.ComponentModel.Serialization;
using System.Workflow.ComponentModel;
using System.Workflow.ComponentModel.Design;
using System.Workflow.Runtime;
using System.Workflow.Activities;
using System.Workflow.Activities.Rules;
using Microsoft.SharePoint;
using Microsoft.SharePoint.WorkflowActions;
using Microsoft.SharePoint.Utilities;
using Microsoft.SharePoint.Workflow;
using Microsoft.SharePoint.Navigation;
using System.Threading;
namespace CustomWorkflowActivities
{
public partial class CreateSite :
SequenceActivity
{
public CreateSite()
{
InitializeComponent();
}
//Current workflow Context
public WorkflowContext
__Context
{
get { return (WorkflowContext)GetValue(__ContextProperty); }
set { SetValue(__ContextProperty, value); }
}
public static readonly DependencyProperty
__ContextProperty =
DependencyProperty.Register("__Context", typeof(WorkflowContext), typeof(CreateSite));
//Parent web Url
public static readonly DependencyProperty
parentWebUrlProperty =
DependencyProperty.Register("parentWebUrl", typeof(string), typeof(CreateSite));
[DescriptionAttribute("A
string that contains the URL of the Parent web under which new web is
created")]
[BrowsableAttribute(true)]
[DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)]
[ValidationOption(ValidationOption.Optional)]
public string
parentWebUrl
{
get { return (string)GetValue(parentWebUrlProperty); }
set { SetValue(parentWebUrlProperty, value); }
}
//New Web Url
public static readonly DependencyProperty
newWebUrlProperty =
DependencyProperty.Register("newWebUrl", typeof(string), typeof(CreateSite));
[DescriptionAttribute("A
string that contains the new website URL relative to the root website in the
site collection. For example, to create a website at
'http://MyServer/sites/MySiteCollection/MyNewWebsite', specify
MyNewWebsite")]
[BrowsableAttribute(true)]
[DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)]
[ValidationOption(ValidationOption.Optional)]
public string
newWebUrl
{
get { return (string)GetValue(newWebUrlProperty); }
set { SetValue(newWebUrlProperty, value); }
}
//Title
public static readonly DependencyProperty
strTitleProperty =
DependencyProperty.Register("Title", typeof(string), typeof(CreateSite));
[DescriptionAttribute("A
string that contains the Title of the site to be created")]
[BrowsableAttribute(true)]
[DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)]
[ValidationOption(ValidationOption.Optional)]
public string
strTitle
{
get { return (string)GetValue(TitleProperty); }
set { SetValue(TitleProperty, value); }
}
//Description
public static readonly DependencyProperty
strDescriptionProperty =
DependencyProperty.Register("strDescription", typeof(string), typeof(CreateSite));
[DescriptionAttribute("A
string that contains the description of the site to be created")]
[BrowsableAttribute(true)]
[DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)]
[ValidationOption(ValidationOption.Optional)]
public string
strDescription
{
get { return (string)GetValue(strDescriptionProperty); }
set { SetValue(strDescriptionProperty, value); }
}
//Web Template
public static readonly DependencyProperty
webTemplateProperty =
DependencyProperty.Register("webTemplate", typeof(string), typeof(CreateSite));
[DescriptionAttribute("A
string that contains the name of template based on which the new site is
created")]
[BrowsableAttribute(true)]
[DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)]
[ValidationOption(ValidationOption.Optional)]
public string
webTemplate
{
get { return (string)GetValue(webTemplateProperty); }
set { SetValue(webTemplateProperty, value); }
}
//Permissions
public static readonly DependencyProperty
useUniquePermissionsProperty =
DependencyProperty.Register("useUniquePermissions", typeof(bool), typeof(CreateSite));
[DescriptionAttribute("True
indicates the new web will 'NOT' inherit permissions from the parent site;False
indicates the new web will inherit permissions from the parent site")]
[BrowsableAttribute(true)]
[DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)]
[ValidationOption(ValidationOption.Optional)]
public bool
useUniquePermissions
{
get { return (bool)GetValue(useUniquePermissionsProperty); }
set { SetValue(useUniquePermissionsProperty, value); }
}
//Top Link Bar
public static readonly DependencyProperty
InheritTopLinkBarProperty =
DependencyProperty.Register("InheritTopLinkBar", typeof(bool), typeof(CreateSite));
[DescriptionAttribute("true
to inherit Global navigation from parent site; otherwise, false")]
[BrowsableAttribute(true)]
[DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)]
[ValidationOption(ValidationOption.Optional)]
public bool
InheritTopLinkBar
{
get { return (bool)GetValue(InheritTopLinkBarProperty); }
set { SetValue(InheritTopLinkBarProperty, value); }
}
protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
{
CreateSiteMethod();
return ActivityExecutionStatus.Closed;
}
private void
CreateSiteMethod()
{
//Open Parent Site Collection
using (SPSite
parentSite = new SPSite(parentWebUrl))
{
//Open Parent Web
using (SPWeb parentWeb = parentSite.OpenWeb())
{
//Get the current Web on which workflow is
running
using (SPWeb
currentWeb = __Context.Web)
{
try
{
SPWeb newWeb = null;
string strWebUrl = null;
parentSite.AllowUnsafeUpdates = true;
//If Site Description is not entered by user, set it to
blank
if (strDescription == null)
strDescription
= "";
//If no template is selected, set default = Team Site(STS#0)
if (String.IsNullOrEmpty(webTemplate))
webTemplate = "STS#0";
// Declare Locale ID : A 32-bit unsigned integer that
specifies the locale ID. You can also specify 1033.
uint nLCID =
parentWeb.Language;
//This step is required only to avoid any human error (Optional)
//If the URL entered by a user is a well formatted URL; get
the last segment which represents the new web URL only
if (Uri.IsWellFormedUriString(newWebUrl,
UriKind.Absolute))
{
Uri uri = new Uri(newWebUrl);
strWebUrl =
uri.Segments.Last();
}
else //If a user enters a
single word which represents the new web URL segment
{
strWebUrl =
newWebUrl;
}
try
{
//Create a new site using overload method
SPWebCollection.Add(String, String, String, UInt32, String, Boolean, Boolean)
newWeb =
parentWeb.Webs.Add(strWebUrl, strTitle, strDescription, nLCID, webTemplate,
useUniquePermissions, false);
//Create a workflow history event
SPWorkflow.CreateHistoryEvent(currentWeb,
__Context.WorkflowInstanceId, 0,
currentWeb.CurrentUser,
TimeSpan.Zero, "Success",
"Message: " + "Site
created successfully", string.Empty);
}
catch (ArgumentException)
{ }
if (newWeb != null)
{
if (InheritTopLinkBar == true)
//Optional
{
// Set the new web's top link bar to inherit links from its
parent web.
newWeb.Navigation.UseShared
= true;
// Create a link pointing to the new web.
SPNavigationNode node = new
SPNavigationNode(newWeb.Title,
newWeb.ServerRelativeUrl);
// Find out if the parent inherits .
bool parentInheritsTopNav =
newWeb.ParentWeb.Navigation.UseShared;
if (!parentInheritsTopNav)
{
// Add the link to the top link bar on the parent web.
newWeb.ParentWeb.Navigation.TopNavigationBar.AddAsLast(node);
}
}
}
parentSite.AllowUnsafeUpdates = false;
//Optional (as per user requirement)
if (useUniquePermissions == true)
{
try
{
newWeb.AllowUnsafeUpdates = true;
//Set the name of each group to be added
String owners
= strTitle + " Owners";
String members = strTitle + " Members";
String
visitors = strTitle + " Visitors";
//Create Groups
in the new Web
newWeb.SiteGroups.Add(owners, parentWeb.AssociatedOwnerGroup,
null, "This
group has full control to" + strTitle + "site");
newWeb.SiteGroups.Add(members, parentWeb.AssociatedOwnerGroup,
null, "This
group has contribute access to" + strTitle + "site");
newWeb.SiteGroups.Add(visitors, parentWeb.AssociatedOwnerGroup,
null, "This
group has read access to" + strTitle + "site");
//Get an instance of each new group created
SPGroup ownersGroup = newWeb.SiteGroups[owners];
SPGroup membersGroup = newWeb.SiteGroups[members];
SPGroup visitorsGroup = newWeb.SiteGroups[visitors];
//Add role assignment to each new group created
SPRoleAssignment ownersRoleAssignment = new SPRoleAssignment(ownersGroup);
SPRoleAssignment membersRoleAssignment = new SPRoleAssignment(membersGroup);
SPRoleAssignment visitorsRoleAssignment = new SPRoleAssignment(visitorsGroup);
//Get role
definitions defined in new Web
SPRoleDefinition contributeRoleDefinition =
newWeb.RoleDefinitions["Contribute"];
SPRoleDefinition readRoleDefinition =
newWeb.RoleDefinitions["Read"];
SPRoleDefinition fullControlRoleDefinition =
newWeb.RoleDefinitions["Full Control"];
//Add Role Definition Bindings to the groups
ownersRoleAssignment.RoleDefinitionBindings.Add(fullControlRoleDefinition);
membersRoleAssignment.RoleDefinitionBindings.Add(contributeRoleDefinition); visitorsRoleAssignment.RoleDefinitionBindings.Add(readRoleDefinition);
//Add role assignments to new web
newWeb.RoleAssignments.Add(ownersRoleAssignment);
newWeb.RoleAssignments.Add(membersRoleAssignment); newWeb.RoleAssignments.Add(visitorsRoleAssignment);
SPWorkflow.CreateHistoryEvent(currentWeb,
__Context.WorkflowInstanceId, 0,
currentWeb.CurrentUser, TimeSpan.Zero, "Success",
"Message: Security Groups created
successfully", string.Empty);
//assign values to the output variable.
Purpose: Can be used in the workflow
this.memberGroupNameOutput = membersGroupName; this.visitorGroupNameOuput = visitorsGroupName;
}
catch (ArgumentException)
{}
}
newWeb.Dispose();
currentWeb.Dispose();
parentWeb.Dispose();
parentSite.Dispose();
}
catch (Exception ex)
{
string Message = ex.Message;
SPWorkflow.CreateHistoryEvent(currentWeb,
__Context.WorkflowInstanceId, 0,
currentWeb.CurrentUser, TimeSpan.Zero,
"Error",
"Message: " + Message, string.Empty);
throw ex;
}
}
}
}
}
}
}
2. Follow steps 8-9
At step 10, paste this code into .actions files
At step 10, paste this code into .actions files
<?xml version="1.0" encoding="utf-8" ?>
<WorkflowInfo>
<Actions Sequential="then" Parallel="and">
<Action Name="Create site"
ClassName="CreateSiteAction.CreateSite"
Assembly="CreateSiteAction, Version=1.0.0.0, Culture=neutral, PublicKeyToken=/*Public Key Token of your project*/"
AppliesTo="all"
UsesCurrentItem="true"
Category="Custom Workflow Actions">
<RuleDesigner Sentence="Create Site: Title:%1, Description:%2, URL:%3 Parent Site: %4 Template %5; Use Unique Permissions: %6, Inherit Top Link Bar: %7
<FieldBind Field="strTitle" Text="Title" Id="1" DesignerType="TextArea" />
<FieldBind Field="strDescription" Text="Description" Id="2" DesignerType="TextArea" />
<FieldBind Field="newWebUrl" Text="URL" Id="3" DesignerType="TextArea" />
<FieldBind Field="parentWebUrl" Text="Parent Site URL. Must be in the form of http://ServerName/(SiteName)" Id="4" DesignerType="TextArea" />
<FieldBind Field="webTemplate" Text="Template" Id="5" DesignerType="TextArea" />
<FieldBind Field="useUniquePermissions" Text="Permissions" Id="6" DesignerType="TextArea" />
<FieldBind Field="InheritTopLinkBar" Text="Inherit Top Link Bar" Id="7" DesignerType="System.Boolean" />
</RuleDesigner>
<Parameters>
<Parameter Name="__Context" Type="Microsoft.SharePoint.WorkflowActions.WorkflowContext" Direction="In" />
<Parameter Name="newWebUrl" Type="System.String, mscorlib" Direction="In" />
<Parameter Name="parentWebUrl" Type="System.String, mscorlib" Direction="In" />
<Parameter Name="strTitle" Type="System.String, mscorlib" Direction="In" />
<Parameter Name="strDescription" Type="System.String, mscorlib" Direction="Optional" />
<Parameter Name="webTemplate" Type="System.String, mscorlib" Direction="Optional" />
<Parameter Name="useUniquePermissions" Type="System.String, mscorlib" Direction="In" />
<Parameter Name="InheritTopLinkBar" Type="System.Boolean, mscorlib" Direction="In" />
</Parameters>
</Action>
Errors:
References:
1. http://google.com
2. http://msdn.microsoft.com/en-us/library/ms412285.aspx
3. http://ankurmadaan.blogspot.com/2012/03/creating-custom-workflow-activity-using.html
4. http://blogs.planetcloud.co.uk/mygreatdiscovery/post/SharePoint-Custom-Workflow-to-create-a-site.aspx
No comments:
Post a Comment