因此,我将区域从使用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" }
);
现在,当我尝试将其切换到属性路由时,唯一接近工作的是:
[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'作为group
参数传入。但正则表达式并不特别有助于URL的最终呈现方式。
我希望喜欢,以便在URL中抑制可选参数,除非它们是非默认值。我尝试将参数指定为可选参数,默认值,以及可选参数和默认值。他们似乎都没有真正做到这一点。
当前的解决方案至少会提供一个没有查询字符串的URL,但它们包含可选参数并使事情变得丑陋。就目前而言,我只是将AreaRegistration
文件&中定义的恶劣路线留下来。没有用[Route()]
件装饰它们。
答案 0 :(得分:3)
您真正的问题是如何使用属性路由配置原始路由。订单问题只是配置多个路由而不是一个路由的副作用。 要实现所需的配置,您可以创建自定义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; }
}
然后在Controller中:
[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");
}
它与初始路由配置完全相同,但使用属性。
答案 1 :(得分: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代码。