How To: Create a site collection in a workflow

So if you have been reading this blog for a while, you know that I am a big fan of site collections versus very deep site trees. There are many benefits to creating a flat structure of site collections; especially when you are considering using those site for instances of a business process. With a site collection, you can apply a quota to maintain growth. And with many site collections, you can spread them across content databases. I recently built a workflow for a demonstration that needed to create a site collection. The workflow triggered off of a list where the list item had a JobReqID column which represented a unique job that a fictional company was interviewing for... There was also a SiteAdmin column (of type Person) which was to be read by the workflow and used to designate the new site collection's administrator. Here is the code I had in my workflow's code activity.

private void codeActivity1_ExecuteCode(object sender, EventArgs e)
{
    string siteUrl = string.Empty;
    SPSecurity.RunWithElevatedPrivileges(delegate()
    {
       SPContext context = SPContext.GetContext(workflowProperties.Web);
       SPSite currentSite = context.Site;
       SPWebApplication webApp = currentSite.WebApplication;
       SPSiteCollection sites = webApp.Sites;

       string jobID = workflowProperties.Item["JobReq: JobReqID"].ToString();
       siteUrl = "https://portal.sample.com/jobs/" + jobID;
       Contact contact = Contact.FromSharePointUserString(workflowProperties.Item["SiteAdmin"].ToString(), workflowProperties.Web);
       string ownerName = contact.DisplayName;
       string ownerEmail = contact.EmailAddress;
       string ownerAccount = contact.LoginName;
       string siteTemplate = "JobOpeningSiteDef_14e1b257-ef45-435d-89b2-e04e74a06e29#1";
               
       SPSite newSite = sites.Add(siteUrl, "Job Opening Site", "Job Opening Site", 1033, siteTemplate, ownerAccount, ownerName, ownerEmail);
                
       //update the item that kicked off the workflow
       workflowProperties.Item["SiteUrl"] = siteUrl;
       workflowProperties.Item.Update();
             
       //save this to the web in case others need it
       SPWeb web = newSite.RootWeb;
       web.Properties["JobID"] = jobID;
       web.Properties.Update();
       web.Update();

    });
 }

Notice the use of the inline delegate to run this code block with elevated security permissions. If you don't do this, the code will throw an error (something like try again later...). There is a Contact class in the Microsoft.Office.Workflow.Utility namespace that can read the SharePoint user string of the SiteAdmin column and do the necessary work for you to get the email address and login name information. Lastly, I update the list item to store the resulting Url and place the JobReqID value in the property bag of the root web of the site collection. Storing this information here, allowed my to setup some connections for the web parts on the page. I'll write about that a bit later.