MVC5 : Attribute Routing Precedence Among Controllers

旧巷老猫 提交于 2019-12-19 18:56:33

问题


I am using the Attribute Routing from MVC5 in my controllers.

Question:

Is there a way to control attribute routing precedence among controllers?

Consider the following

[Route("home/{action=index}/{username?}")]
public class HomeController : Controller
{
    [Route("home/index/{username?}", Order = 1)]
    [Route("home/{username?}", Order = 2)]
    [Route("{username?}", Order = 3)]
    public ActionResult Index()
    {
        // ... bunch of stuff
    }
}

Base on the code above, HomeController.Index() action method should be invoked using the following requests:

  • domain/
  • domain/{username}
  • domain/home/
  • domain/home/{username}
  • domain/home/index/
  • domain/home/index/{username}

Second Controller:

[Authorize(Roles = "Member")]
[Route("profile/{action=index}")]
public class ProfileController : Controller
{
    [Route("profile")]
    public ActionResult Index()
    {

    }
}

The ProfileController.Index() should be invoked using the following request.

  • domain/profile
  • domain/profile/index

The problem

From the examples, if I send domain/profile in the url, an ambiguity exception is thrown. It seems that there is an ambiguity between domain/{username} and domain/profile.

Now, if I used convention-based routing, this would have worked (first match wins). But can it be done in MVC5 Attribute Routing? because I found that a third party library supports precedence among controllers

https://github.com/mccalltd/AttributeRouting/wiki/Controlling-Route-Precedence

routes.MapAttributeRoutes(config =>
{
    config.AddRoutesFromController<ProfileController>();
    config.AddRoutesFromController<HomeController>();
});

回答1:


No, it is not possible in ASP.Net MVC 5.2.3 to prioritise controller routes over each other. If multiple match, then the order of the actions is ignored and an exception is thrown.

I have verified this by downloading the source from https://aspnetwebstack.codeplex.com/SourceControl/latest and checking the function GetControllerTypeFromDirectRoute (below). None of the calls made out of this function do anything to prioritise the routes, they are just found and reported back. As you can see, GetControllerTypeFromDirectRoute just throws on a multiple match.

Not great at all, but hopefully this will save someone else some time.

I put a manually mapped route in to avoid this issue.

 private static Type GetControllerTypeFromDirectRoute(RouteData routeData)
    {
        Contract.Assert(routeData != null);

        var matchingRouteDatas = routeData.GetDirectRouteMatches();

        List<Type> controllerTypes = new List<Type>();
        foreach (var directRouteData in matchingRouteDatas)
        {
            if (directRouteData != null)
            {
                Type controllerType = directRouteData.GetTargetControllerType();
                if (controllerType == null)
                {
                    // We don't expect this to happen, but it could happen if some code messes with the 
                    // route data tokens and removes the key we're looking for. 
                    throw new InvalidOperationException(MvcResources.DirectRoute_MissingControllerType);
                }

                if (!controllerTypes.Contains(controllerType))
                {
                    controllerTypes.Add(controllerType);
                }
            }
        }

        // We only want to handle the case where all matched direct routes refer to the same controller.
        // Handling the multiple-controllers case would put attribute routing down a totally different
        // path than traditional routing.
        if (controllerTypes.Count == 0)
        {
            return null;
        }
        else if (controllerTypes.Count == 1)
        {
            return controllerTypes[0];
        }
        else
        {
            throw CreateDirectRouteAmbiguousControllerException(controllerTypes);
        }
    }


来源:https://stackoverflow.com/questions/21809556/mvc5-attribute-routing-precedence-among-controllers

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