user2227904
user2227904

Reputation: 679

MVC Routing with relative path as parameter - How to escape the default behavior of searching for a file when link ends with extension?

I am looking for a way to make the MVC routing to hide upload path of a file, but considering it might be an html file that links to another html file I need to compensate for that.

routes.MapRoute(
    name: "GetFile",
    url: "File/{id}/{*path}",
    defaults: new { controller = "Home", action = "GetFile", id = UrlParameter.Optional, path = UrlParameter.Optional }
);

So this leading to a url for example: http://example.com/Files/5/Folder1/Folder2/Folder3/index.html and if a link is clicked on that page to lead to: http://example.com/Files/5/Folder1/Folder2/Folder3/index2.html

But currently my problem is that if I add any file extension in the mix it dies because it is looking for the file itself, when I need it to just pass it as a text variable.

Upvotes: 1

Views: 1684

Answers (1)

NightOwl888
NightOwl888

Reputation: 56859

The problem you describe "if I add any file extension in the mix it dies because it is looking for the file itself" is not an MVC problem, but due to the default web server settings.

In IIS, there are settings to control how specific file extensions are handled. .html files are served directly through the web server by default and thus ignored by MVC. You can override this behavior by changing the handlers from their default settings.

1. Change HTTP Handlers in web.config to Handle .html Extension

<system.webServer>
    <handlers>     
        <add name="HtmlFileHandler" path="*.html" verb="GET" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
        <!-- other handlers... -->
    </handlers>
</system.webServer>

2. Ensure runAllManagedModulesForAllRequests is false

Note this is the default so if this doesn't exist, don't add it.

<system.webServer>
    <modules runAllManagedModulesForAllRequests="false" />
</system.webServer>

3. Add the Route

You have this (almost). But it probably doesn't make any sense to make id or path optional on the route. After all, what is it supposed to do if you don't supply the path? id can only be optional if it is not followed by path, so you would need to make another route to handle the no id case if it is indeed optional.

routes.MapRoute(
    name: "GetFile",
    url: "File/{id}/{*path}",
    defaults: new { controller = "Home", action = "GetFile" }
);

4. Route Existing Files

To route the files in their original location, you need to apply the setting to routing, otherwise you will get an error if the URL is the same as a physical file on disk.

public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

    routes.RouteExistingFiles = true;

    routes.MapRoute(
        name: "GetFile",
        url: "File/{id}/{*path}",
        defaults: new { controller = "Home", action = "GetFile" }
    );

    routes.MapRoute(
        name: "Default",
        url: "{controller}/{action}/{id}",
        defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
        );
}

Reference: https://weblogs.asp.net/jongalloway/asp-net-mvc-routing-intercepting-file-requests-like-index-html-and-what-it-teaches-about-how-routing-works

Upvotes: 3

Related Questions