MVC routing when a file actually exists at the specified location

情到浓时终转凉″ 提交于 2019-11-29 03:03:27

问题


So I have a route like this in my MVC 3 application running under IIS 7:

routes.MapRoute(
               "VirtualTourConfig",
               "virtualtour/config.xml",
               new { controller = "VirtualTour", action = "Config" }
               );

The trick is that a file actually exists at /virtualtour/config.xml. It seems like the request is just returning the xml file at that location instead of hitting the route, which processes the XML, makes some changes and returns a custom XmlResult.

Any suggestions on how I can tell my application to hit the route and not the actual file in the event that the file exists on disk?

EDIT: It appears that I can use routes.RouteExistingFiles = true; in the RegisterRoutes method of Global.asax to tell the application to ignore files on disk. This, however, sets the flag globally and breaks a lot of other requests within the application. For example, I still want calls to /assets/css/site.css to return the CSS file without having to specifically set routes up for each static asset. So now the question becomes, is there a way to do this on a per-route basis?


回答1:


So far the best answer to this that I have found is to globally apply routes.RouteExistingFiles=true and then selectively ignore the routes I want to pass through to existing files like .js, .css, etc. So I ended up with something like this:

public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
            routes.IgnoreRoute("*.js|css|swf");
            routes.RouteExistingFiles = true;

            routes.MapRoute(
               "VirtualTourConfig",
               "virtualtour/config.xml",
               new { controller = "VirtualTour", action = "Config" }
               );
}

If anyone has a better solution, I'd like to see it. I'd much prefer to selectively apply an "RouteExistingFIles" flag to individual routes but I don't know if there's a way to do that.




回答2:


No solution here, just an idea.

You can try to implement solution based on your own VirtualPathProvider that will provide your own mapping of web paths to file system paths and use default provider for all paths you don't want to take care of.




回答3:


A very simple solution, certainly if you consider Scott's answer, would be eg: routes.IgnoreRoute("templates/*.html");, routes.IgnoreRoute("scripts/*.js"); and routes.IgnoreRoute("styles/*.css");.

This gives you both the simplicity of just supplying paths to the RoutesCollection and avoids the work of having to initiate eg. a VirtualPathProvider.




回答4:


You could try UrlRewiting e.g.:

<configuration>
  <system.webServer>
    <rewrite>
      <rules>
        <rule name="VirtualTourConfig">
          <match url="^virtualtour/config.xml" />
          <action type="Rewrite" url="virtualtour/config" />
        </rule>
      </rules>
    </rewrite>

NB I'm using this for a different use-case (i.e. serving an angular app from asp.net MVC) - I haven't tested whether MVC routing occurs AFTER url rewriting.

In my case I have a normal MVC route (i.e. /Dashboard/ => DashboardController.Index()) but need all relative paths in the Views/Dashboard/Index.cshtml to serve static files without getting confused by MVC routing i.e. /Dashboard/app/app.module.js must serve a static file. I use UrlRewriting to map /Dashboard/(.+) to /ng/Dashboard/{R:1} as follows:

<configuration>
  <system.webServer>
    <rewrite>
      <rules>
        <rule name="Dashboard">
          <match url="^dashboard/(.+)" />
          <action type="Rewrite" url="ng/dashboard/{R:1}" />
        </rule>
      </rules>
    </rewrite>


来源:https://stackoverflow.com/questions/4681777/mvc-routing-when-a-file-actually-exists-at-the-specified-location

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!