Removing port 443 from urls generated by Sitecore

For as long as I’ve been working on Sitecore there has been this really annoying issue where setting the link manager to include server url and running under https will cause urls to be generated with the port number included. e.g. https://www.himynameistim.com:443/ which naturally you don’t actually want.

Aside: This issue was finally fixed in Sitecore 9.1

To overcome this there are a few methods you can take.

Method 1 – Set the Scheme and Port on you site defenition

This is possibly the smallest change you can make as it’s just 2 settings in a config file.

Setting the external port on site node to 80 (yes 80) tricks the link manager code into not appending the port number as it does it for everything other than port 80.

<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/" xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
  <sitecore>
    <sites xdt:Transform="Insert">
      <site name="website">
        <patch:attribute name="hostName">www.MySite.com</patch:attribute>
        <patch:attribute name="rootPath">/sitecore/content/MySite</patch:attribute>
        <patch:attribute name="scheme">https</patch:attribute>
        <patch:attribute name="externalPort">80</patch:attribute>
      </site>     
    </sites>
  </sitecore>
</configuration>

What I don’t like about this method though, is your setting something to be wrong to get something else to come out right. It’s all a bit wrong.

Method 2 – Write your own link provider

The second method which I have generally done is to write your own provider which strips the port number off the generated URL.

For this you will need:

1. A patch file to add the provider:

<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
  <sitecore>
    <linkManager defaultProvider="sitecore">
      <patch:attribute
          name="defaultProvider"
          value="CustomLinkProvider" />
      <providers>
        <add name="CustomLinkProvider"
             type="MySite.Services.CustomLinkProvider, 
                         MySite"
                       languageEmbedding="never"
                       lowercaseUrls="true"
                       useDisplayName="true"
                       alwaysIncludeServerUrl="true"
          />
      </providers>
    </linkManager>
    <mediaLibrary>
      <mediaProvider>
        <patch:attribute name="type">
          MySite.Services.NoSslPortMediaProvider, MySite
        </patch:attribute>
      </mediaProvider>
    </mediaLibrary>
  </sitecore>
</configuration>

2. A helper method that removes the ssl port

namespace MySite
{
    /// <summary> 
    /// Link Helper is used to remove SSL Port 
    /// </summary> 
    public static class LinkHelper
    {
        /// <summary> 
        /// This method removes the 443 port number from url 
        /// </summary> 
        /// <param name="url">The url string being evaluated</param> 
        /// <returns>An updated URL minus 443 port number</returns> 
        public static string RemoveSslPort(string url)
        {
            if (string.IsNullOrWhiteSpace(url))
            {
                return url;
            }

            if (url.Contains(":443"))
            {
                url = url.Replace(":443", string.Empty);
            }

            return url;
        }
    }
}

3. The custom link provider which first gets the item url the regular way and then strips the ssl port

using Sitecore.Data.Items;
using Sitecore.Links;

namespace MySite
{
    /// <summary>Provide links for resources.</summary> 
    public class CustomLinkProvider : LinkProvider
    {
        public override string GetItemUrl(Item item, UrlOptions options)
        {
            // Some code which manipulates and exams the item...

            return LinkHelper.RemoveSslPort(base.GetItemUrl(item, options));
        }
    }
}

4. The same provider for media

using Sitecore.Data.Items;
using Sitecore.Resources.Media;

namespace MySite
{
    /// <summary> 
    /// This method removes SSL port number from Media Item URLs 
    /// </summary> 
    public class NoSslPortMediaProvider : MediaProvider
    {
        /// <summary> 
        /// Overrides Url mechanism for Media Items 
        /// </summary> 
        /// <param name="item">Sitecore Media Item</param> 
        /// <param name="options">Sitecore Media Url Options object</param> 
        /// <returns>Updated Media Item URL minus 443 port</returns> 

        public override string GetMediaUrl(MediaItem item, MediaUrlOptions options)
        {
            var mediaUrl = base.GetMediaUrl(item, options);
            return LinkHelper.RemoveSslPort(mediaUrl);
        }
    }
}

What I don’t like about this method is it’s messy in the opposite way. The port number is still being added, and we’re just adding code to try and fix it after.

Credit to Sabo413 for the code in this example

Method 3 – Official Sitecore Patch

Given that it’s Sitecore’s bug, it does actually make sense that they fix it. After all people are paying a license fee for support! This simplifies your solution down to 1 extra patch file and a dll. What’s better is as it’s Sitecores code they have the responsibility of fixing it, if it ever breaks something, and you have less custom code in your repo.

You can get the fix here for Sitecore version 8.1 – 9.0.

So this may leave you wondering how did Sitecore fix it? Well having a look inside the dll reveals they wen’t for method 2.

SEO Friendly URL’s in Sitecore

As silly as it seams to the average developer, URL’s are an important factor when it comes to SEO. As ridiculous as some of the requirements are (like not having spaces in a URL) they are unfortunately requirements that we have to live with. Here’s how to deal with not having upper case letters in a URL, replacing spaces with hyphens and getting rid of that pesky aspx extension.

Removing SpacesĀ from a URL

A space in a URL actually gets translated to %20, which for the average user isn’t very readable. I would argue that as well as doing the translation, browsers could actually just hide this fact from users, and Google could also hide it as well. But alas that hasn’t happened and the accepted solution is to replace spaces with a hyphen.

Within a patch config file add the following:

    <encodeNameReplacements>
      <replace mode="on" find=" " replaceWith="-" />
    </encodeNameReplacements>

What this will do is replace every space in an items name with a hyphen as links are rendered. When a request comes into Sitecore it will also replace all hyphens with a space, so that the URL’s still resolve.

However this does cause a problem for any items you have that already had a hyphen in them. Sadly the best we can do for this is to stop content editors including hyphens in item names with the following config patch:

    <settings>
      <setting name="InvalidItemNameChars">
        <patch:attribute name="value">\/:?&quot;&lt;&gt;|[]-</patch:attribute>
      </setting>
    </settings>

Make URLs all lower case

Believe it or not URL’s are actually case sensitive. Maybe not in the Windows / IIS world, but with Linux and the rest of the web they are. So the simplest solution is to make all the URL’s on the site lower case.

Sitecore 6.6 and above

If your using Sitecore 6.6 or above then you in luck, there’s a config setting on the linkManager to set all urls to lower case

    <linkManager defaultProvider="sitecore">
      <providers>
        <add name="sitecore">
          <patch:attribute name="lowercaseUrls">true</patch:attribute>
        </add>
      </providers>
    </linkManager>

Sitecore 6.5 and below

If you using 6.5 or below you need to do a little more work.

One way is using the same encodeNameReplacements config as we used before and replace every upper case letter in the alphabet with the lower case equivalent.


    <encodeNameReplacements>
      <replace mode="on" find="A" replaceWith="a" />
      <replace mode="on" find="B" replaceWith="b" />
      <replace mode="on" find="C" replaceWith="c" />
      <replace mode="on" find="D" replaceWith="d" />
    </encodeNameReplacements>

Personally this doesn’t seen the nicest solution and I expect will lead to a lot of replace functions being called.

Another solution is to create a class that overrides the Sitecores LinkProvider and simply makes the result of GetItemUrl lowercase

namespace YourNamespace.Providers
{
    public class LinkProvider : Sitecore.Links.LinkProvider
    {
        public override string GetItemUrl(Sitecore.Data.Items.Item item, Sitecore.Links.UrlOptions urlOptions)
        {
            return base.GetItemUrl(item, urlOptions).ToLower();
        }
    }
}

And then add a patch config to tell Sitecore to use your LinkManager rather than the default.

    <linkManager defaultProvider="sitecore">
      <providers>
        <add name="sitecore">
          <patch:attribute name="type">YourNamespace.Providers.LinkProvider, YourProjectName</patch:attribute>
        </add>
      </providers>
    </linkManager>

Getting rid of the aspx extension

By default Sitecore puts a .aspx extension on the end of a url. Changing it is just a config setting:

    <linkManager defaultProvider="sitecore">
      <providers>
        <add name="sitecore">
          <patch:attribute name="addAspxExtension">false</patch:attribute>
        </add>
      </providers>
    </linkManager>