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
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!
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
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.
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!