MVC5:控制器之间的属性路由优先级 [英] MVC5 : Attribute Routing Precedence Among Controllers

查看:189
本文介绍了MVC5:控制器之间的属性路由优先级的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在控制器中使用了来自MVC5的属性路由.

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

是否可以控制控制器之间的属性路由优先级?

考虑以下

[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
    }
}

根据上面的代码,应使用以下请求调用HomeController.Index()动作方法:

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

  • 域/
  • 域/{用户名}
  • domain/home/
  • domain/home/{username}
  • domain/home/index/
  • domain/home/index/{username}

第二个控制器:

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

    }
}

ProfileController.Index()应该使用以下请求来调用.

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

  • 域/配置文件
  • 域/配置文件/索引

从示例中,如果我在URL中发送domain/profile,则会引发歧义异常.似乎在domain/{username}domain/profile之间存在歧义.

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.

现在,如果我使用基于约定的路由,那将奏效(首场比赛获胜).但是可以在MVC5属性路由中完成吗?因为我发现第三方库支持控制器之间的优先级

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>();
});

推荐答案

否,在ASP.Net MVC 5.2.3中不可能优先确定彼此之间的控制器路由优先级.如果有多个匹配项,则将忽略操作顺序,并引发异常.

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.

我已通过从 https://aspnetwebstack.codeplex.com/SourceControl/latest下载源进行了验证并检查功能GetControllerTypeFromDirectRoute(如下).从该函数发出的任何调用都不会对路由进行优先级排序,只是找到并报告了路由.如您所见,GetControllerTypeFromDirectRoute只会引发多个匹配.

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);
        }
    }

这篇关于MVC5:控制器之间的属性路由优先级的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆