C# module for HTTP to HTTPS redirection for custom ports by reading them from AppHost.config

A week back I was thinking if we can dynamically fetch the custom ports (other than 443) from apphost.config and use it to redirect the request without writing any URL Rewrite rules. Then I wrote a module which does the same job. In this article I will explain the module which I have written.

I have written a class library which makes use of Microsoft.Web.Administration.dll and returns Port in integer format. I have referenced this library in the HTTP Module. You can find the code below.

using System;using Microsoft.Web.Administration;public static class ServerMgr{public static int getPort(){using (ServerManager serverManager = new ServerManager()){Configuration config = serverManager.GetApplicationHostConfiguration();ConfigurationSection sitesSection = config.GetSection("system.applicationHost/sites");ConfigurationElementCollection sitesCollection = sitesSection.GetCollection();ConfigurationElement siteElement = FindElement(sitesCollection, "site", "name", @"site2");if (siteElement == null) throw new InvalidOperationException("Element not found!");ConfigurationElementCollection bindingsCollection = siteElement.GetCollection("bindings");ConfigurationElement bindingElement = FindElement(bindingsCollection, "binding", "protocol", @"https");if (bindingElement == null) throw new InvalidOperationException("Element not found!");string combinedPort = (string)bindingElement["bindingInformation"];serverManager.CommitChanges();int port = Convert.ToInt32(string.Join(null, System.Text.RegularExpressions.Regex.Split(combinedPort,"[^\\d]")));return port;}}private static ConfigurationElement FindElement(ConfigurationElementCollection collection, string elementTagName, params string[] keyValues){foreach (ConfigurationElement element in collection){if (String.Equals(element.ElementTagName, elementTagName, StringComparison.OrdinalIgnoreCase)){bool matches = true;for (int i = 0; i < keyValues.Length; i += 2){object o = element.GetAttributeValue(keyValues[i]);string value = null;if (o != null){value = o.ToString();}if (!String.Equals(value, keyValues[i + 1], StringComparison.OrdinalIgnoreCase)){matches = false;/span>break;/span>}}if (matches){return element;}}}return null;}}

Below is the code for HTTP module which makes use of the above class library to get the port and redirect request. The module has registered to listen for one event called application.BeginRequest which does the trick when the first request begins.

using System;using System.Web;namespace Module{public class HttpToHttps : IHttpModule{// In the Init function, register for HttpApplication events by adding your handlers.public void Init(HttpApplication application){application.BeginRequest += new EventHandler(this.OnBeginRequest);}public void Dispose(){}public void OnBeginRequest(object sender, EventArgs e){// Create HttpApplication and HttpContext objects to access request and response properties.HttpApplication application = (HttpApplication)sender;HttpContext context = application.Context;if (!application.Request.IsSecureConnection){string serverName = HttpUtility.UrlEncode(application.Request.ServerVariables["SERVER_NAME"]);string filePath = application.Request.FilePath;int customPort = ServerMgr.getPort();application.Response.Redirect("https://" + serverName + ":" + customPort + filePath);}}}}

Just register this module in your web.config so that it is fired as soon as the request reaches the IIS server. You can do it from IIS manager as well.

Below are the steps to register the module in your site.

  • Make sure all the 3 DLLs (Getport.dll, HttpToHttps.dll and Microsost.Web.Administration.dll) are in the bin folder of website location
  • Open IIS manager and select your site.
  • In the Connections pane, expand the server name, expand Sites, and then go to the Web site or application to which you want to add a managed module.
  • In the Home pane, double-click Modules.

  • In the Actions pane, click Add Managed Module.
  • In the Add Managed Module dialog box, enter the name of the managed module in the Name box, and then enter or select the module's .NET Framework fully-qualified type in the Type box.
  • Select the Invoke only for requests to ASP.NET applications or managed handlers option if you want the module to respond only to managed requests.

  • Click OK.

I have provided the link below to download both class library and HTTP Module in case if you want to test it.

Code.zip

Happy Coding !