It’s generally a best practice to add a backslash to your URLs, for performance reasons (let’s get back to that later in another post). There are several ways to do it, but the best/simplest way, IMO, is using UrlRewrite module. In most of the case, processing the Urls before it reaching the server code will be most effective, and here by using UrlRewrite we trust IIS to do the right thing. Our application does not even need to know about it. It’s also a matter of reusable. You can simply copy a working, well tested rule to another sites without having to worry much about compatibility.
Before getting started, it’s worth noting that UrlRewrite is an IIS module which is not installed by default, if you want to use it, then you would have to install it explicitly. Download and install it from https://www.iis.net/downloads/microsoft/url-rewrite .
And then we can simple add rules to <system.webServer><rewrite><rules>
section in web.config. For the purpose of this post, this rule should be enough:
<rule name="Add 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>
If you are new to UrlRewrite, may be it’s useful to explain a bit on the rule. Here we want to add a rule which matches every url, except the urls which already end with backslash (/) already.
However we don’t want to redirect every url, even if they do not end with backslash. The two exceptions are files, and directories, and for that purpose we added to condition. UrlRewrite provides matchType
for files and directories as above, and by adding negate="true"
we tell UrlRewrite to exclude a Url from this rule if it matches this conditions.
The final part of the rule is the action
applied to the matching urls. Here we simply do a permanent redirect – HTTP code 301. The url redirected to is {R:1}/
which is quite interesting. The match condition (.*[^/])$
was a regex expression, and here we are saying redirect to the same url, but with the ending backslash. Now you can simply try the new rule on your website.
Pretty cool, huh?
But it’s not the end of it. What if you want to exclude a path from the redirection? There are special paths that might not work properly with the ending backslash. There are two way to do it. You can add another rule which excludes the special urls from being processed by the rule we added.
<rule name="special passthrough" stopProcessing="true"> <match url="^(login|episerver|util)/" ignoreCase="true" /> <action type="None" /> </rule>
Notice `stopProcessing=”true”` ? Well, it tells UrlRewrite to stop processing any rules below. (It’s worth mentioning that UrlRewrite process rules sequentially, so first rule in the <rules>
will be processed first, and so on and so forth). By adding this rule, we make a special passthrough for any urls which match login/, episerver/ or util/ path.
But it’s not the only way. We can also add a condition to the original rule to tell UrlRewrite to exclude specific paths from being processed by the rule. Simple add this to <conditions>
<add input="{URL}" pattern="^/(Login|episerver|util)" negate="true"/>
And that’s it, my friends.
UrlRewrite is actually cool and useful than you might think it could be – I hope to get back to it in near future with more blog posts.
I know this is an old post…however I have a question.
How can you create a rule which also validates any query parameters?
E.g. shop/path1/path2?test=test