ASP MVC HTTPS and 301 Redirect

By James Kenny
2 min read

Table of Contents

Last time around I explained how to get Lets encrypt up and running on Windows Azure to catch up click here

Now I have it running I need to get my sites to use HTTPS all the time and also use 301 Redirect for SEO goodness

All below works as of today on Visual studio 2015 and ASP 4.6 working site https://cloudstatus.eu

Force HTTPS

First step was to always require HTTPS. This in MVC 4 + is straight forward enough, in the controller. Simply add the [RequireHttps] to the top of each controller you want to force the SSL in.

[RequireHttps]
public class HomeController : Controller

Every time you open the controller it will send you to the HTTPS version of the page

IISExpress does have an issure here but it's easy to sort. You need to tell IIS Express it's ok to use SSL.

With the web project selected hit F4 to bring up the "Project Properties pane"

You should see an option "SSL Enabled" select True and then when you run the website it will open on the port set.

This now means that all requests to the site will be using the https. If a visitor uses http:// then it will be sent to the [RequireHttps] this will then send it with a redirect.

301 or 302 Redirect

RequireHttps sends a 302 redirect you can test your redirect here

302 Redirect is fine I think in most cases but it's a temporary redirect and Google isn't kind to that.

For SEO we need a 301 redirect but we can do that.

To sort this we need to create a custom RequireHttps attribute.

public class CustomRequireHttpsFilter : RequireHttpsAttribute
{
    protected override void HandleNonHttpsRequest(AuthorizationContext filterContext)
    {
        // If the request does not have a GET or HEAD verb then we throw it away.
        if (!String.Equals(filterContext.HttpContext.Request.HttpMethod, "GET", StringComparison.OrdinalIgnoreCase)
            && !String.Equals(filterContext.HttpContext.Request.HttpMethod, "HEAD", StringComparison.OrdinalIgnoreCase))
        {
            base.HandleNonHttpsRequest(filterContext);
        }

        // Update the URL to use https instead of http
        string url = "https://" + filterContext.HttpContext.Request.Url.Host + filterContext.HttpContext.Request.RawUrl;

        // If it's localhost we are using IIS Express which has two different ports.
        // update the url with the IIS Express port for redirect on local machine.
        if (string.Equals(filterContext.HttpContext.Request.Url.Host, "localhost", StringComparison.OrdinalIgnoreCase))
        {
            url = "https://" + filterContext.HttpContext.Request.Url.Host + ":44363" + filterContext.HttpContext.Request.RawUrl;
        }

        // Build the httpContext Response
        // Setting a status of 301 and then telling the browser what the correct route is.
        filterContext.HttpContext.Response.StatusCode = 301;
        filterContext.HttpContext.Response.AppendHeader("Location", url);
        filterContext.HttpContext.Response.End();
    }
}

Then we make a change to our filterConfig to call our CustomerRequirehttps

public class FilterConfig
{
    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        filters.Add(new CustomRequireHttpsFilter());         
    }
}

And that's it, all HTTP:// calls are sent into the custom Require and will return a 301 with the new URL.

Tagged in:

ASP, .NET, https, 301, requirehttps, SSL

Last Update: August 21, 2018

About the Author