12

I'm trying to understand how RouteExistingFiles works. So I've created a new MVC 3 internet project (MVC 4 behaves the same way) and put a HTMLPage.html file to the Content folder of my project. Now I went to the Global.Asax file and edited the RegisterRoutes function so it looks like this:

public static void RegisterRoutes(RouteCollection routes)
{
    routes.RouteExistingFiles = true; //Look for routes before looking if a static file exists

    routes.MapRoute(
            "Default", // Route name
            "{controller}/{action}/{id}", // URL with parameters
            new {controller = "Home", action = "Index", id = UrlParameter.Optional} // Parameter defaults
            );
    }

Now it should give me an error when I'm requesting a localhost:XXXX/Content/HTMLPage.html since there's no "Content" controller and the request definitely hits the default pattern. But instead I'm seeing my HTMLPage. What am I doing wrong here?

Update: I think I'll have to give up. Even if I'm adding a route like this one:

routes.MapRoute("", "Content/{*anything}", new {controller = "Home", action = "Index"});

it still shows me the content of the HTMLPage. When I request a url like ~/Content/HTMLPage I'm getting the Index page as expected, but when I add a file extenstion like .html or .txt the content is shown (or a 404 error if the file does not exist). If anyone can check this in VS2012 please let me know what result you're getting. Thank you.

Oleksandr Kaplun
  • 121
  • 1
  • 1
  • 4

3 Answers3

19

To enabling routing for static files you must perform following steps.

In RouteConfig.cs enable routing for existing files

routes.RouteExistingFiles = true;

Add a route for your path ( Make sure specialized path are above generalized paths)

routes.MapRoute(
            name: "staticFileRoute",
            url: "Public/{file}/",
            defaults: new { controller = "Home", action = "SomeAction" }
        );

Next configure your application, so that request for static files are handeled by "TransferRequestHandler".In Webconfig under system.webServer>handlers add following entry.

<add name="MyCustomUrlHandler2" path="Public/*" verb="GET" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />

The value of 'path' can be more generic or specific depending on your requirement. But i prefer it to be always very specific as per one's need. Keeping it very generic will block serving of other site specific resources such as .js or css files. For example if above is set as path="*", then request for even the css (inside the content folder) which is responsible for how your page would look will also end up in your Controller's action. Something that you will not like.

Prerak K
  • 10,940
  • 7
  • 30
  • 37
6

Visual Studio 2012 uses IIS Express. You need to tell IIS not to intercept requests for disk files before they are passed to the MVC routing system. You need set preCondition attribute to the empty string in config file:

<add name="UrlRoutingModule-4.0" type="System.Web.Routing.UrlRoutingModule" 
     preCondition="" />

In Win7/8 you can find config file on this path: %userprofile%\Documents\IISExpress\config\applicationhost.config

Nalaka526
  • 11,278
  • 21
  • 82
  • 116
Igor
  • 61
  • 1
  • 1
  • This worked for me, thanks, but I assume it can't be configured per solution? – Savage Nov 16 '15 at 10:32
  • You can, by adding before adding this module. Refer https://svenaelterman.wordpress.com/2011/01/31/using-asp-net-4-0-extension-less-routing-on-iis-7-5/ – XPD Jan 14 '18 at 05:33
5

The RouteExistingFiles doesn't keep files from being viewed if there is no route for them, it just checks the routes before checking if the file exists. If there is no matching route, it will continue to check if there is a matching file.

Guffa
  • 687,336
  • 108
  • 737
  • 1,005
  • The Default route with "{controller}/{action}/{id}" pattern looks like a good candidate for ~/Content/HTMLPage.html request. So there is a matching route. – Oleksandr Kaplun Dec 16 '12 at 22:14
  • @OleksandrKaplun: That only matches if you actually have a controller named "Content" and an action method in that controller named "HTMLPage.html". – Guffa Dec 16 '12 at 22:43
  • It sounds convincing, but still doesn't work. Here's what I've added to the top of my RegisterRoutes function: `routes.MapRoute( "ExactMatch", "Content/HTMLPage.html", new {controller = "Home", action = "About"});`. Still shows me the content of the html page. P.S. I understand that it should be working like this (the manual says it should) but it just doesn't so I'm guessing it's something I've done wrong. I'm testing locally on VS2012 and Windows 7. – Oleksandr Kaplun Dec 17 '12 at 08:06
  • It works as expected on VS2010 and Empty MVC 3 project. Will keep digging. – Oleksandr Kaplun Dec 17 '12 at 08:27
  • @OleksandrKaplun any finding? – Volodymyr Ivanov Jul 30 '19 at 11:16