• Skip to main content
  • Skip to primary sidebar
  • Skip to secondary sidebar
  • Skip to footer

Coding Still

  • Home
  • About

URL rewriting in IIS7

August 10, 2010 By _tasos 4 Comments

URL rewriting was a weak point for IIS. While Apache Web Server had the mod_rewrite module, for IIS and asp.net web applications not much could be done. Of course, third party solutions existed such as the URL Rewriter or the URL Rewriting HttpModules that provided some functionality for URL rewriting. The drawback here was that in every case the .aspx extension was necessary, so that the request was led to the asp.net engine (The request for http://mydomain.com/style.css is not handled by the asp.net engine in IIS6).

In order to accomplish extension-less URL rewriting to IIS6 or IIS5 you needed to use an ISAPI filter. Although there were some solutions available, in the case of shared hosting servers it was not easy to find one that had such ISAPI filters installed. Read more of this in Scott Guthrie’s article on URL rewriting in asp.net 2.0.

When IIS7 was released, a built-in URL rewriting module appeared which made things much easier for ASP.NET developers. All requests go through the ASP.NET engine. We can now easily perform extension-less URL rewriting tasks. Using regular expressions we can create our rules.

Recently, I made my first set of rules. All ran smoothly except from two basic points. My first approach was to create a rule that the URL http://mydomain.com/contact to be rewritten to http://domain.com/default.aspx?title=contact. A simple rule would be able to complete this task. The rule I came up was:

<rewrite>
  <rules>
    <rule name="Rewrite content">
      <match url="^([._0-9a-z-]+)" />
      <action type="Rewrite" url="default.aspx?title={R:1}" />
    </rule>
  </rules>
</rewrite>

Please notice that in the matching characters is the ‘.’. This complicates things a bit since all requests for .htm, .js, .css were handled by this rule and the default.aspx page loaded with an invalid title in the query string (oops!). One solution is to write rules that wont allow rewriting for the extensions you don’t want to. An other approach that I found more elegant is to change the above rule and if the original URL is an existing file or folder the rewriting rule wont apply. The above rule changed to something like this:

<rewrite>
  <rules>
    <rule name="Rewrite content">
      <match url="^([._0-9a-z-]+)" />
      <conditions logicalGrouping="MatchAll">
        <add matchType="IsFile" negate="true" />
        <add matchType="IsDirectory" negate="true" />
      </conditions>
      <action type="Rewrite" url="default.aspx?title={R:1}" />
  </rule>
</rules>
</rewrite>

The second thing I sot stuck is that the /WebResource.axd?d=... and the /ScriptResource.axd?d=... references that are generated by the asp.net engine would be rewritten. The result was some missing CSS declarations and a JavaScript error that Sys is not defined, which means that the asp.net AJAX engine failed to load. In order to fix this, an extra line is required to the above rule so that all the .axd requests will be excluded by this rule.

<rewrite>
  <rules>
    <rule name="Rewrite content">
      <match url="^([._0-9a-z-]+)" />
      <conditions logicalGrouping="MatchAll">
        <add input="{URL}" negate="true" pattern="\.axd$" />
        <add matchType="IsFile" negate="true" />
        <add matchType="IsDirectory" negate="true" />
      </conditions>
      <action type="Rewrite" url="default.aspx?title={R:1}" />
    </rule>
  </rules>
</rewrite>

I think that this is a rather good approach in the case of an existing web site that URL rewriting must be applied. Telling the IIS to exclude all requests that are actual files not to be processed is a very quick and generic way to avoid the scenario that all static content is mapped to default.aspx. There is a catch though, if there are many broken links to your web page this rule would cause to load the default.aspx more than once. This could easily lead to a performance bottleneck. A safer approach is to add a prefix to your URLs, e.g. http://mydomain.com/content/contact or http://mydomain.com/article/123/my-title. With this rapport your URL rewriting rules will be more solid and hide less surprises. Also, the second suggestion saves you the query to the database to get the id of the article ;-).

Rule examples

Redirect from a non-www URL to its www equivalent.

<rule name="non www to www" enabled="true">
    <match url="(.*)" />
    <conditions>
        <add input="{HTTP_HOST}" negate="true" pattern="^www\.([.a-zA-Z0-9]+)$" />
    </conditions>
    <action type="Redirect" url="http://www.{HTTP_HOST}/{R:0}" appendQueryString="true" redirectType="Permanent" />
</rule>

Remove trailing slash from URL.

<rule name="Remove trailing slash" stopProcessing="true">
    <match url="(.*)/$" />
    <conditions>
        <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
	<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
    </conditions>
    <action type="Redirect" redirectType="Permanent" url="{R:1}" />
</rule>

Redirect to HTTPS

<rule name="HTTP to HTTPS redirect" stopProcessing="true">
    <match url="(.*)" />
    <conditions>
        <add input="{HTTPS}" pattern="off" ignoreCase="true" />
    </conditions>
    <action type="Redirect" redirectType="Found" url="https://{HTTP_HOST}/{R:1}" />
</rule>

Exclude a specific path from being processed by the existing rules. Note here that such rules should be declared first in order to work.

<rule name="block" stopProcessing="true">
    <match url="^path/that/should/be/blocked.aspx$" />
    <action type="None" />
</rule>

You can also check these links below:

  • http://learn.iis.net/page.aspx/460/using-the-url-rewrite-module/
  • http://learn.iis.net/page.aspx/461/creating-rewrite-rules-for-the-url-rewrite-module/
  • http://weblogs.asp.net/scottgu/archive/2007/02/26/tip-trick-url-rewriting-with-asp-net.aspx
  • http://www.iis.net/learn/extensions/url-rewrite-module/url-rewrite-module-configuration-reference

Filed Under: IIS Tagged With: Regular expressions, Url rewriting

Reader Interactions

Comments

  1. Greg McCarthy says

    December 18, 2012 at 06:51

    Thank you SO much for this very informative article. I had searched so long for the solution to the .axd files being re-written. My site is running with AJAX and URL rewrite working hand-in-hand. Cheers!

    Reply
  2. Hani says

    October 19, 2013 at 03:59

    Kindly note that i need to exclude all JPG, JS, CSS, …
    i am using ASP classic and here are the rules created using the wizard of URL Friendly Template

    please correct it for me

    Reply
  3. _tasos says

    October 19, 2013 at 15:52

    Hello Hani, unfortunately the rules you posted were blocked and I didn’t get them.

    A similar issue is discussed here: http://stackoverflow.com/questions/11973459/aspnet-static-file-access-with-authentication.

    Reply
  4. Arjen says

    December 20, 2013 at 22:43

    Any ideas how to solve this url rewriting issue?

    http://stackoverflow.com/questions/20708765/how-to-exclude-a-directory-with-iis-url-rewriting

    An jQuery Ajax scripts needs to access code in the /admin/ directory. Any help is welcome!

    Reply

Leave a Reply to Arjen Cancel reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Primary Sidebar

Categories

  • .NET Development
  • ASP.NET
  • Databases
  • Fun
  • IIS
  • JavaScript
  • Web Development

Tags

.NET Core Android ANTLR ASP.NET Ajax ASP.NET Core ASP.NET MVC ASP.NET Web Forms AWS Bouncy Castle Chartjs cli Client info detection Comic Continuous integration CSS Data backup Date handling Firebase Firefox addons Github HigLabo HTML5 Image manipulation jQuery JWT MySQL Nodejs Nuget OAuth Objectionjs OOP openssl Oracle ORM PHP Regular expressions SEO Social media SQL SQL Server UI/UX Url rewriting Videos Visual Studio Web design

Meta

  • Log in
  • Entries feed
  • Comments feed
  • WordPress.org

Secondary Sidebar

Archives

  • July 2020
  • March 2020
  • August 2019
  • December 2018
  • November 2018
  • February 2018
  • August 2016
  • June 2016
  • May 2016
  • February 2016
  • January 2016
  • August 2015
  • July 2015
  • October 2014
  • July 2014
  • November 2013
  • April 2013
  • February 2013
  • January 2013
  • December 2012
  • November 2012
  • August 2012
  • May 2012
  • February 2012
  • December 2011
  • October 2011
  • September 2011
  • August 2011
  • July 2011
  • May 2011
  • April 2011
  • March 2011
  • February 2011
  • January 2011
  • December 2010
  • November 2010
  • October 2010
  • September 2010
  • August 2010
  • July 2010

Footer

Recent Posts

  • Anatomy of an Objection.js model
  • Check your RSA private and public keys
  • Round functions on the Nth digit
  • Send FCM Notifications in C#
  • Jwt Manager
  • Things around the web #5
  • Query JSON data as relational in MySQL
  • Create and sign JWT token with RS256 using the private key
  • Drop all database objects in Oracle
  • Create and deploy a Nuget package

Latest tweets

  • Geekiness Intensifies.. NASA used Three.js to render a real-time simulation of this week's NASA rover landing on M… https://t.co/orgkXnYj9O February 19, 2021 18:12
  • Things I Wished More Developers Knew About Databases https://t.co/h4gfq6NJgo #softwaredevelopment #databases May 3, 2020 12:52
  • How a Few Lines of Code Broke Lots of Packages https://t.co/p7ZSiLY5ca #javascript May 3, 2020 12:48
  • Can someone steal my IP address and use it as their own? https://t.co/HoQ7Z3BG69 January 24, 2020 13:27
  • Organizational complexity is the best predictor of bugs in a software module https://t.co/aUYn9hD4oa #softwaredevelopment January 13, 2020 08:24
  • http://twitter.com/codingstill

Misc Links

  • George Liatsos Blog
  • Plethora Themes
  • C# / VB Converter
  • Higlabo: .NET library for mail, DropBox, Twitter & more

Connect with me

  • GitHub
  • LinkedIn
  • RSS
  • Twitter
  • Stack Overflow

Copyright © 2021 · eleven40 Pro on Genesis Framework · WordPress · Log in