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

查看:30
本文介绍了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:

  • 域/
  • 域/{用户名}
  • 域/家/
  • 域/家/{用户名}
  • 域/家/索引/
  • 域/家/索引/{用户名}

第二控制器:

[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天全站免登陆