Wednesday, 4 June 2014

Renaming a HNSC (Host Named Site Collection) in a SharePoint Farm with Multiple Web Applications

Recently I've been involved in migrating a large SharePoint farm from SharePoint 2010 to SharePoint 2013. The farm has multiple web applications, and HSNC's have been created in different web applications. Part of the migration has required us to rename a number of HNSC's (Host Named Site Collections) for the development, testing and staging environments.

I'll start by saying, Microsoft recommends using one web application (SPWebApplication) per farm if you are planning on using HNSC (host named site collections). But that doesn't stop people using HSNC's in a farm with multiple SharePoint web applications.

So the short of this is, if you have a SharePoint farm with multiple web applications, and you want to rename a HNSC within one of those web applications, you have to add a new URL (using New-SPSiteUrl) to an "unused" zone, and then manually add the IIS bindings into SharePoint Web Applications IIS site, for each server in the farm that accepts requests for the site collection. To see some PowerShell on how to do this, skip to the bottom of the article!

If you google or bing "rename SPSIte", you'll get a number of articles and posts about renaming both "path based" and "host named" site collections. There are a few PowerShell ways for achieving this, including Rename-SPSite, and SPSite.Rename(newurl).

In our case, none of these approaches worked. Renaming "path based" site collections works fine, and renaming "host named" site collections also works fine... as long as you have configured your farm in the supported way for HNSC's (with one web application). The environment we were upgrading had many web applications, and HNSC's in more than one of those web applications.

So after a bit of investigation, we (and by we, I mean a colleague of mine, Elaine Van Bergen) pointed out that IIS has to know which IIS site it should send the request to(there is always a single IIS site behind each SharePoint web application). Each IIS site has bindings (for domain names) that tell IIS which urls the site will serve requests for.

After checking the IIS bindings on the IIS site behind one of the SharePoint web applications where we had added a new URL for a HNSC, I found there was no binding there for the new URL (domain) I'd added to the HNSC.

If that doesn't already make sense, hopefully the following example explains it clearer.

For the example, we have an IIS site listening on port 80, with a binding for blackburn.trainstation.com. This IIS site will respond to any requests sent to the address blackburn.trainstation.com/* (e.g. http://blackburn.trainstation.com/default.aspx). We also have another IIS site with a binding for hawthorn.trainstation.com. Both of these IIS Sites have SharePoint web applications behind them, and each web application has a single SharePoint site collection. The site collections are host named site collections.

In this scenario, we have a SharePoint web application for the blackburn.trainstation.com, with an IIS site behind it listening on port 80, with the binding blackburn.trainstation.com. Web requests for blackburn.trainstation.com/* will be accepted by this IIS site, which will pass it onto SharePoint to look up the site, and respond to the request.



If a new URL, "gleniris.trainstation.com", is added to the "intranet" zone of the blackburn.trainstation.com web application, what would happen? When the request is received by the web server, IIS looks for an "IIS" site that has a binding for gleniris.trainistation.com. In our example there are no sites with this binding, but there is a site with a binding for "*" (anything), so IIS will send the request to that "IIS" site (Default Website). Because the Default IIS site doesn't actually have any sort of site behind it, an HTTP 404 is returned.



Once a binding for gleniris.trainstation.com is added to the blackburn.trainstation.com IIS site, requests for gleniris.trainstation.com will now be responded to by the IIS site with the binding. If this is an IIS site with a SharePoint web application behind it, the request is then handed off to SharePoint to fulfil.



So, getting back to the original problem, how do we rename a HNSC on a SharePoint farm with multiple web applications (without doing a backup-spsite, delete-spsite, restore-spsite)? It's not ideal. The way we found was to use Add-SPSiteURL cmdlet to add the new URL to a new zone (one other than the default zone). After doing this, we needed to manually add an IIS binding for the SharePoint web application's IIS website, on all the SharePoint WFE's (web servers), to tell the IIS site to respond to requests for the new URL.

Building on our example, the commands for this looks like this:

#Add a new URL for the HNSC http://blackburn.trainstation.com            
$site = Get-SPSite http://blackburn.trainstation.com            
Add-SPSiteUrl $site -URL http://gleniris.trainstation.com -Zone Intranet            
            
#Add the IIS binding, for gleniris.trainstation.com on port 80 (remember, this will need to be performed on each WFE)            
Import-Module "WebAdministration"            
New-WebBinding -Name $site.WebApplication.Name -Protocol http -Port 80 -IPAddress "*" -HostHeader gleniris.trainstation.com

It's not pretty, but it is a workaround if you find yourself in this position.

As I said at the start, this is probably one reason why Microsoft recommends using HNSC with one web application. If you are using one web application, you can configure it with a binding of "*". Doing this ensures the IIS site responds to all requests, and hands them off to SharePoint to satisfy. SharePoint contains the list of HNSC's and takes care of responding to valid requests.