Views: 1087
Number of votes: 2
Average rating:

Site Settings Url and Episerver Cloud license

When Episerver released their Cloud license, also called the instance bound license that can be used both on prem or in ordinary Azure or Amazon they needed a way to get information on what site that is using the license. This to verify if there is a license for that site and to update/verify the number of servers/instances the site is running on.

For that information they decided to use the URL property that is set in Admin/Config/Manage Websites and that is all fine, since that url is usually correct. But since the license usually say for example 1 site and 2 instances if you buy a license to be used in production and also in test environment the problem comes to how to determinate what site there is on the test environment and for that Episerver decided that URL in Site Settings must be the same on all environment. (Read more about it here: https://world.episerver.com/documentation/developer-guides/CMS/Deployment/managing-cloud-licenses/)

This works fine for them and for most part of Episerver core (maybe there is some AddOns that still is not updated) but for us developers and our client implementation this can be a problem. The reason for that is that we used to use that URL to generate for example the external url or simular stuff.

We used to have (or still have) code that could looks like this:

private string GetExternalUrl(string path)
{
	if (SiteDefinition.Current != null && SiteDefinition.Current.SiteUrl != null)
	{
		return new Uri(SiteDefinition.Current.SiteUrl, path).AbsoluteUri;
	}

	return path;
}

This code have a couple of problems, first it does not handle having multiple language and with the new License rule we will end up with production url's in test environment as well.

To fix this we will use the hostname part of the settings instead (that is also what Episerver is using internally now). So first you need to update (if it is not already) inside Admin/Config/Manage Websites/Settings so you have a hostname that is marked as primary (for multi language, one primary per language). Also you need to mark the correct scheme for the hostname so you set it to https if you are using it.

We then update the code for the function that was in the previous example so it takes some more parameters. We need to send in the language we want the external url for and also the ContentReference to the content. Inside the function we are going to use the interface ISiteDefinitionResolver so we need the current implementation for that so either get it by constructor injection or parameter injection or Valdis forbids via ServiceLocator.

Then the function can look like this:

private string GetExternalUrl(string path, CultureInfo lang, ContentReference contentLink, ISiteDefinitionResolver siteDefinitionResolver)
{
	var siteDefinition = this.siteDefinitionResolver.GetByContent(contentLink, true, true);
	var hosts = siteDefinition.GetHosts(lang, true).ToList();

	var host = hosts.FirstOrDefault(h => h.Type == HostDefinitionType.Primary) ?? hosts.FirstOrDefault(h => h.Type == HostDefinitionType.Undefined);

	var baseUri = siteDefinition.SiteUrl;

	if (host != null && host.Name.Equals("*") == false)
	{
		var uriString = string.Format("http{0}://{1}", host.UseSecureConnection.HasValue && host.UseSecureConnection.Value ? "s" : string.Empty, host.Name);
		
		// Try to create a new base URI from the host with the site's URI scheme. Name should be a valid
		// authority, i.e. have a port number if it differs from the URI scheme's default port number.
		if (!Uri.TryCreate(uriString, UriKind.Absolute, out baseUri))
		{
			return path;
		}
	}

	var absoluteUri = new Uri(baseUri, path);
	return absoluteUri.AbsoluteUri;
}

Yes, it is a little bit more code, and yes the code could use a couple of refactoring session but you get a hold on what is needing to be done.

To explain it a little we first get the correct SiteDefinition (for the site that the content belongs to) and then we look for the hostname with the primary flag on it or we take the first one if there arent any primary. Then we get the baseUri (Site url) from the current SiteDefintion to be used if there is not any hostnames or there’s only the star. And in the end we try to create a uri with the information for the primary hostname (and return the relative url if something goes wrong) and return the absolut url for the SiteUrl together with the path that was sent in to the function.

I hope you find this useable and I have sent in a feature request to Episerver to move the settings for the License to a specific field in admin since I even with code that support hostname like to have the correct Url in Site Settings.

Mar 08, 2019

Please login to comment.