RePierre
RePierre

Reputation: 9566

ASP.NET MVC route not resolving controller/action

I have a controller named DocumentsController inside an area called Public.

public class DocumentsController : AsyncController
{
    public async Task<ActionResult> DownloadAsync(string fileName)
    {
        // ...
    }
}

In the PublicAreaRegistration.cs file I have the following routing setup:

public override void RegisterArea(AreaRegistrationContext context)
{
    context.MapRoute(null, "Public/Documents/Download/{fileName}",
        new { action = "Download", controller = "Documents", area = "Public" });

    context.MapRoute(
        "Public_default",
        "Public/{controller}/{action}/{id}",
        new { action = "Index", id = UrlParameter.Optional, area = "Public" });
}

And in a view I'm invoking Url.Action() like this:

<a href="@Url.Action("Download", "Documents", new { area = "Public", fileName = document.FileName })">@document.FileName</a>

However, although the url is resolved properly (http://localhost/test/Public/Documents/Download/my-file.pdf) the action never gets invoked.

But if I completely remove the first MapRoute call the url is resolved to http://localhost/test/Public/Documents/Download?fileName=my-file.pdf and the action method gets invoked as expected.

What am I doing wrong?

Upvotes: 0

Views: 1761

Answers (2)

jpgrassi
jpgrassi

Reputation: 5732

I edited the answer because I failed to see in your code sample that you are inheriting from AsyncController. Nevertheless, I just created a new project with this setup:

PublicAreaRegistration.cs

public override void RegisterArea(AreaRegistrationContext context)
{
    context.MapRoute(
        "Documents",
        "Public/Documents/Download/{fileName}",
         new { action = "Download", controller = "Documents", area = "Public" });

    context.MapRoute(
        "Public_default",
        "Public/{controller}/{action}/{id}",
        new { action = "Index", id = UrlParameter.Optional, area = "Public" }
    );
}

Running in VS 2013 with IIS Express, this request is mapped correctly to the DownloadAsync action: http://localhost:1555/Public/Documents/Download/myfilename

But this wasn't (Was giving me a 404 error): http://localhost:1555/Public/Documents/Download/myfilename.pdf

Looking at the problem, I've found this blog post stating the problem:

The cause of the problem is related to when a managed module is invoked on an incoming request. Managed modules (vs. Native modules) are only executed for requests to that map to managed handlers. That of course includes requests for URLs with the .aspx extension and several more. However, URLs with no extension are not mapped to a managed handler and thus the managed module that takes care of the URL Routing is not invoked.

Using ASP.NET 4.0 Extension-less Routing on IIS 7.5

Which in the end tells you to add this to your Web.config:

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

Upvotes: 1

Rahul
Rahul

Reputation: 77846

Not sure what's the issue and moreover why you need a custom route. As a suggestion, modify your area registration class and remove the custom route keeping only the default one

public override void RegisterArea(AreaRegistrationContext context)
{
            context.MapRoute(
                "Public_default",
                "Public/{controller}/{action}/{filename}",
                new { action = "Index", controller = "Documents" }
            );
}

Upvotes: 0

Related Questions