我们有一个比它应该检查的更多的IRouteConstraint。在进一步的测试中,Order on [Route]似乎被路由约束忽略了。
例如,如果我有以下约束:
public class TestConstraint : IRouteConstraint {
public bool Match(
HttpContextBase httpContext,
Route route,
string parameterName,
RouteValueDictionary values,
RouteDirection routeDirection
) {
Debug.WriteLine("TestConstraint");
return true;
}
}并将其连接起来:
constraintResolver.ConstraintMap.Add("testConstraint", typeof(TestConstraint));并有下列路线:
public partial class HomeController {
[Route("test/0", Order = 1)]
public ActionResult Test0() {
return Content("Test0");
}
[Route("{someParam}/{test:testConstraint}", Order = 10)]
public ActionResult Test1() {
return Content("Test1");
}
}然后向http://localhost/test/0发出请求,它将返回正确的内容(Test0),但是TestContraint.Match()仍然被执行。
我认为只有在RouteTable中遇到路由时才会执行路由约束,但它似乎会在每个与[Route]模式匹配的请求上运行它。
如果有区别的话,我们使用的是ASP.NET MVC版本5.2.4。
发布于 2018-04-17 15:29:30
在ASP.NET MVC管道中,路由阶段和调用控制器动作的选择阶段是分开的。在路由阶段,您不能只选择第一个匹配操作并停止进一步的查找。发现的动作(严格地说是方法)可以在后期进行过滤。例如,它可能不能满足应用的动作选择器(例如,NonAction属性)。
这就是为什么基本操作选择算法如下:
现在有以下选择:
如果您对通信ASP.NET MVC源代码感兴趣,以下是一些参考资料:
IRouteConstraint.Match()由ProcessConstraint()方法在System.Web.Routing.Route中调用。调用堆栈中最接近的方法(在路由收集级别上操作)是System.Web.Mvc.Routing.RouteCollectionRoute类中的System.Web.Mvc.Routing.RouteCollectionRoute方法:

这是它的源代码
public override RouteData GetRouteData(HttpContextBase httpContext)
{
List<RouteData> matches = new List<RouteData>();
foreach (RouteBase route in _subRoutes)
{
var match = route.GetRouteData(httpContext);
if (match != null)
{
matches.Add(match);
}
}
return CreateDirectRouteMatch(this, matches);
}正如您所看到的,当找到匹配的路由时,循环不会中断。
应用动作选择器、执行排序和选择动作候选的代码驻留在DirectRouteCandidate.SelectBestCandidate() (源代码)中:
public static DirectRouteCandidate SelectBestCandidate(List<DirectRouteCandidate> candidates, ControllerContext controllerContext)
{
Debug.Assert(controllerContext != null);
Debug.Assert(candidates != null);
// These filters will allow actions to opt-out of execution via the provided public extensibility points.
List<DirectRouteCandidate> filteredByActionName = ApplyActionNameFilters(candidates, controllerContext);
List<DirectRouteCandidate> applicableCandidates = ApplyActionSelectors(filteredByActionName, controllerContext);
// At this point all of the remaining actions are applicable - now we're just trying to find the
// most specific match.
//
// Order is first, because it's the 'override' to our algorithm
List<DirectRouteCandidate> filteredByOrder = FilterByOrder(applicableCandidates);
List<DirectRouteCandidate> filteredByPrecedence = FilterByPrecedence(filteredByOrder);
if (filteredByPrecedence.Count == 0)
{
return null;
}
else if (filteredByPrecedence.Count == 1)
{
return filteredByPrecedence[0];
}
else
{
throw CreateAmbiguiousMatchException(candidates);
}
}https://stackoverflow.com/questions/49869484
复制相似问题