Handing MVC paths with dots in the path

A friend of mine asked me recently how to handle a situation with a dot (.) in the path for an MVC project.  The path looked something like this:

http://domain.com/aspnet/CLR4.0

The MVC routes didn’t work for this path and the standard IIS 404 handler served up the page instead. However, the following URL did work:

http://domain.com/aspnet/CLR4.0/

The only difference is the trailing slash. For anyone that runs into the same situation, here’s the reason and the solution.

What causes this inconsistency

The issue with the first path is that IIS can’t tell if the path is a file or folder. In fact, it looks so much like a file with an extension of .0 then that’s what IIS assumes that it is. However, the second path is fine because the trailing slash makes it obvious that it’s a folder.

We can’t just assign a wildcard handler to MVC in IIS for all file types because that will break files like .css, .js, .png, and other files are processed as static images.

Note that this would not be an issue if the dot is in a different part of the path. It’s only an issue if the dot is in the last section. For example, the following would be fine:

http://domain.com/aspnet/CLR4.0/info

So how do we resolve it?

As I mentioned, we can’t simply set a wildcard handler on it because it will break other necessary static files. So have about three options:

  1. You could always change the paths in your application. If you’re early enough in the development cycle that may be an option for you.
  2. Add file handlers for all extension types that you may have. For example, add a handler for .0, another for .1, etc.
  3. Use a URL rewriter like IIS URL Rewrite to watch for a particular pattern and append the training slash.

Let’s look at these second two options. I’ll mention now up front that the URL Rewrite solution is probably the best bet, although I’ll cover both in case you prefer the handler method.

Http Handler Solution

You can handle specific extensions by adding a handler for each possible extension that you’ll support. This maps to System.Web.UI.PageHandlerFactory so that ASP.NET MVC has a handle on it and you can create an MVC route for it. This would apply to ASP.NET, PHP, or other frameworks too.

C:\Windows\System32\inetsrv\appcmd.exe set config "Sitename" -section:system.webServer/handlers /+"[name='.0-PageHandlerFactory-Integrated-4.0',path='*.0',verb='GET,HEAD,POST,DEBUG',type='System.Web.UI.PageHandlerFactory',preCondition='integratedMode']" /commit:apphost
C:\Windows\System32\inetsrv\appcmd.exe set config "SiteName" -section:system.webServer/handlers /+"[name='.1-PageHandlerFactory-Integrated-4.0',path='*.1',verb='GET,HEAD,POST,DEBUG',type='System.Web.UI.PageHandlerFactory',preCondition='integratedMode']" /commit:apphost

Run this appcmd command from the command prompt to create the handlers.

Make sure to update “Sitename” with your own site name, or leave it off to make it a server-wide change. And you can update ‘*.0’, ‘*.1’ to your extensions.

If you do create the site-level rule, make sure to save your web.config back to your source control so that you don’t overwrite it on your next site update.

IIS URL Rewrite Solution

Probably the best solution, and the one that my friend used in this case, is to use URL Rewrite to add a trailing slash when needed. The advantage of this is that you can use a more general pattern to redirect the URL rather than a bunch of handlers for each specific extension.

This assumes that you have IIS 7.0 or greater and that you have URL Rewrite installed. If you’re not familiar with URL Rewrite, check out the URL Rewrite articles on my blog (start with this one).

Note: If you want, you can skip this section and jump right to the next section for an easier way to do this using URL Rewrite’s rule wizard.

The following rule watches for a pattern of exactly “something.{digits}” (without a trailing slash). If it finds it then it performs a redirect and appends the trailing slash. It also confirms that it’s not a file or directory that exists on disk.

<rule name="Add trailing slash for some URLs" stopProcessing="true">
<match url="^(.*\.(\d)+)$" />
<conditions>
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
</conditions>
<action type="Redirect" url="{R:1}/" />
</rule>

To apply this rule, using IIS Manager you can create a dummy rule as a placeholder and then edit web.config and replace your placeholder rule with this rule. If this still doesn’t make sense then be sure to review the articles I mentioned above. The configuration location is in <configuration><system.webServer><rules><rule>

An added benefit of this rule is that you’ll make the search engines happy by having just one path for each page, rather than possibly two with and without the slash. This will help with your SEO rankings.

I didn’t think of it at the time but just now I realized that you could use a general match url pattern of “.(*[^/])” and it will work for you too. The reason is that the check for IsFile and IsDirectory will ensure that your static images will continue to be served directly from disk so you won’t break them. So feel free to use <match url="(.*[^/])" /> instead if you want to add the trailing slash for all paths that don’t have them.

The Real Easy Solution (URL Rewrite wizard)

In fact, to make this easier yet, you can use URL Rewrite’s existing rule wizard to add the trailing slash. You must apply this at the site or folder level since the trailing slash wizard doesn’t exist at the server level.

  1. From IIS Manager, open URL Rewrite at the site or folder level.
    image
  2. Click “Add Rule(s)…” from the Actions pane.
    SNAGHTML14017621
  3. Select “Append or remove the trailing slash symbol” rule.
    image
  4. Use the default option of “Appended if it does not exist”
  5. Press OK.

That’s it! You’ll have a rule added which will append the trailing slash for all non-physical file or folder paths that don’t already have the trailing slash. Not only will it handle dots in the path but the search engines will be happy too.

As with the http extension solution, if you create this as a site or folder-level rule, it will be applied to your web.config file. Make sure to update web.config in your source control so that you don’t lose your changes on your next site deployment.

No Comments