Dots in URL causes 404 with ASP.NET mvc and IIS
Asked Answered
F

18

321

I have a project that requires my URLs have dots in the path. For example I may have a URL such as www.example.com/people/michael.phelps

URLs with the dot generate a 404. My routing is fine. If I pass in michaelphelps, without the dot, then everything works. If I add the dot I get a 404 error. The sample site is running on Windows 7 with IIS8 Express. URLScan is not running.

I tried adding the following to my web.config:

<security>
  <requestFiltering allowDoubleEscaping="true"/>
</security>

Unfortunately that didn't make a difference. I just receive a 404.0 Not Found error.

This is a MVC4 project but I don't think that's relevant. My routing works fine and the parameters I expect are there, until they include a dot.

What do I need to configure so I can have dots in my URL?

Fray answered 30/7, 2012 at 20:9 Comment(7)
Can't believe I spent so much time on this one. The URL works fine if I add a trailing slash. For example, www.example.com/people/michael.phelps/ however without the trailing slash IIS throws a 404 error.Fray
Mark - that is because without the trailing slash, IIS thinks it is a file that it should go and find. Adding the slash has the effect of...this is not a real file. Additionally, the configuration option below tells IIS that if it is not a file, try to route it instead.Albany
I'm having the same problem after I updated my project to mvc 4 + asp.net 4.5.Copro
As a work around I'm using IIS Rewrite to add the trailing slash to my URLs.Fray
This doesn't work for me. The URL works fine with "." within the URL but when it is at the very end it gives an errorGrison
@magic-c0d3r Do you mean when the '.' is the very last character or simply in the last word of the URL?Fray
the period is invoking the static file handler. Set runAllManagedModulesForAllRequests="true" in the web.config and it will work.Lovely
F
391

I got this working by editing my site's HTTP handlers. For my needs this works well and resolves my issue.

I simply added a new HTTP handler that looks for specific path criteria. If the request matches it is correctly sent to .NET for processing. I'm much happier with this solution that the URLRewrite hack or enabling RAMMFAR.

For example to have .NET process the URL www.example.com/people/michael.phelps add the following line to your site's web.config within the system.webServer / handlers element:

<add name="ApiURIs-ISAPI-Integrated-4.0"
     path="/people/*"
     verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS"
     type="System.Web.Handlers.TransferRequestHandler"
     preCondition="integratedMode,runtimeVersionv4.0" />

Edit

There are other posts suggesting that the solution to this issue is RAMMFAR or RunAllManagedModulesForAllRequests. Enabling this option will enable all managed modules for all requests. That means static files such as images, PDFs and everything else will be processed by .NET when they don't need to be. This options is best left off unless you have a specific case for it.

Fray answered 28/8, 2012 at 1:1 Comment(19)
here is a complete example https://mcmap.net/q/98824/-dots-in-url-causes-404-with-asp-net-mvc-and-iis based on this answerGastelum
after adding this with [path="*"] all requests to any static files such as .css, .js fail. I have a custom route that handles urls that look like this "domain/ABCDE.FGHIJ". All of my static files are in my /Content directory. Is there a way to exclude that entire directory from this? setting RAMMFAR to true works but I would like to avoid that overhead.Vendace
This also seems to solve my VERB issue with ExtensionlessUrls: https://mcmap.net/q/100988/-asp-net-handle-put-delete-verbs/203891Majorette
Local IIS works with starting slash, but IIS8 understands route only without first slash.Foolery
Works for me without "preCondition". For what is used?Singspiel
Works locally and on dev machine but once published to live I get a 500 error on the root, no even the route I defined. No description at all or event log for it.Canaanite
After 2 hours of searching on Route Maps I decided to look into IIS :(Discontinuity
This answer fixed my issue. The application I am updating uses decimal values with a significant digit to the right of the decimal point. Setting this handler up for the paths that use this value corrected the errant 404 error that made no sense. It's a good thing I'm bald or I would have pulled all my hair out - LOL.Trestlework
I'm having the same issue as @Vendace ... It blocks the static files. Do you know why? Using MVC4 here.Nainsook
It works in MVC5, but if you put slash in the beginning of the path, it works only when the path is immediately after hostname (it is not relative to app folder). For example path /people/* would work for www.example.com/people/michael.phelps, but not for www.example.com/app/people/michael.phelps. AFAIK there is no way to make the path relative to app.Haply
Same issue as @Vendace and eestein... all static files are blocked... any solution to this "side effect" yet? This answer is not a viable solution for me without a fix for this...Fleeman
It works for MVC 5, and strangely enough it works with for example path="User/Edit/*" too regardless of the sub-path. Which contradicts to what Hogan said (and I thought what he said makes perfect sense). weirdDepth
This solution disables Asp.net OutputCache Feature for me if the url contains a dot.Andrade
This answer has not worked for me at all. I still get a 404 error with the following URL: localhost:50093/Item/GetItem/Some Name./6a00f5f8-c051-4f5c-a74d-eb4a3968453FRajiv
This works locally but then when running from IIS this returns system 500 errors... Are there includes or references to add to your project in addition to this web.config change that are necessary for this to work in MVC 5?Conscription
This worked for me eventually. But only after adding an extra star to the right path element value. path=" * /people/ * " // Without spaces, Github wont let me include stars next to other characters.Tungting
There is also the RouteExistingFiles property in RouteCollection. When set to false, it will return 500 for request if virtual path points to real file, after mapping virtual path to physical.Schulte
this one's safe to use. most recommended wayVesuvianite
Not sure if it should referred-to as a URL Rewrite "Hack", but I strongly recommend folks take a look at the web.config system.webServer rewrite presented by Suprotim Agarwaln here: devcurry.com/2015/07/allowing-dots-in-aspnet-mvc-paths.htmlNope
C
51

After some poking around I found that relaxedUrlToFileSystemMapping did not work at all for me, what worked in my case was setting RAMMFAR to true, the same is valid for (.net 4.0 + mvc3) and (.net 4.5 + mvc4).

<system.webserver>
    <modules runAllManagedModulesForAllRequests="true">

Be aware when setting RAMMFAR true Hanselman post about RAMMFAR and performance

Copro answered 21/8, 2012 at 23:19 Comment(6)
Be aware when setting RAMMFAR... Is there any performance loss if i use this <modules runAllManagedModulesForAllRequests="true">Salter
In the case of the original poster it should not be needed, since he is using IIS7 and above. There it is the default and setting the RAMMFAR is indeed costing you exta. See msdn.microsoft.com/en-us/library/…Schuh
Though this is useful, this wasn't enough to get periods to stop returning 404s in MVC5/IIS7 for me.Durwyn
Just to reiterate.You want to avoid having this option turned onMarlee
Don't do this on a live site though, if at all possible.Corner
its work but should be <modules runAllManagedModulesForAllRequests="true" /> with / character at lastObverse
S
30

I got stuck on this issue for a long time following all the different remedies without avail.

I noticed that when adding a forward slash [/] to the end of the URL containing the dots [.], it did not throw a 404 error and it actually worked.

I finally solved the issue using a URL rewriter like IIS URL Rewrite to watch for a particular pattern and append the training slash.

My URL looks like this: /Contact/~firstname.lastname so my pattern is simply: /Contact/~(.*[^/])$

I got this idea from Scott Forsyth, see link below: http://weblogs.asp.net/owscott/handing-mvc-paths-with-dots-in-the-path

Southpaw answered 30/5, 2015 at 15:41 Comment(2)
This worked for me (MVC5). Other suggestions above didn't work, and weren't needed, just a trailing slash. I will change my routes as suggested by @jonduncan05 here.Buckram
Thank you, Leon. Saved the day for me. Not sure about all of the web.config stuff people around talking about here, but adding the trailing / was the answer I needed. In my case, I have control over the server-side controller, and the javascript that was calling it, so I just updated the JavaScript and voila!Partheniaparthenocarpy
A
29

I believe you have to set the property relaxedUrlToFileSystemMapping in your web.config. Haack wrote an article about this a little while ago (and there are some other SO posts asking the same types of question)

<system.web>
<httpRuntime relaxedUrlToFileSystemMapping="true" />

Edit From the comments below, later versions of .NET / IIS may require this to be in the system.WebServer element.

<system.webServer>
<httpRuntime relaxedUrlToFileSystemMapping="true" />
Albany answered 30/7, 2012 at 21:39 Comment(10)
This is what I had with mvc3+.net4.0 and worked beautifully, but don't work anymore with mvc4+.net4.5.Copro
I tried the relaxedUrlToFileSystemMapping without success. I don't think it works with the newest versions of MVC.Fray
This allowed me to catch the url /WEB-INF./web.xml and redirect it to a custom error page when very many other ways I tried did not work.Hallee
Interesting. Given that it didn't work for you, I was about to assume this wouldn't work for me... given I'm on MVC4 with .NET4.5. But bingo, it worked anyway. In my case I simply had a URL with a period "." as the last character. I was getting 404's but this fixed it.Video
Does his have security repercussions?Hephaestus
It seems this setting needs to go into the <system.webServer> element rather than the <system.web> one.Impacted
@O.R.Mapper - Thanks for the feedback. When this question was posted (2012), the target framework would have been .NET 4.0. According to the MSDN for the <httpRuntime> element, at this time it belonged to the <system.web> section: learn.microsoft.com/en-us/previous-versions/dotnet/…Albany
@O.R.Mapper - I was going to update a link to the latest documentation but the MS docs for system.webServer doesn't list <httpRuntime> as a valid attribute. Maybe the docs are out of date? learn.microsoft.com/en-us/iis/configuration/system.webserver/…Albany
@Tommy: Not sure - I just wrote what did turn out working on our application by trying. Maybe we're not using the latest libraries, either, though.Impacted
@O.R.Mapper - oh I totally believe that they moved it, updated the answer to reflect .NET versions may dictate where this goes today. :)Albany
G
21

Just add this section to Web.config, and all requests to the route/{*pathInfo} will be handled by the specified handler, even when there are dots in pathInfo. (taken from ServiceStack MVC Host Web.config example and this answer https://mcmap.net/q/98824/-dots-in-url-causes-404-with-asp-net-mvc-and-iis)

This should work for both IIS 6 & 7. You could assign specific handlers to different paths after the 'route' by modifying path="*" in 'add' elements

  <location path="route">
    <system.web>
      <httpHandlers>
        <add path="*" type="System.Web.Handlers.TransferRequestHandler" verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" />
      </httpHandlers>
    </system.web>
    <!-- Required for IIS 7.0 -->
    <system.webServer>
      <modules runAllManagedModulesForAllRequests="true" />
      <validation validateIntegratedModeConfiguration="false" />
      <handlers>
        <add name="ApiURIs-ISAPI-Integrated-4.0" path="*" type="System.Web.Handlers.TransferRequestHandler" verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" preCondition="integratedMode,runtimeVersionv4.0" />
      </handlers>
    </system.webServer>
  </location>
Gastelum answered 17/5, 2013 at 11:18 Comment(7)
Beware of the performance consequences runAllManagedModulesForAllRequests (RAMMFAR) has. This will enable all managed modules for every request. Static files, such as images, can be processed by IIS directly but this processes them through every module adding overhead to every request.Fray
@MarkS. yes, but I believe this will affect only request to route/... if we use <location> section and do not set the runAllManagedModulesForAllRequests in the main <system.webServer> section.Gastelum
@Gastelum I think just the handler is sufficient, unless you have files on the system that match a URL that .NET is supposed to process. And for some reason, RAMMFAR didn't work at the <location> level, but the handler solution did.Majorette
@Majorette <location> needed when you do not want MVC to process requests to a specified route and add routes.IgnoreRoute("route/{*pathInfo}"); Then IIS will look into location section <location path="route"> and will use specified handlers in the location section, but it will bypass completely MVC's routing and other MVC's pipeline steps. In my project, ServiceStack api just doesn't work without that setup.Gastelum
Why won't simply adding the handler work? In my case, I have to add RAMMFAR along with the handler. Looking for some good explanation here. :)Calan
@AdityaPatil No idea why and no reason, 2 years ago that just workedGastelum
Using the location section is perfect for including a referenced assembly with embedded content for a specific path. In that case I want RAMMFAR.Alkmaar
R
6

MVC 5.0 Workaround.

Many of the suggested answers doesn't seem to work in MVC 5.0.

As the 404 dot problem in the last section can be solved by closing that section with a trailing slash, here's the little trick I use, clean and simple.

While keeping a convenient placeholder in your view:

@Html.ActionLink("Change your Town", "Manage", "GeoData", new { id = User.Identity.Name }, null)

add a little jquery/javascript to get the job done:

<script>
    $('a:contains("Change your Town")').on("click", function (event) {
        event.preventDefault();
        window.location.href = '@Url.Action("Manage", "GeoData", new { id = User.Identity.Name })' + "/";
    });</script>

please note the trailing slash, that is responsible for changing

http://localhost:51003/GeoData/Manage/[email protected]

into

http://localhost:51003/GeoData/Manage/[email protected]/
Roxane answered 24/2, 2017 at 18:54 Comment(0)
C
5

Super easy answer for those that only have this on one webpage. Edit your actionlink and a + "/" on the end of it.

  @Html.ActionLink("Edit", "Edit", new { id = item.name + "/" }) |
Circe answered 29/11, 2016 at 18:0 Comment(1)
Solved it for me! Simple and elegant! Most irritating is that it works without the '/' on Windows 10 during development, but for Windows 2012 it seems to be required.Concretize
B
3

Depending on how important it is for you to keep your URI without querystrings, you can also just pass the value with dots as part of the querystring, not the URI.

E.g. www.example.com/people?name=michael.phelps will work, without having to change any settings or anything.

You lose the elegance of having a clean URI, but this solution does not require changing or adding any settings or handlers.

Belda answered 1/8, 2018 at 18:8 Comment(0)
G
2

You might want to think about using dashes instead of periods.

In Pro ASP MVC 3 Framework they suggest this about making friendly URLs:

Avoid symbols, codes, and character sequences. If you want a word separator, use a dash (/my-great-article). Underscores are unfriendly, and URL-encoded spaces are bizarre (/my+great+article) or disgusting (/my%20great%20article).

It also mentions that URLs should be be easy to read and change for humans. Maybe a reason to think about using a dash instead of a dot also comes from the same book:

Don't use file name extensions for HTML pages (.aspx or .mvc), but do use them for specialized file types (.jpg, .pdf, .zip, etc). Web browsers don't care about file name extensions if you set the MIME type appropriately, but humans still expect PDF files to end with .pdf

So while a period is still readable to humans (though less readable than dashes, IMO), it might still be a bit confusing/misleading depending on what comes after the period. What if someone has a last name of zip? Then the URL will be /John.zip instead of /John-zip, something that can be misleading even to the developer that wrote the application.

Goad answered 29/8, 2012 at 16:43 Comment(3)
It's likely a username or other field that inherently contains dots. That said, StackOverflow replaces all punctuation (including .) with dashes in its user urls :PHimeji
I encountered this because I have secure file retrieval service that obviously contains filenames in the route parameter...Cordierite
Downvoted for the obvious reason: It doesn't answer the question. If I could, I wouldn't let periods appear in my URL. They appear, because the URL is generated and has to be human-readable.Polo
E
1

Would it be possible to change your URL structure?
For what I was working on I tried a route for

url: "Download/{fileName}"

but it failed with anything that had a . in it.

I switched the route to

    routes.MapRoute(
        name: "Download",
        url:  "{fileName}/Download",
        defaults: new { controller = "Home", action = "Download", }
    );

Now I can put in localhost:xxxxx/File1.doc/Download and it works fine.

My helpers in the view also picked up on it

     @Html.ActionLink("click here", "Download", new { fileName = "File1.doc"})

that makes a link to the localhost:xxxxx/File1.doc/Download format as well.

Maybe you could put an unneeded word like "/view" or action on the end of your route so your property can end with a trailing / something like /mike.smith/view

Elysian answered 16/10, 2015 at 17:30 Comment(0)
C
1

Tried all the solutions above but none of them worked for me. What did work was I uninstalling .NET versions > 4.5, including all its multilingual versions; Eventually I added newer (English only) versions piece by piece. Right now versions installed on my system is this:

  • 2.0
  • 3.0
  • 3.5 4
  • 4.5
  • 4.5.1
  • 4.5.2
  • 4.6
  • 4.6.1

And its still working at this point. I'm afraid to install 4.6.2 because it might mess everything up.

So I could only speculate that either 4.6.2 or all those non-English versions were messing up my configuration.

Countercharge answered 23/5, 2016 at 9:27 Comment(0)
U
1

As solution could be also considering encoding to a format which doesn't contain symbol., as base64.

In js should be added

btoa(parameter); 

In controller

byte[] bytes = Convert.FromBase64String(parameter);
string parameter= Encoding.UTF8.GetString(bytes);
Unshakable answered 13/6, 2017 at 8:49 Comment(0)
D
1

Add URL Rewrite rule to Web.config archive. You need to have the URL Rewrite module already installed in IIS. Use the following rewrite rule as inspiration for your own.

<?xml version="1.0" encoding="utf-8"?>
<configuration>

<system.webServer>
  <rewrite>
    <rules>
      <rule name="Add trailing slash for some URLs" 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" url="{R:1}/" />
      </rule>
    </rules>
    </rewrite>
</system.webServer>

</configuration> 
Doublecross answered 10/5, 2018 at 21:53 Comment(1)
This absolutely works, and was presented by Suprotim Agarwal in 2015 here: devcurry.com/2015/07/allowing-dots-in-aspnet-mvc-paths.htmlNope
D
1

It's as simple as changing path="." to path="". Just remove the dot in the path for ExensionlessUrlHandler-Integrated-4.0 in web.config.

Here's a nice article https://weblog.west-wind.com/posts/2015/Nov/13/Serving-URLs-with-File-Extensions-in-an-ASPNET-MVC-Application

Darbie answered 21/2, 2019 at 9:35 Comment(1)
This link led me to the best solution to my issue (the segment contains a "." character but clients will not trail with a "/"). Fixed by having this line in <system.webServer> of web.config - <modules runAllManagedModulesForAllRequests="true" />Adherent
J
0

I was able to solve my particular version of this problem (had to make /customer.html route to /customer, trailing slashes not allowed) using the solution at https://mcmap.net/q/100989/-asp-net-mvc-url-route-supporting-dot, and substituting path="*.html".

Jessi answered 12/2, 2014 at 18:47 Comment(0)
C
0

Also, (related) check the order of your handler mappings. We had a .ashx with a .svc (e.g. /foo.asmx/bar.svc/path) in the path after it. The .svc mapping was first so 404 for the .svc path which matched before the .asmx. Havn't thought too much but maybe url encodeing the path would take care of this.

Crown answered 14/6, 2018 at 9:59 Comment(0)
G
0

This is the best solution I have found for the error 404 on IIS 7.5 and .NET Framework 4.5 environment, and without using: runAllManagedModulesForAllRequests="true".

I followed this thread: https://forums.asp.net/t/2070064.aspx?Web+API+2+URL+routing+404+error+on+IIS+7+5+IIS+Express+works+fine and I have modified my web.config accordingly, and now the MVC web app works well on IIS 7.5 and .NET Framework 4.5 environment.

Grieve answered 8/12, 2020 at 11:42 Comment(0)
L
-3
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace WebApplication1.Controllers
{
    [RoutePrefix("File")]
    [Route("{action=index}")]
    public class FileController : Controller
    {
        // GET: File
        public ActionResult Index()
        {
            return View();
        }

        [AllowAnonymous]
        [Route("Image/{extension?}/{filename}")]
        public ActionResult Image(string extension, string filename)
        {
            var dir = Server.MapPath("/app_data/images");

            var path = Path.Combine(dir, filename+"."+ (extension!=null?    extension:"jpg"));
           // var extension = filename.Substring(0,filename.LastIndexOf("."));

            return base.File(path, "image/jpeg");
        }
    }
}
Lozada answered 20/12, 2015 at 16:12 Comment(2)
How does this answer OP's question? Mind describing it please?Diviner
it's not a solution, it's a hack which requires the file extension to be placed into the uri path (without a period) e.g. "~/Image/jpg/cow" to retrieve the file "/app_data/images/cow/jpg" -- not the solution this guy and everyone else finding this needs.Iz

© 2022 - 2024 — McMap. All rights reserved.