Using Url.RouteUrl() with Route Names in an Area

2020-02-13 07:51发布

问题:

As a side note, I understand the whole ambiguous controller names problem and have used namespacing to get my routes working, so I don't think that is an issue here.

So far I have my project level controllers and then a User Area with the following registration:

public class UserAreaRegistration : AreaRegistration
{
    public override string AreaName
    {
        get
        {
            return "User";
        }
    }

    public override void RegisterArea(AreaRegistrationContext context)
    {
        context.MapRoute(
            "UserHome",
            "User/{id}",
            new { action = "Index", controller = "Home", id = 0 },
            new { controller = @"Home", id = @"\d+" }
        );

        context.MapRoute(
            "UserDefault",
            "User/{controller}/{action}/{id}",
            new { action = "Index", id = UrlParameter.Optional }
        );
    }
}

The "UserHome" route is there so I can allow the route /User/5 vs. /User/Home/Index/5 which looks cleaner IMO.

Ideally I would like to use Url.RouteUrl("UserHome", new { id = 5 }), to generate the route elsewhere, but this always either comes back blank or gives me an exception saying it cannot find the route name, which is obviously there.

However when I use Url.RouteUrl("UserHome", new { controller = "Home", action = "Index", id = 5 }) it works no problem.

Why do I have to specify the action and controller when they have defaults already in the route mapping? What am I missing?

回答1:

Everyone please see @ryanulit's answer below. This issue may be fixed for you with a newer framework version.

Not sure if there has been a hot fix, but the behavior now is a bit different. Using your exact code and trying:

Url.RouteUrl("UserHome", new { id = 5 })

I now get:

/User/5?httproute=True 

This still looks awkward, so I experimented with the route and added another default param:

 context.MapRoute(
            "UserHome",
            "User/{id}",
            new { action = "Index", controller = "Home", area = "User", id = 0, 
                       httproute = true },
            new { controller = @"Home", id = @"\d+" }
        );

Now when I use

Url.RouteUrl("UserHome", new { id = 5 })

I get a nice url of

/User/5

disclaimer There could be unwanted side effects of httproute=true in the route declaration.

Also, the more verbose use:

@Url.RouteUrl("UserHome", new { controller = "Home", action = "Index", id = 5 })

still works as well.



回答2:

Try this:

@Url.Action("Index", "Home", new { Area = "User" })


回答3:

I can confirm that with .NET 4.5.1 and MVC 5.2.2 at the minimum, that this behavior has been fixed and now works as is with this same exact code using Url.RouteUrl("UserHome", new { id = 5 }).

It looks like this was a bug that has been fixed since the time of my post.

Adding this as the answer since although TSmith's solution would work, you no longer need to do that extra work now that there is a fix.