使用属性路由时是不是可以更改路由表中的路由顺序?

Posted

技术标签:

【中文标题】使用属性路由时是不是可以更改路由表中的路由顺序?【英文标题】:Is it possible to change order of routes in routing table when using attribute routing?使用属性路由时是否可以更改路由表中的路由顺序? 【发布时间】:2016-01-14 07:23:49 【问题描述】:

所以,我正在将一个区域从使用 AreaRegistration 切换到使用 Attribute Routing。我遇到了一个问题,这似乎是由将路由加载到路由表中的顺序引起的。我通过最后加载有问题的路由解决了 AreaRegistration 中的问题,这样只有当所有其他路由不匹配时,该路由才会匹配。使用属性路由,这似乎是不可能的。我在创建路由时有 Order 参数,但这不会影响事物如何到达路由表,除非非常狭窄。

这是我在 AreaRegistration 文件中的路线:

context.MapRoute(
    name: "ActionItems_home",
    url: "ActionItems/group/statuses/overdueOnly",
    defaults: new  controller = "Home", action = "Index", group = "All", statuses = "New,Open", overdueOnly = false ,
    namespaces: new string[]  "IssueTracker.Areas.ActionItems.Controllers" 
    );

现在,当我尝试将其切换到属性路由时,唯一接近工作的是:

[Route("", Order = 4)]
[Route("group:regex(^(?!Item|DecisionLogs))?", Order = 3)]
[Route("group:regex(^(?!Item|DecisionLogs))/statuses=New,Open?", Order = 2)]
[Route("group:regex(^(?!Item|DecisionLogs))/statuses=New,Open/overdueOnly:bool=false?", Order = 1)]

请注意,我必须输入正则表达式,否则不会调用 Item 控制器 - 相反,我最终将字符串“Item”作为 group 参数传入。但是正则表达式对于 URL 的最终呈现方式并没有特别的帮助。

我希望 喜欢 在 URL 中抑制可选参数,除非它们是非默认的。我尝试将参数指定为可选的、具有默认值的、可选的和具有默认值的。他们似乎都没有真正做到这一点。

当前的解决方案至少提供了一个没有查询字符串的 URL,但它们包含可选参数并使事情变得丑陋。目前,我只是将那些令人震惊的路线留在了AreaRegistration 文件中,而不是用[Route()] 片段来装饰它们。

【问题讨论】:

看asp.net/web-api/overview/web-api-routing-and-actions/… 谢谢你,阿米尔。似乎 RouteOrder 属性可用于 ApiController 类......在某些版本的 Web API 控制器中。但是,它不适用于从 System.Web.Mvc.Controller 类继承的控制器,这是我遇到问题的地方。将我的控制器的继承更改为 System.Web.Http.ApiController 也无济于事,因为 ApiController 在 MVC5 中没有 RouteOrder 参数(另外,这会破坏控制器)。 听起来你可能不在 ASP.NET MVC 5 上。我认为属性路由是在 5 中才引入的。blogs.msdn.com/b/webdev/archive/2013/10/17/… 不——我在 MVC5 上,属性路由在大多数情况下都非常有效。只有这些带有一堆可选参数的路由会变得很麻烦。 这可能会有所帮助,它有点旧,但应该是一本好书,有点反思,你可以自己滚动blog.stevensanderson.com/2008/07/31/… 【参考方案1】:

您真正的问题是如何使用属性路由配置您的原始路由。顺序问题只是配置多个路由而不是一个的副作用。 为了实现你想要的配置,你可以创建一个自定义的 RouteAttribute 并在里面做任何你需要的事情。

public class OptionalsRouteAttribute : RouteFactoryAttribute

    private object _defaults;

    public OptionalsRouteAttribute(string template, object defaults)
        : base(template)
    
        Defaults = defaults;
    

    [...]

你可以看到sample here 以及original RouteFactoryAttribute来源供参考

恐怕我现在没有时间自己提供实际的实现,但我希望这会引导您走向正确的方向。

更新 我已经尝试过了,以下非常简单的解决方案按预期工作。我的属性实现特定于您提供的带有 group、status 和 overdueOnly 参数的示例,但您应该能够创建一个涵盖所有案例的更通用的解决方案(您还需要添加命名空间)

 public class OptionalsRouteAttribute : RouteFactoryAttribute

    public OptionalsRouteAttribute(string template, string group, string statuses, bool overdueOnly)
        : base(template)
    
        var defaults = new RouteValueDictionary
        
            "group", @group,
            "statuses", statuses,
            "overdueOnly", overdueOnly
        ;
        Defaults = defaults;
    

    public override RouteValueDictionary Defaults  get; 


然后在控制器中:

 [OptionalsRoute("ActionItemsAttribute/group/statuses/overdueOnly", "All", "New,Open", false)]
    public ActionResult AttributeRouting(string group, string statuses, bool overdueOnly)
    
        ViewBag.Message = $"Attribute Routing: Group [@group] - Statuses [statuses] - overdueOnly [overdueOnly]";
        return View("Index");
    

它的工作方式与您的初始路由配置完全相同,但使用了一个属性。

【讨论】:

【参考方案2】:

ASP.NET MVC 是开源的,它的设计方式是每一层都可以被您自己替换。您可以download the source code,找到有问题的部分并了解它是如何工作的。如果需要,最后用自己的代码替换。

git clone https://git01.codeplex.com/aspnetwebstack.git

如果你下载这个源代码,你会发现一个带有 CreateRoute 方法的 System.Web.Mvc.RouteAttribute 类。我不确定,但它可能与您的问题有关。

RouteEntry IDirectRouteFactory.CreateRoute(DirectRouteFactoryContext context)

    Contract.Assert(context != null);

    IDirectRouteBuilder builder = context.CreateBuilder(Template);
    Contract.Assert(builder != null);

    builder.Name = Name;
    builder.Order = Order;
    return builder.Build();

在这个接口上查找引用,可以找到 DefaultDirectRouteProvider 类。

另一种方法是,您可以尝试在项目中找到工作“订单”。如果省略 test,那么出现的次数就不多,而且有些在 routeSomething 类中。

您可以在 Visual Studio 中取消选中“仅我的代码”并调试 ASP.NET MVC 代码。

【讨论】:

以上是关于使用属性路由时是不是可以更改路由表中的路由顺序?的主要内容,如果未能解决你的问题,请参考以下文章

路由系统

Vue路由匹配规则routes中的name属性

BGP的属性和选路原则

3.21下午

windows电脑怎么设置永久路由的先后顺序

H3C路由两者的优先级顺序是啥?