Processing extension-less files with IIS 6.0 and ASP.NET


The problem

As part of a Single Sign-On implementation with a 3rd party system using SAML 2.0, the user was being redirected to a URL looking like https://mydomain.com/Profile/SAML2/Redirect/SSO?SAMLRequest=… which is the standard for a Shibboleth implementation of SAML 2.0.

This is all good if you are using a web server such as Apache which doesn’t really care if files have an extension or not and for which URL rewriting is common and easy to implement. The problem with IIS 6, is that the file will not be served by IIS and even if it was, it couldn’t be processed by the ASP.Net ISAPI filter because it doesn’t have an extension registered with this filter.

Solutions

In both cases, IIS needs to be configured to process extension-less files. However, on the ASP.NET side, there are 2 solutions that can be implemented to solve this problem. The first one uses the URL redirect feature of IIS and the second one uses URL Rewriting in ASP.NET. For the end user, both approaches will have the same result but depending on your situation you may want to pick one or the other depending on the implementation and maintenance constraints.

Security and performance warning

The settings described below have both security and performance implications. Therefore, it is important to apply these changes only on the directories or virtual directories at the lowest level possible and not at the website level (unless really necessary).

Solution 1 – Configuring URL redirect in IIS

If a redirection is not an issue, this is the easiest solution to implement. There are several drawbacks to consider:

  • The URL the end user will end on will be different than the original target URL. This is usually just a cosmetic thing and shouldn’t matter much.
  • Some search engines do not like redirects.
  • If there are a lot of extension-less files that need to be accessible through IIS, this will become a cumbersome process because each individual file needs to be configured in IIS. In our particular case, this wasn’t an issue because we had a single file to handle.

You can accomplish this solution with a few steps:

  1. Create an empty file with the name of the target (e.g. SSO)
  2. Upload the ASP.NET version of the file which will be the one processed by IIS (e.g. SSO.aspx)
  3. Right-click on the file from the IIS management console and open the Properties window
  4. Select the A redirection to a URL radio button
  5. Enter the new URL (https://mydomain.com/Profile/SAML2/Redirect/SSO.aspx$Q) in the Redirect to text box. The $Q part of the URL is explained below in the “Dealing with query strings” section
  6. make sure that The exact URL entered above and A permanent redirection for this resource radio buttons are selected

redirect

Dealing with query strings

In our particular case, the URL our users are being sent to contains a query string. If you just enter the URL of the new page to go to, the query string will be lost. To solve this problem, you just append $Q (dollar sign and capital letter Q) at the end of the URL and IIS will substitute it with the actual query string when doing the redirect.

Solution 2 – URL Rewriting

URL rewriting is a little cleaner from the user’s point of view because there is no redirection or URL change on the browser side. In addition to this, it also allows us to create a catch-all solution to be able to process all extension-less files in a directory with a single configuration change. If we add new files, they will automatically be processed in the same way.

Configuring IIS to serve extension-less files

By default, IIS 6 does not process files that do not have an extension. The first step will be to change this behavior by creating a new MIME type. MIME types are created in the HTTP Headers tab of the directory’s or website’s Properties window:

1. click on the MIME Types… button to view the existing MIME Types
http_header

2. Click on the Add… button to create a new MIME type
mime_types

3. Enter the Extension and MIME Type as shown on the screenshot below
image

4. Click OK to close all the MIME windows

Wildcard Mapping

Now that IIS will process extension-less files, we need to make sure that those files are processed by the asp.net ISAPI filter. To do this, we need to create a wildcard mapping.

  1. On the WebSite or Virtual Directory Properties window, go to the Home Directory tab and click on the Configuration… button.
    image
  2. On the Application Configuration window, make sure you are on the Mappings tab and click on the Insert… button in the Wildcard application maps section
    image
  3. Browse to the aspnet_isapi.dll file for the .Net Framework 2.0. Also make sure that the Verify that file exists checkbox is unchecked
    image
  4. Click OK and we are done with this step

URL Rewriting using an HTTPModule

After setting up the extension mapping, all files in that directory will be passed through the ASP.NET processor before being served by IIS but they will not be treated as ASP.NET files because of their lack of extension. If we were to stop here, the actual inline C# or VB.NET code would be served by IIS instead of being processed by ASP.NET.

To resolve this issue, we are going to use a trick called URL rewriting using an ASP.NET feature called HTTP Modules. For this, we need to create the module and then modify our web.config to add the module to the page lifecycle.

The HTTP Module:

   1: using System.Web;
   2:
   3: public class aspneturlModule : System.Web.IHttpModule
   4: {
   5:     public void Init( System.Web.HttpApplication context )
   6:     {
   7:         context.BeginRequest += new System.EventHandler(this.BaseModuleRewriter_BeginRequest);
   8:     }
   9:
  10:     private void BaseModuleRewriter_BeginRequest(object sender, System.EventArgs e)
  11:     {
  12:         HttpApplication app = (HttpApplication)sender;
  13:         string requestedPage = app.Request.RawUrl;
  14:         string appVirtualPath = app.Request.ApplicationPath;
  15:
  16:         if (requestedPage.Length >= appVirtualPath.Length)
  17:         {
  18:             if (requestedPage.Substring(0, appVirtualPath.Length - 1).ToLower() == appVirtualPath.ToLower())
  19:                 requestedPage = requestedPage.Substring(appVirtualPath.Length);
  20:             else
  21:                 requestedPage = string.Format("{0}.aspx?{1}", app.Request.FilePath, app.Request.QueryString.ToString());
  22:         }
  23:
  24:         HttpContext.Current.RewritePath(requestedPage);
  25:     }
  26:
  27:     public void Dispose()
  28:     {}
  29: }

The code presented above is a very simple version of an HTTP Module doing the URL rewriting for our case. This is just to illustrate how such a module would be created but there are a lot of different scenarios that may need to be handled differently.

After building the module, place the resulting library file (e.g. HTTPModule.dll) in the bin folder of the Website or Virtual Directory. If there is no bin folder, create it.

The web.config

We now need to reference this module in the web.config. Open the web.config file and locate the section about httpModules. Then, add our new module like this:

   1: <httpModules>
   2:     […] (other httpModules if any)
   3:     <add type="HttpModule.aspneturlModule" name="HttpModule" />
   4: </httpModules>

We are all set. As opposed to the first solution presented, there is no need to create an empty file without extension and the user will not be redirected to a .aspx file. It all happens behind the scenes.

Advertisements

2 Responses to Processing extension-less files with IIS 6.0 and ASP.NET

  1. Pramod says:

    Though I have been using 3rd party url rewriters, I have been trying to find out how extension-less urls work in the background using ASP.net.

    Brilliant article and well presented. Will get on cracking with it right away to build a custom url rewriter. Thanks a ton.

  2. benoit808 says:

    Thank you Pramod. Glad you find it usefull

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: