使用属性路由时是否可以更改路由 table 中的路由顺序?
Is it possible to change order of routes in routing table when using attribute routing?
所以,我正在将一个区域从使用 AreaRegistration 切换到使用属性路由。我 运行 遇到了一个问题,该问题似乎是由路由加载到路由 table 中的顺序引起的。我通过最后加载有问题的路由解决了 AreaRegistration 中的问题,这样只有当所有其他路由都不匹配时才会匹配该路由。使用属性路由,这似乎是不可能的。我在创建路线时有 Order 参数,但这不会影响事情如何影响路线 table 除了非常狭窄。
这是我在 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 中抑制可选参数,除非它们不是默认值。我试过将参数指定为可选参数、默认值参数,以及可选参数和默认值参数。 None 他们中的一些人似乎真的做到了。
当前的解决方案至少提供了一个没有查询字符串的 URL,但它们包含可选参数并使事情变得难看。现在,我只是将令人震惊的路线留在 AreaRegistration
文件中定义,而不用 [Route()]
部分装饰它们。
你真正的问题是如何使用属性路由配置你的原始路由。顺序问题只是配置多个路由而不是一个的副作用。
为了实现你想要的配置,你可以创建一个自定义的 RouteAttribute 并在里面做任何你需要的事情。
public class OptionalsRouteAttribute : RouteFactoryAttribute
{
private object _defaults;
public OptionalsRouteAttribute(string template, object defaults)
: base(template)
{
Defaults = defaults;
}
[...]
}
你可以看到 sample here
以及original RouteFactoryAttribute参考资料
恐怕我现在没有时间亲自提供实际的实施,但我希望这会引导您走向正确的方向。
更新
我试了一下,下面的非常简单的解决方案按预期工作。我的属性实现特定于您使用组、状态和 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");
}
它的工作原理与您的初始路由配置完全相同,但使用了一个属性。
ASP.NET MVC 是开源的,它的设计方式是每一层都可以由你自己替换。您可以 download the source code,找到有问题的部分并找出它是如何工作的。如果需要,最后用自己的代码替换。
git clone https://git01.codeplex.com/aspnetwebstack.git
如果你下载这个源代码,你会发现一个System.Web.Mvc.RouteAttribute class 带有CreateRoute 方法。我不确定,但这可能与您的问题有某种联系。
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 class.
另一种方法是,您可以尝试在项目中找到工作"Order"。如果省略测试,则出现次数不多,有些在 routeSomething classes.
您可以取消选中 Visual Studio 中的 "Just my code" 并调试 ASP.NET MVC 代码。
所以,我正在将一个区域从使用 AreaRegistration 切换到使用属性路由。我 运行 遇到了一个问题,该问题似乎是由路由加载到路由 table 中的顺序引起的。我通过最后加载有问题的路由解决了 AreaRegistration 中的问题,这样只有当所有其他路由都不匹配时才会匹配该路由。使用属性路由,这似乎是不可能的。我在创建路线时有 Order 参数,但这不会影响事情如何影响路线 table 除了非常狭窄。
这是我在 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 中抑制可选参数,除非它们不是默认值。我试过将参数指定为可选参数、默认值参数,以及可选参数和默认值参数。 None 他们中的一些人似乎真的做到了。
当前的解决方案至少提供了一个没有查询字符串的 URL,但它们包含可选参数并使事情变得难看。现在,我只是将令人震惊的路线留在 AreaRegistration
文件中定义,而不用 [Route()]
部分装饰它们。
你真正的问题是如何使用属性路由配置你的原始路由。顺序问题只是配置多个路由而不是一个的副作用。 为了实现你想要的配置,你可以创建一个自定义的 RouteAttribute 并在里面做任何你需要的事情。
public class OptionalsRouteAttribute : RouteFactoryAttribute
{
private object _defaults;
public OptionalsRouteAttribute(string template, object defaults)
: base(template)
{
Defaults = defaults;
}
[...]
}
你可以看到 sample here 以及original RouteFactoryAttribute参考资料
恐怕我现在没有时间亲自提供实际的实施,但我希望这会引导您走向正确的方向。
更新 我试了一下,下面的非常简单的解决方案按预期工作。我的属性实现特定于您使用组、状态和 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");
}
它的工作原理与您的初始路由配置完全相同,但使用了一个属性。
ASP.NET MVC 是开源的,它的设计方式是每一层都可以由你自己替换。您可以 download the source code,找到有问题的部分并找出它是如何工作的。如果需要,最后用自己的代码替换。
git clone https://git01.codeplex.com/aspnetwebstack.git
如果你下载这个源代码,你会发现一个System.Web.Mvc.RouteAttribute class 带有CreateRoute 方法。我不确定,但这可能与您的问题有某种联系。
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 class.
另一种方法是,您可以尝试在项目中找到工作"Order"。如果省略测试,则出现次数不多,有些在 routeSomething classes.
您可以取消选中 Visual Studio 中的 "Just my code" 并调试 ASP.NET MVC 代码。