In a recent project, we were tasked to create Host Named Site Collections (HNSC) using a Timer job programmatically for an Intranet Hosting portal. It took us some time to find out the right way to get it implemented because Host named site collections for SharePoint On-prem are easy to create using PowerShell (technet article – link) but becomes challenging when you want to do the same using C# or object model, because there is no direct method to call.

To achieve this, we could use reflection (courtesy: Joseph’s blog post) to call the site creation programmatically using C# Timer job. Below steps outline the same.

  1. Get the following parameters as per the Reflection signature below. This will be used to fill into the paramater array below.
    SPSite.Add(SPContentDatabase database, SPSiteSubscription siteSubscription, string siteUrl, string title, string description, uint nLCID, int compatibilityLevel, string webTemplate, string ownerLogin, string ownerName, string ownerEmail, string secondaryContactLogin, string secondaryContactName, string secondaryContactEmail, string quotaTemplate, string sscRootWebUrl, bool useHostHeaderAsSiteName, bool overrideCompatibilityRestriction)
  2. Some of the above parameters will need to be fetched and provided in the parameter array below:
    • Content database object – You can get it from the ContentDatabases property of SPWebApplication object or there are various other ways.
    • LCID – it is 1033 for US-EN but you can get your locale one using
      uint nLCID = Convert.ToUInt32(new System.Globalization.CultureInfo(1033).LCID);
    • Compatibility Level – Get it from SPWebApplication Object using
       webAppObj.CompatibilityRange.DefaultCompatibilityLevel
    • Template – Get the #hash template name from link
    • Quota Template – You can fetch the default quota template
       webAppSC.DefaultQuotaTemplate
    • The last three parameters will have the below values
      useHostHeaderAsSiteName = true
      overrideCompatibilityRestriction = false
      sscRootWebUrl = null
  3. Initialize the Type object, create the dummy signature for the Type object and create a MethodInfo for that signature.
    The idea is to mimic the code structure of the internal function which we are going to Invoke.

    Type type = sites.GetType();
    Type[] signature = new Type[]{typeof(SPContentDatabase), typeof(SPSiteSubscription), typeof(string), typeof(string), typeof(string), typeof(uint),
                       typeof(int), typeof(string), typeof(string), typeof(string), typeof(string), typeof(string), typeof(string), typeof(string),
                       typeof(string), typeof(string), typeof(bool), typeof(bool)};
    
    MethodInfo methodInfo = type.GetMethod("Add", BindingFlags.NonPublic | BindingFlags.Instance, null, signature, null);
  4. Fill in  the values into the parameter array as in the Reflection method
    object[] parametersArray = new object[] {para 1, para2 ..}; //Fill it with values in sequence as in Reflection signature
    SPSite newSite = (SPSite)methodInfo.Invoke(sites, parametersArray);
    
  5. If you are running the code on web page backend code, then call the below methods before you call the Invoke method in order to prevent it from session time out
    SPLongOperation spLongOperation = new SPLongOperation(this);
    spLongOperation.Begin();

And thats’ it.. and keep your fingers crossed 🙂

Finally, it takes some time for the site collection to be prepared, so make sure you are logging the process so you can see the progress.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s