<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:atom="https://www.w3.org/2005/Atom" xmlns:sy="https://purl.org/rss/1.0/modules/syndication/" xmlns:dc="https://purl.org/dc/elements/1.1/" xmlns:content="https://purl.org/rss/1.0/modules/content/" xmlns:wfw="https://wellformedweb.org/CommentAPI/" xmlns:slash="https://purl.org/rss/1.0/modules/slash/"
  version="2.0">
  <channel>
    <title>Technobytes</title>
    <atom:link
      href="https://docs.microsoft.com/archive/blogs/surajdixit/feed.xml"
      rel="self"
      type="application/rss+xml" />
    <link>https://docs.microsoft.com/archive/blogs/surajdixit/feed.xml</link>
    <description>More about technology..</description>
    <lastBuildDate>Tue, 16 Apr 2019 05:32:22 GMT</lastBuildDate>
    <language>en-US</language>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>1</sy:updateFrequency>
    <item>
      <title>Custom Module for ARR Reverse Proxy to Pass the logged-in user to back-end servers</title>
      <link>https://docs.microsoft.com/archive/blogs/surajdixit/custom-module-for-arr-reverse-proxy-to-pass-the-logged-in-user-to-back-end-servers</link>
      <pubDate>Mon, 01 Oct 2018 01:41:24 GMT</pubDate>
      <dc:creator><![CDATA[Suraj Dixit]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/surajdixit/?p=455</guid>
      <description><![CDATA[While I was working one of the issues with one of my customers, I encountered a scenario where in...]]></description>
      <content:encoded><![CDATA[While I was working one of the issues with one of my customers, I encountered a scenario where in customer has an Application Request Routing server which is being used as a Revese Proxy. In the backend, they have an Apache server (Linux).  They want the logged in credentials to be passed from the client machine to the proxy server and from the proxy server the logged in credentials to be passed to the backend Apapche servers so that they can re-authenticate the user on Apache server.

The scenario was something like below:

<strong><span>Client (logged in user) =&gt; ARR Reverse Proxy (IIS) (logged in user) =&gt; (logged in user) Apache</span></strong>

What I did was pretty simple. I enabled windows authetication on the ARR server so that it gets logged in credentials. Once we get the logged in credentials, we have to set a Request Header with the value of the logged in credentials so that when the proxy makes a request to the backend apache server, this header will be passed and the backend server will be able to read the header and get the user credentials.

For setting a header, I created a simple custom http module and configured it on the reverse proxy server. Below is the code for the module:
<blockquote>
<div><em>using System;</em></div>
<div><em>using System.Security.Principal;</em></div>
<div><em>using System.Web;</em></div>
<div><em>namespace Module</em></div>
<div><em>{</em></div>
<div><em>    public class HttpToHttps : IHttpModule</em></div>
<div><em>    {</em></div>
<div><em>        // In the Init function, register for HttpApplication events by adding your handlers.</em></div>
<div><em>        public void Init(HttpApplication application)</em></div>
<div><em>        {</em></div>
<div><em>            application.PostAuthenticateRequest += new EventHandler(this.OnAuthorizeRequest);</em></div>
<div><em>        }</em></div>
<div><em>        public void Dispose()</em></div>
<div><em>        {</em></div>
<div><em>        }</em></div>
<div><em>        public void OnAuthorizeRequest(object sender, EventArgs e)</em></div>
<div><em>        {</em></div>
<div><em>            HttpApplication httpApplication = (HttpApplication)sender;</em></div>
<div><em>            HttpApplication application = (HttpApplication)sender;</em></div>
<div><em>            HttpContext context = application.Context;</em></div>
<div><em>            IIdentity id = HttpContext.Current.User.Identity;</em></div>
<div><em>            if (null != id)</em></div>
<div><em>            {</em></div>
<div><em>                application.Request.Headers.Set("REMOTE_USER", id.Name);</em></div>
<div><em>            }</em></div>
<div><em>        }</em></div>
<div><em>    }</em></div>
<div><em>}</em></div></blockquote>
First we created a rewrite rule to point to the backend server then added this module and tested it out.  Basically what this module does is, as soon as the request arrives with the Kerberos/NTLM token on the reverse proxy, it extracts the logged in user information and sets a custom request header with the value of logged in credentials.  So when the proxy makes a request to the backend server based on the rewrite rule, this header will be passed in request and the backend server can read the header and get the user info. On testing, I could see the <em><strong>REMOTE_USER</strong></em> header in the outbound request from proxy.

Below are the request headers for the request from the Client machine to Proxy server.
<blockquote>
<div><em><span>GET / HTTP/1.1</span></em></div>
<div><em><span>Accept: image/gif, image/jpeg, image/pjpeg, application/x-ms-application, application/xaml+xml, application/x-ms-xbap, */*</span></em></div>
<div><em><span>Accept-Language: en-US</span></em></div>
<div><em><span>User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 10.0; WOW64; Trident/7.0; .NET4.0C; .NET4.0E; .NET CLR 2.0.50727; .NET CLR 3.0.30729; .NET CLR 3.5.30729)</span></em></div>
<div><em><span>Accept-Encoding: gzip, deflate</span></em></div>
<div><em><span>Connection: Keep-Alive</span></em></div>
<div><em><span>Host: sudixi418vm</span></em></div>
<div><em><span>Authorization: NTLM TlRMTVNTUAADAAAAGAAYAJYAAABKAUoBrgAAAA4ADgBY<strong>&lt;&lt;trimmed&gt;&gt;</strong></span></em></div></blockquote>
below are the request headers for the outbound request from proxy which is reaching the backend server containing the remote_user header with the logged in user value which was fetched from the custom http module configured on proxy server.
<blockquote>
<div><em><span>GET / HTTP/1.1</span></em></div>
<div><em><span>Accept: image/gif, image/jpeg, image/pjpeg, application/x-ms-application, application/xaml+xml, application/x-ms-xbap, */*</span></em></div>
<div><em><span>Accept-Encoding: gzip, deflate</span></em></div>
<div><em><span>Accept-Language: en-US</span></em></div>
<div><em><span>Authorization: NTLM TlRMTVNTUAADAAAAGAAYAJYAAABKAUoBrgAAAA4ADgBY<strong>&lt;&lt;trimmed&gt;&gt;</strong></span></em></div>
<div><em><span>Host: sudixi483vm</span></em></div>
<div><em><span>Max-Forwards: 10</span></em></div>
<div><em><span>User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 10.0; WOW64; Trident/7.0; .NET4.0C; .NET4.0E; .NET CLR 2.0.50727; .NET CLR 3.0.30729; .NET CLR 3.5.30729)</span></em></div>
<div><em><span>X-Original-URL: /</span></em></div>
<div><em><span><strong>REMOTE_USER: SUDIXI1\Administrator</strong></span></em></div>
<div><em><span>X-Forwarded-For: 192.168.2.50:57639</span></em></div>
<div><em><span>X-ARR-LOG-ID: 1f5e738d-0172-4a8a-8151-7d30337802e9</span></em></div>
<div><em><span>Connection: Keep-Alive</span></em></div></blockquote>
Hope this helps! Happy Coding!!

&nbsp;]]></content:encoded>
    </item>
    <item>
      <title>Kerberos Configuration Manager for IIS Server</title>
      <link>https://docs.microsoft.com/archive/blogs/surajdixit/kerberos-configuration-manager-for-internet-information-services-server</link>
      <pubDate>Wed, 07 Feb 2018 06:36:08 GMT</pubDate>
      <dc:creator><![CDATA[Suraj Dixit]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/surajdixit/?p=85</guid>
      <description><![CDATA[Many of us find troubleshooting Kerberos configured for a website on IIS Server quite a tedious task...]]></description>
      <content:encoded><![CDATA[Many of us find troubleshooting Kerberos configured for a website on IIS Server quite a tedious task since it involves multiple levels of troubleshooting. This blog is meant to demystify the art of troubleshooting Kerberos on IIS Server.

<strong><u>Why is Kerberos painful at times?</u></strong>
<ol>
 	<li>First, understanding Kerberos is quite tricky.</li>
 	<li>Configuration takes a lot of time as we need to look at configuration of IIS server, Domain controller and Client side.</li>
 	<li>Once a site breaks because of some configuration related issues, it’s really difficult to identify the exact cause because of the complexity.</li>
</ol>
<strong><u>Let’s see what exactly happens “Under the Hood”:</u></strong>

At a high level, the following steps needs to be followed to configure Kerberos for a website:

<strong>On IIS Server:</strong>
<ol>
 	<li>Disable all the authentication methods except windows authentication</li>
 	<li>In windows authentication section, in Providers we should see negotiate should be a priority</li>
 	<li>ASP.NET Impersonation should enabled if you want to configure Pass-through Authentication(Kerberos double hop)</li>
 	<li>Based on the Application pool credentials,
<ul>
 	<li>useAppPoolCredentials to true if we are using a custom account</li>
 	<li>useAppPoolCredentials to false and useKernelMode to true if we are using a machine account</li>
</ul>
</li>
</ol>
<strong>On Domain Controller:</strong>
<ol>
 	<li>Based on the Application pool credentials on the IIS we set Service Principle names on the DC.
<ul>
 	<li>If we use a Machine account, set SPNs on Machine account</li>
 	<li>If we use a custom account, set SPNs on custom account</li>
</ul>
</li>
 	<li>The above also depends on whether we are using a hostname or machine name to browse the website</li>
 	<li>Delegation need to be enabled for the Application pool credentials if you want configure pass-through authentication (This tab will come up after we set the SPNs).</li>
</ol>
<strong>On Client Browser(Internet Explorer):</strong>

Based on whether we use hostname or not, we need to add the host/machine name to Trusted sites/Local Intranet Zone.

<span style="text-decoration: underline"><strong>You can find more information regarding Configuration of Kerberos in the following blogs:</strong></span>
<ol>
 	<li><a href="https://blogs.msdn.microsoft.com/chiranth/2013/09/20/all-about-kerberos-the-three-headed-dog-with-respect-to-iis-and-sql/">https://blogs.msdn.microsoft.com/chiranth/2013/09/20/all-about-kerberos-the-three-headed-dog-with-respect-to-iis-and-sql/</a></li>
 	<li><a href="https://blogs.msdn.microsoft.com/chiranth/2014/04/17/setting-up-kerberos-authentication-for-a-website-in-iis/">https://blogs.msdn.microsoft.com/chiranth/2014/04/17/setting-up-kerberos-authentication-for-a-website-in-iis/</a></li>
</ol>
Now just imagine if we can automate the above process through a nifty application which can help us troubleshoot/configure Kerberos in just a few minutes – Is it possible? The good news is that <strong>NOW IT IS POSSIBLE :)</strong>

I have developed a simple troubleshooter “<strong>Kerberos Configuration Manager for IIS</strong>” which allows one to do the following tasks on the server:
<ol>
 	<li>Review the current settings related to Kerberos for any specific website in IIS.
<ul>
 	<li>Checks and displays the site properties</li>
 	<li>Checks and displays Application pool properties like Application pool identity</li>
 	<li>Checks and displays Anonymous authentication properties</li>
 	<li>Checks and displays Basic authentication properties</li>
 	<li>Checks and displays Digest authentication properties</li>
 	<li>Checks and displays ASP.NET Impersonation properties</li>
 	<li>Checks and displays Windows authentication
<ul>
 	<li>whether Windows authentication is enabled or disabled</li>
 	<li>What are the Providers settings</li>
</ul>
</li>
 	<li>Checks and displays Configuration editor settings for windows authentication
<ul>
 	<li>UseAppPoolCredentials settings</li>
 	<li>UseKernelMode settings</li>
</ul>
</li>
 	<li>Based on the Application pool identity,
<ul>
 	<li>Checks for the existing SPNs for that identity and displays them</li>
 	<li>Displays the necessary SPNs required for Kerberos to work</li>
 	<li>Checks and displays existing Delegation settings in case you want to go with the Pass-through authentication.</li>
 	<li>Displays the necessary Delegation settings in case you want to go with the Pass-through authentication.</li>
</ul>
</li>
</ul>
</li>
</ol>
<ol start="2">
 	<li>Configures Kerberos for the affected website:
<ul>
 	<li>Disables Anonymous authentication if enabled</li>
 	<li>Disables Basic authentication if enabled</li>
 	<li>Disables Digest authentication if enabled</li>
 	<li>Disables ASP.NET Impersonation if enabled</li>
 	<li>Enables Windows authentication if disabled
<ul>
 	<li>Once the above is enabled, checks whether we have Negotiate on priority or no. If not, Negotiate is moved to the top</li>
</ul>
</li>
 	<li>Based on the application pool credentials,
<ul>
 	<li>Either it will enable useAppPoolCredentials or disables it</li>
 	<li>Either it will enable useKernelMode or disables it</li>
</ul>
</li>
 	<li>Based on the Application pool identity,
<ul>
 	<li>Checks for the existing SPNs for that identity and displays them</li>
 	<li>Displays the necessary SPNs required for Kerberos to work</li>
 	<li>Checks and displays existing Delegation settings in case you want to go with the Pass-through authentication.</li>
 	<li>Displays the necessary Delegation settings in case you want to go with the Pass-through authentication.</li>
</ul>
</li>
 	<li>Generates the script for setting the required SPNs in the same directory if you want to configure single hop</li>
 	<li>Generates the script for setting the required SPNs and setting the delegation properties for the application pool identity in the same directory if you want to configure Pass-through authentication.</li>
</ul>
</li>
</ol>
<ol start="3">
 	<li>It also has a provision to revert the changes made just in case there is a requirement.</li>
 	<li>It also has a feature of auditing through a log file which would capture the below details:
<ul>
 	<li>Logged in user who used the tool and made changes</li>
 	<li>Timestamp when the changes were made</li>
 	<li>Review, Configure and Revert logs (All settings which were added/modified)</li>
</ul>
</li>
</ol>
The good news is that we have released the Kerberos Configuration Manager v2.0 which supports <strong>reviewing and configuring the Kerberos Pass-through authentication </strong>also (Kerberos Double Hop).

<span style="text-decoration: underline"><strong>Whats new in Kerberos Configuration Manager v2.0 ?</strong></span>
<ol>
 	<li><span>Double Hop Support - Delegation and Impersonation</span></li>
 	<li><span>UI changes</span></li>
 	<li><span>Scroll view for the text area</span></li>
 	<li><span>Application can run as administrator without any intervention</span></li>
 	<li><span>Bug fixes</span></li>
</ol>
<strong><u>Why should I use tool?:</u></strong>
<ol>
 	<li>Troubleshooting Kerberos just becomes much simpler with this tool and it optimizes the time taken to troubleshoot from few hours to few minutes.</li>
 	<li>You can review the Kerberos Configuration for any of your web sites and share the generated log files with support to save precious troubleshooting time.</li>
 	<li>No need to install the tool -  it’s a standalone executable.</li>
 	<li>Disk space utilization is minimal.</li>
 	<li>Open source, free to download and modify.</li>
 	<li>Auditing support which makes troubleshooting Kerberos easier.</li>
</ol>
<span style="text-decoration: underline"><strong>Where do I get it from and how do I use it?</strong></span>

The tool can be downloaded from the open source github repo:

<strong>Latest release: </strong><a href="https://github.com/SurajDixit/KerberosConfigMgrIIS/releases/download/v2.1/KerberosConfigMgrIIS.exe">https://github.com/SurajDixit/KerberosConfigMgrIIS/releases/download/v2.1/KerberosConfigMgrIIS.exe</a>

<strong>All releases : </strong><a href="https://github.com/SurajDixit/KerberosConfigMgrIIS/releases">https://github.com/SurajDixit/KerberosConfigMgrIIS/releases</a>

The GUI has a fairly simple layout with the options to Review, Configure, Generate Script and Revert the Kerberos related configuration settings.

<strong><u>Instructions for use:</u></strong>
<ul>
 	<li>Create a folder called KCMI on the server where <strong>IIS</strong> is installed and copy the executable file “KerberosConfigMgrIIS.exe”.</li>
 	<li>Run the executable “KerberosConfigMgrIIS.exe”.</li>
 	<li>When you execute the file, you will see the below screen:</li>
</ul>
<img src="https://msdnshared.blob.core.windows.net/media/2018/02/1st-271x300.png" alt="" width="271" height="300" class="aligncenter wp-image-385 size-medium" />
<ul>
 	<li>Select the website from the drop down menu for which you want to configure Kerberos.</li>
</ul>
<img src="https://msdnshared.blob.core.windows.net/media/2018/02/28-268x300.png" alt="" width="268" height="300" class="size-medium wp-image-435 aligncenter" />
<ul>
 	<li>Now select from the Radio buttons whether you want to configure the website for Single Hop or Double Hop(Pass Through Authentication) and click on Review.</li>
</ul>
<img src="https://msdnshared.blob.core.windows.net/media/2018/02/39-270x300.png" alt="ddd" width="270" height="300" class="size-medium wp-image-445 aligncenter" />
<ul>
 	<li>Once you click on the Review button you will see the current Kerberos configuration for the selected website.</li>
 	<li>In-between you will see the Dialogue which is shown below to ask whether we are making use of “Hostname” to browse the website?</li>
</ul>
<img src="https://msdnshared.blob.core.windows.net/media/2018/02/46-277x300.png" alt="" width="277" height="300" class="size-medium wp-image-285 aligncenter" />
<ul>
 	<li>If we click “Yes”,  we will see one more Dialogue box to input the hostname. If we click “No”,  we don’t see any dialogue box and execution will continue.</li>
</ul>
<img src="https://msdnshared.blob.core.windows.net/media/2018/02/55-269x300.png" alt="" width="269" height="300" class="size-medium wp-image-295 aligncenter" />
<ul>
 	<li>The Kerberos configuration would show all the recommended and non-recommended settings. Please review it carefully.</li>
</ul>
<img src="https://msdnshared.blob.core.windows.net/media/2018/02/62-273x300.png" alt="" width="273" height="300" class="size-medium wp-image-305 aligncenter" />
<ul>
 	<li>Once you have reviewed the setting and you are ready to “Fix” the problem, please click on “Configure” button to make the necessary changes.</li>
</ul>
<img src="https://msdnshared.blob.core.windows.net/media/2018/02/72-267x300.png" alt="" width="267" height="300" class="size-medium wp-image-315 aligncenter" />
<ul>
 	<li>Once the configuration is implemented, you will see 2 buttons enabled, One is Generate script and other is Revert. Also you will notice that the dropped down will be locked so that we don’t revert the changes for a wrong site by mistake.</li>
</ul>
<img src="https://msdnshared.blob.core.windows.net/media/2018/02/84-265x300.png" alt="" width="265" height="300" class="size-medium wp-image-325 aligncenter" />
<ul>
 	<li>Once you click the Generate Script you will see a .cmd file and .ps1 file (Only if you have selected Pass-Though authentication) in the current folder which has the commands to add SPNs and Set the delegation for the application pool identity user on the Domain controller.</li>
</ul>
<img src="https://msdnshared.blob.core.windows.net/media/2018/02/93-300x114.png" alt="" width="300" height="114" class="size-medium wp-image-335 aligncenter" />
<ul>
 	<li>In case you want to revert the changes, simply click on “Revert” button and all the changes which were made earlier will be reverted back with respect to IIS (Note: If you have executed the .cmd file, it will not be reverted).</li>
</ul>
<img src="https://msdnshared.blob.core.windows.net/media/2018/02/102-268x300.png" alt="" width="268" height="300" class="size-medium wp-image-345 aligncenter" />
<ul>
 	<li>As soon as you start the application, a Log file is generated in the same folder as the executable with the system date timestamp. This log file would capture the timestamp, logged on user and all the series of configuration changes implemented during the session.</li>
</ul>
<img src="https://msdnshared.blob.core.windows.net/media/2018/02/111-300x72.png" alt="" width="300" height="72" class="size-medium wp-image-355 aligncenter" />
<ul>
 	<li>In case you want to review changes for new website, Close the tool and reopen it as administrator and follow the above steps from step# 1.</li>
</ul>
And that’s all, you will have your site configured with Kerberos on IIS!

<strong><span style="text-decoration: underline">Any pre-requisites?</span></strong>
<ol>
 	<li><strong>Operating System :</strong><span> </span>Windows Vista &amp; above</li>
 	<li><strong>.NET Framework  :</strong><span> </span>4.5.2 &amp; above</li>
 	<li><strong>IIS Server Version : </strong>7.5 and above</li>
 	<li>All the modules should be installed related to Kerberos authentication like windows authentication module etc.</li>
</ol>
<strong><u>Feedback:</u></strong>

If you have any feedback, inputs, bugs to report about the tool, please comment below.

Happy Troubleshooting!]]></content:encoded>
    </item>
    <item>
      <title>Drupal : PDOException: SQLSTATE[HY000][2002] on Azure PAAS</title>
      <link>https://docs.microsoft.com/archive/blogs/surajdixit/drupal-pdoexception-sqlstatehy0002002-on-azure-paas</link>
      <pubDate>Wed, 09 Aug 2017 23:34:02 GMT</pubDate>
      <dc:creator><![CDATA[Suraj Dixit]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/surajdixit/?p=66</guid>
      <description><![CDATA[A month back I was trying to browse this site (https://technobytes.azurewebsites.net) which is...]]></description>
      <content:encoded><![CDATA[A month back<span> I was trying to browse this site </span><b>(<a href="https://technobytes.azurewebsites.net/">https://technobytes.azurewebsites.net</a>)</b><span> which is a </span><b>Drupal Website</b><span> and is hosted on </span><b>Azure</b><span> as an </span><b>App Service</b><span> and </span><span> suddenly I could see the below exception. I kind of wondered what happened.</span>

<img src="https://msdnshared.blob.core.windows.net/media/2017/08/azure-PDOException-1024x328.png" alt="" width="1024" height="328" class="size-large wp-image-75 aligncenter" />

I quickly checked that line of code mentioned in the exception but couldn't find much info about exception but I got a hint that cause might be hidden in the<span> </span><b style="background-color: yellow">sites/default/settings.php</b>

I checked the php script and it had all the information about the SQL connection

Now I checked its socket for connecting to the MySQL server and I could see<span> </span><b style="background-color: yellow">127.0.0.1:40456</b>

So I quickly checked the<span> </span><span style="color: #000000;background-color: yellow"><strong>data/mysql/MYSQLCONNSTR_localdb.txt</strong></span><span> </span>to check the connection string and I could see a different port in the socket.

I changed the port in the settings.php which is there in the connection string and the site started working as expected.

<b style="background-color: lightgreen"><u>What actually happened?</u></b>

MySQL runs on a process created on azure called<span> </span><b style="background-color: yellow">mysqld.exe</b>, due to some reason it was recycled i.e. in simple words the process was be killed and re-spawned, and <strong>Port</strong> was changed. And it was updated in the connection string file

<b style="background-color: lightgreen"><u>Resolution:</u></b>

Find out the new Port from<span> </span><b style="background-color: yellow">data/mysql/MYSQLCONNSTR_localdb.txt</b><span> </span>file and update it in your <b style="background-color: yellow">sites/default/settings.php</b> as below

<hr />

<code>$databases['default']['default'] = array(
* 'driver' =&gt; 'pgsql',
* 'database' =&gt; 'databasename',
* 'username' =&gt; 'username',
* 'password' =&gt; 'password',
* 'host' =&gt; 'localhost:<b style="background-color: yellow">port</b>',
* 'prefix' =&gt; '',
* );</code>

<hr />

I hope this helps you.

Happy Coding !]]></content:encoded>
    </item>
    <item>
      <title>C# module for HTTP to HTTPS redirection for custom ports by reading them from AppHost.config</title>
      <link>https://docs.microsoft.com/archive/blogs/surajdixit/c-sharp-http-module-for-http-to-https-for-custom-ports</link>
      <pubDate>Sat, 29 Jul 2017 08:07:44 GMT</pubDate>
      <dc:creator><![CDATA[Suraj Dixit]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/surajdixit/?p=25</guid>
      <description><![CDATA[A week back I was thinking if we can dynamically fetch the custom ports (other than 443) from...]]></description>
      <content:encoded><![CDATA[<em></em>A week back I was thinking if we can dynamically fetch the custom ports (other than 443) from <strong><span style="color: #0000ff">apphost.config </span></strong>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 <strong><span style="color: #0000ff">class library</span></strong> which makes use of <strong><span style="color: #0000ff">Microsoft.Web.Administration.dll </span></strong>and returns <strong><span style="color: #0000ff">Port</span></strong> in integer format. I have referenced this library in the HTTP Module. You can find the code below.

<code><span style="color: #ff0000;padding-left: 30px">using System;
<span style="padding-left: 30px">using Microsoft.Web.Administration;</span>
<span style="padding-left: 30px">public static class ServerMgr</span>
<span style="padding-left: 30px">{
<span style="padding-left: 50px">public static int getPort()</span>
<span style="padding-left: 50px">{</span>
<span style="padding-left: 70px">using (ServerManager serverManager = new ServerManager())</span>
<span style="padding-left: 70px">{</span>
<span style="padding-left: 90px">Configuration config = serverManager.GetApplicationHostConfiguration();</span>
<span style="padding-left: 90px">ConfigurationSection sitesSection = config.GetSection("system.applicationHost/sites");</span>
<span style="padding-left: 90px">ConfigurationElementCollection sitesCollection = sitesSection.GetCollection();</span>
<span style="padding-left: 90px">ConfigurationElement siteElement = FindElement(sitesCollection, "site", "name", @"site2");</span>
<span style="padding-left: 90px">if (siteElement == null) throw new InvalidOperationException("Element not found!");</span>
<span style="padding-left: 90px">ConfigurationElementCollection bindingsCollection = siteElement.GetCollection("bindings");</span>
<span style="padding-left: 90px">ConfigurationElement bindingElement = FindElement(bindingsCollection, "binding", "protocol", @"https");</span>
<span style="padding-left: 90px">if (bindingElement == null) throw new InvalidOperationException("Element not found!");</span>
<span style="padding-left: 90px">string combinedPort = (string)bindingElement["bindingInformation"];</span>
<span style="padding-left: 90px">serverManager.CommitChanges();</span>
<span style="padding-left: 90px">int port = Convert.ToInt32(string.Join(null, System.Text.RegularExpressions.Regex.Split(combinedPort,"[^\\d]")));</span>
<span style="padding-left: 90px">return port;</span>
<span style="padding-left: 70px">}</span>
<span style="padding-left: 50px">}</span>
<span style="padding-left: 50px">private static ConfigurationElement FindElement(ConfigurationElementCollection collection, string elementTagName, params string[] keyValues)</span>
<span style="padding-left: 50px">{</span>
<span style="padding-left: 70px">foreach (ConfigurationElement element in collection)</span>
<span style="padding-left: 70px">{</span>
<span style="padding-left: 90px">if (String.Equals(element.ElementTagName, elementTagName, StringComparison.OrdinalIgnoreCase))</span>
<span style="padding-left: 90px">{</span>
<span style="padding-left: 110px">bool matches = true;</span>
<span style="padding-left: 110px">for (int i = 0; i &lt; keyValues.Length; i += 2)</span>
<span style="padding-left: 110px">{</span>
<span style="padding-left: 130px">object o = element.GetAttributeValue(keyValues[i]);</span>
<span style="padding-left: 130px">string value = null;</span>
<span style="padding-left: 130px">if (o != null)</span>
<span style="padding-left: 130px">{</span>
<span style="padding-left: 150px">value = o.ToString();</span>
<span style="padding-left: 130px">}</span>
<span style="padding-left: 130px">if (!String.Equals(value, keyValues[i + 1], StringComparison.OrdinalIgnoreCase))</span>
<span style="padding-left: 130px">{</span>
<span style="padding-left: 150px">matches = false;/span&gt;
<span style="padding-left: 150px">break;/span&gt;
<span style="padding-left: 130px">}</span>
<span style="padding-left: 110px">}</span>
<span style="padding-left: 110px">if (matches)</span>
<span style="padding-left: 110px">{</span>
<span style="padding-left: 130px">return element;</span>
<span style="padding-left: 110px">}</span>
<span style="padding-left: 90px">}</span>
<span style="padding-left: 70px">}</span>
<span style="padding-left: 70px">return null;</span>
<span style="padding-left: 50px">}</span>
<span style="padding-left: 30px">}</span></span></span></span></span></code>

Below is the code for <strong><span style="color: #0000ff">HTTP module</span></strong> 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 <span style="color: #0000ff"><em>application.BeginRequest</em></span> which does the trick when the first request begins.

<code><span style="color: #ff0000;padding-left: 30px">using System;
<span style="padding-left: 30px">using System.Web;</span>
<span style="padding-left: 30px">namespace Module</span>
<span style="padding-left: 30px">{</span>
<span style="padding-left: 50px">public class HttpToHttps : IHttpModule</span>
<span style="padding-left: 50px">{</span>
<span style="padding-left: 70px">// In the Init function, register for HttpApplication events by adding your handlers.</span>
<span style="padding-left: 70px">public void Init(HttpApplication application)</span>
<span style="padding-left: 70px">{</span>
<span style="padding-left: 90px">application.BeginRequest += new EventHandler(this.OnBeginRequest);</span>
<span style="padding-left: 70px">}</span>
<span style="padding-left: 70px">public void Dispose()</span>
<span style="padding-left: 70px">{</span>
<span style="padding-left: 70px">}</span>
<span style="padding-left: 70px">public void OnBeginRequest(object sender, EventArgs e)</span>
<span style="padding-left: 70px">{</span>
<span style="padding-left: 90px">// Create HttpApplication and HttpContext objects to access request and response properties.</span>
<span style="padding-left: 90px">HttpApplication application = (HttpApplication)sender;</span>
<span style="padding-left: 90px">HttpContext context = application.Context;</span>
<span style="padding-left: 90px">if (!application.Request.IsSecureConnection)</span>
<span style="padding-left: 90px">{</span>
<span style="padding-left: 110px">string serverName = HttpUtility.UrlEncode(application.Request.ServerVariables["SERVER_NAME"]);</span>
<span style="padding-left: 110px">string filePath = application.Request.FilePath;</span>
<span style="padding-left: 110px">int customPort = ServerMgr.getPort();</span>
<span style="padding-left: 110px">application.Response.Redirect("https://" + serverName + ":" + customPort + filePath);</span>
<span style="padding-left: 90px">}</span>
<span style="padding-left: 70px">}</span>
<span style="padding-left: 50px">}</span>
<span style="padding-left: 30px">}</span></span></code>

Just register this module in your <em>web.config</em> so that it is fired as soon as the request reaches the IIS server.<em> Y</em>ou can do it from IIS manager as well.

Below are the steps to register the module in your site.
<ul>
 	<li>Make sure all the 3 DLLs (Getport.dll, HttpToHttps.dll and Microsost.Web.Administration.dll) are in the bin folder of website location</li>
 	<li>Open IIS manager and select your site.</li>
 	<li>In the<span> </span><strong>Connections</strong><span> </span>pane, expand the server name, expand<span> </span><strong>Sites</strong>, and then go to the Web site or application to which you want to add a managed module.</li>
 	<li>In the<span> </span><strong>Home</strong><span> </span>pane, double-click<span> </span><strong>Modules</strong>.<a href="https://docs.microsoft.com/en-us/iis/configuration/system.webserver/modules/add/_static/image1.png"></a><a href="https://docs.microsoft.com/en-us/iis/configuration/system.webserver/modules/add/_static/image1.png"></a></li>
</ul>
<p style="padding-left: 60px"><a href="https://docs.microsoft.com/en-us/iis/configuration/system.webserver/modules/add/_static/image1.png"><img src="https://docs.microsoft.com/en-us/iis/configuration/system.webserver/modules/add/_static/image2.png" alt="" /></a></p>

<ul>
 	<li>In the Actions pane, click<span> </span><strong>Add Managed Module</strong>.</li>
 	<li>In the<span> </span><strong>Add Managed Module</strong><span> </span>dialog box, enter the name of the managed module in the<span> </span><strong>Name</strong><span> </span>box, and then enter or select the module's .NET Framework fully-qualified type in the Type box.</li>
 	<li>Select the<span> </span><strong>Invoke only for requests to ASP.NET applications or managed handlers</strong><span> </span>option if you want the module to respond only to managed requests.</li>
</ul>
<p style="padding-left: 60px"><a href="https://msdnshared.blob.core.windows.net/media/2017/07/managedmodule.png"><img src="https://msdnshared.blob.core.windows.net/media/2017/07/managedmodule.png" alt="" /></a></p>

<ul>
 	<li>Click<span> </span><strong>OK</strong>.</li>
</ul>
I have provided the link below to download both class library and HTTP Module in case if you want to test it.

<a href="https://msdnshared.blob.core.windows.net/media/2017/07/Code1.zip">Code.zip</a>

Happy Coding !]]></content:encoded>
    </item>
  </channel>
</rss>