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.
- 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)
- 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
- 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);
- 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);
- 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