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

Dav*_*net 14 c# asp.net-mvc routing attributerouting asp.net-mvc-5

所以,我正在将区域从使用AreaRegistration切换到使用属性路由.我遇到的问题似乎是由路由加载到路由表中的顺序引起的.我通过最后加载有问题的路由解决了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" }
    );
Run Code Online (Sandbox Code Playgroud)

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

[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)]
Run Code Online (Sandbox Code Playgroud)

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

为在URL,除非他们非默认被抑制的可选参数.我已经尝试将参数指定为可选参数,使用默认值,以及可选参数和默认值.他们似乎都没有真正做到这一点.

目前的解决方案,至少没有呈现一个查询字符串的URL,但它们包括可选参数,使事情难看.现在,我只是简单地将令人震惊的路线留在AreaRegistration文件中,而不是用[Route()]碎片装饰它们.

Fra*_*lls 3

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

public class OptionalsRouteAttribute : RouteFactoryAttribute
{
    private object _defaults;

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

    [...]
}
Run Code Online (Sandbox Code Playgroud)

您可以在此处查看示例 以及原始的 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; }

}
Run Code Online (Sandbox Code Playgroud)

然后在控制器中:

 [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");
    }
Run Code Online (Sandbox Code Playgroud)

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