2
votes

I'm hosting my mvc4 application in a virtual path under an existing site:

ie: http://www.mysite.com/myApp

There is a well-known problem with relative paths being broken if the trailing slash is not provided in the URL. So if the user types the URL as I did above, scripts, styles etc that are using a relative path are not going to be found.

If a trailing slash is provided, everything is ok.

To resolve this problem I installed URL Rewrite (http://www.iis.net/downloads/microsoft/url-rewrite) and added the rule to append the trailing slash if not present. This is a pre-defined rule that looks like:

<rewrite>
<rules>
    <rule name="AddTrailingSlashRule1" stopProcessing="true">
        <match url="(.*[^/])$" />
        <conditions>
            <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
            <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
        </conditions>
        <action type="Redirect" url="{R:1}/" />
    </rule>
</rules>

So far so good, the only problem is that this is now breaking the bundles by adding a trailing slash between the bundle name/url and the chache busting:

ie:

http://www.mysite.com/myApp/bundles/myBundle/?v=8_EQPT2vzBgg4HcGhkeTQpLE1flm2VOsp3A1ZEy-C3k1

(Note the / between myBundle and ?v=8....)

I have tried excluding "bundles" from the conditions, but I had no luck.

I would like to know how I can either exclude certain paths from the conditions (not all my bundles are using "bundles" on the path) or maybe a simpler rule that allow me to add the trailing slash for the only case I need to care about: when the user forgets to type it at the end of my app url.

Thanks, R.

UPDATE

I just added a permanent redirection condition to my main controller -the one that is more susceptible to be typed by the user directly on the address bar. This is resolving my issue. I'm letting the question open just in case someone came up with a better idea by either tweaking the route engine or using a URL Rewrite.

This is the code:

public ActionResult Index()
{
    if (!Request.Path.EndsWith("/"))
        return RedirectPermanent(Request.Url.ToString() + "/");
    return View();
}
3

3 Answers

14
votes

Here's how to add an exclusion of a folder:

<rule name="AddTrailingSlashRule1" stopProcessing="true">
   <match url="(.*[^/])$" />
   <conditions>
      <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
      <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
      <add input="{URL}" pattern="myBundle$" negate="true" />
   </conditions>
   <action type="Redirect" url="{R:1}/" redirectType="Found" />
</rule>

Simply add new {URL} lines for your exclusions. This example 'ends with' myBundle, but you could use the following instead:

<add input="{URL}" pattern="/bundles/" negate="true" />

That will perform a contains search instead since it doesn't check for a start (^) or end ($).

And if you want to reverse the logic to only include certain paths then remove the negate="true" on the {URL} line, and set the pattern to what you want to include.

0
votes

If you want to prevent this rule from happening when a query string is submitted you can use a condition as follow:

<rule name="Add Trailing Slash" stopProcessing="true">
    <match url="^(.*)/$" negate="true" />
    <action type="Redirect" url="{R:0}/" />
    <conditions>
        <add input="{QUERY_STRING}" pattern="(.+)" negate="true" />
    </conditions>
</rule>

The condition will make sure this rule is not executed (negate="true") when (.+) (at least on character) is true against the query string.

I also changed the match to use a negate form that seems more clear and appropriate to me, but if your rule works for you, keep it the way it is!

0
votes

This sounds like one of the symptoms that installing this fix is supposed to fix. http://support.microsoft.com/kb/2520479