2

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 Answers 3

14

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.

Sign up to request clarification or add additional context in comments.

1 Comment

Duh - I could swear I tried this. Simple solution, bundles are now ok. I still have the problem of the trailing slash needed to be enforced in the started controller only. Event when your solution is working fine, adding the trailing slash to ALL urls in the app breaks the root for the content that is referenced using virtual paths. This is from the question I published in the asp.net forums Particularly on this reply I'm marking this as the accepted answer.
0

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!

4 Comments

The problem is not the querystring but the bundles not being neither a file nor a directory. I resolved this problem with a permanent redirect in the main controller that ensure the trailing slash in the event the user forgets it.
@RacielR. Can you post your solution as an answer and accept it?
I updated my question with the work around that is currently working for me. I'm letting the question open because its scope is broader than my problem actually.
Raciel R, I think that cheesemacfly's solution is a great idea. Wouldn't checking if there is a querystring be a good way to tell if it's an exception that should be ignored? One thing is that the negate option on the match won't work for the root path (www.domain.com), so I would combine your two rules. But other than that, I like it. I'll still post an example on how to exclude certain paths.
0

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

1 Comment

It won't install on my server. I have IIS7.5 with .NET 4.5 running, this applies to .NET 4.0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.