| Liquid Development Is What I Do
Seb Nilsson

IIS URL Rewrite-Rules Skipping Files-types

IIS Welcome

If you need to put in a rule for the IIS URL Rewrite Module, but need the rule to skip some file-endings and/or targets that are directories or actual files on disk, this is the post for you.

Following some SEO best-practices that tells us to use trailing slashes on our URLs I used the IIS Manager and added the IIS URL Rewrite-module's built-in rule "Append or remove the trailing slash symbol", which creates the following rule:

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

This rule takes into account and doesn't apply the rule to files and directories that exists on disk. But there is a big problem with this generic rule.

If you are dynamically serving up files with extensions, then an URL like:

will become:

Adding conditions for specific file-endings

To solve this you can add conditions for certain file-endings, like .html and .aspx:

  <!-- ... -->
  <add input="{REQUEST_FILENAME}" pattern="(.*?)\.html$" negate="true" />
  <add input="{REQUEST_FILENAME}" pattern="(.*?)\.aspx$" negate="true" />

Since the rules above already don't apply for files physically on disk, you don't need to add file-endings like .css, .png or .js.

Update: Match ANY file-ending

If you want to match just any file-ending at all, you use the following pattern:

  <!-- ... -->
  <add input="{URL}" pattern=".*/[^.]*\.[\d\w]+$" negate="true" />

Guidelines for URI Design

Jacob Gillespie has worked on a post concerning URL Guidelines, that underwent much revision and was posted as a guest post on CSS-Tricks named Guidelines for URI Design.

Clean URIs are one component of a clean website, and it is an important one. The majority of end-user access to the Internet involves a URI, and whether or not the user actually enters the URI, they are working with one nonetheless.

Here is an outtake of the general principles of the article:

  • A URI must represent an object, uniquely and permanently - The URI must be unique so that it is a one-to-one match – one URI per one data object.
  • Be as human-friendly as possible - URIs should be designed with the end user in mind. SEO and ease of development should come second.
  • Consistency - URIs across a site must be consistent in format. Once you pick your URI structure, be consistent and follow it!
  • “Hackable” URIs - Related to consistency, URIs should be structured so that they are intelligibly “hackable” or changeable.
  • Keywords - The URI should be composed of keywords that are important to the content of the page. So, if the URI is for a blog post that has a long title, only the words important to the content of the page should be in the URI.

When it comes to technical details, here are their concerned bullet-points:

  • No WWW - The www. should be dropped from the website URI, as it is unnecessary typing and violates the rules of being as human-friendly as possible and not including unnecessary information in the URI.
  • Format - Google News has some interesting requirements for webpages that want to be listed in the Google News results – Google requires at least a 3-digit unique number.
  • All lowercase - All characters must be lowercase. Attempting to describe a URI to someone when mixed case is involved is next to impossible.
  • URI identifiers should be made URI friendly - A URI might contain the title of a post, and that title might contain characters that are not URI-friendly. That post title must therefore be made URI friendly. [...] Spaces should be replaced with hyphens.

Scott Mitchell has written an article on about Techniques for Preventing Duplicate URLs in Your Website.

A key tenet of search engine optimization is URL normalization, or URL canonicalization. URL normalization is the process of eliminating duplicate URLs in your website. This article explores four different ways to implement URL normalization in your ASP.NET website.

The important subjects of this article are the following:

  • First Things First: Deciding on a Canonical URL Format - Before we examine techniques for normalizing URLs, and certainly before such techniques can be implemented, we must first decide on a canonical URL format.
  • URL Normalization Using Permanent Redirects - [...] when a search engine spider receives a 301 status it updates its index with the new URL. Therefore, if anytime a request comes in for a non-canonical URL we immediately issue a permanent redirect to the same page but use the canonical form then a search engine spider crawling our site will only maintain the canonical form in its index.
  • Issuing Permanent Redirects From ASP.NET - Every time an incoming request is handled by the ASP.NET engine, it raises the BeginRequest event. You can execute code in response to this event by creating an HTTP Module or by creating the Application_BeginRequest event handler in Global.asax.
  • Rewriting URLs Into Canonical Form Using IIS 7's URL Rewrite Module - Shortly after releasing IIS 7, Microsoft created and released a free URL Rewrite Module. The URL Rewrite Module makes it easy to define URL rewriting rules in your Web.config file.
  • Rewriting URLs Into Canonical Form Using ISAPI_Rewrite - Microsoft's URL Rewriter Module is a great choice if you are using IIS 7, but if you are using previous version of IIS you're out of luck.
  • Telling Search Engine Spiders Your Canonical Form In Markup - Consider a URL that may include querystring parameters that don't affect the content rendered on the page or only affect non-essential parts of the page.
    In the case of YouTube, all video pages specify a <link> element like so, regardless of whether the querystring includes just the videoId or the videoId and other parameters:
    <link rel="canonical" href="/watch?v=videoId">

ASP.NET Request Paths Reference

I decided to write down and document for myself the different paths provided by ASP.NET, to get a grip on the subject and a reference to turn to.

The path I will be requesting is:

This will be an ASP.NET-application named MyApplication in the IIS.


Here is the result returned by the Request-property of the page, which is a HttpRequest.

/MyApplication - Gets the ASP.NET application's virtual application root path on the server.

~/MyFolder/MyPage.aspx - Gets the virtual path of the application root and makes it relative by using the tilde (~) notation for the application root (as in "~/page.aspx").

/MyApplication/MyFolder/MyPage.aspx - Gets the virtual path of the current request.

/MyApplication/MyFolder/MyPage.aspx - Gets the virtual path of the current request.

/MyApplication/MyFolder/MyPage.aspx - Gets the virtual path of the current request.

- Gets additional path information for a resource with a URL extension.

C:\Visual Studio Projects\MyApplication\ - Gets the physical file system path of the currently executing server application's root directory.

C:\Visual Studio Projects\MyApplication\MyFolder\MyPage.aspx - Gets the physical file system path corresponding to the requested URL.

/MyApplication/MyFolder/MyPage.aspx?QueryStringKey=QueryStringValue - Gets the ASP.NET application's virtual application root path on the server.


Then there is the property Request.Url that returns a System.Uri , with all its properties. This is an interesting thing to explore as well.

/MyApplication/MyFolder/MyPage.aspx - Gets the absolute path of the URI.

Request.Url.AbsoluteUri: - Gets the absolute URI.

Request.Url.DnsSafeHost: - Gets an unescaped host name that is safe to use for DNS resolution.

Request.Url.Host: - Gets the host component of this instance.

/MyApplication/MyFolder/MyPage.aspx - Gets a local operating-system representation of a file name.

Request.Url.OriginalString: - Gets the original URI string that was passed to the Uri constructor.

/MyApplication/MyFolder/MyPage.aspx?QueryStringKey=QueryStringValue - Gets the AbsolutePath and Query properties separated by a question mark (?).

?QueryStringKey=QueryStringValue - Gets any query information included in the specified URI.

Request.Url.ToString(): - Gets a canonical string representation for the specified Uri instance.

Request also has the property Request.UrlReferrer which is of the type System.Uri and has the same properties as Request.Url. It has the following description: Gets information about the URL of the client's previous request that linked to the current URL.