首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在IRouteConstraint上完全忽略了RouteAttribute的命令

在IRouteConstraint上完全忽略了RouteAttribute的命令
EN

Stack Overflow用户
提问于 2018-04-17 03:35:43
回答 1查看 277关注 0票数 3

我们有一个比它应该检查的更多的IRouteConstraint。在进一步的测试中,Order on [Route]似乎被路由约束忽略了。

例如,如果我有以下约束:

代码语言:javascript
复制
public class TestConstraint : IRouteConstraint {
    public bool Match(
        HttpContextBase httpContext,
        Route route,
        string parameterName,
        RouteValueDictionary values,
        RouteDirection routeDirection
    ) {
        Debug.WriteLine("TestConstraint");
        return true;
    }
}

并将其连接起来:

代码语言:javascript
复制
constraintResolver.ConstraintMap.Add("testConstraint", typeof(TestConstraint));

并有下列路线:

代码语言:javascript
复制
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。

EN

回答 1

Stack Overflow用户

发布于 2018-04-17 15:29:30

在ASP.NET MVC管道中,路由阶段和调用控制器动作的选择阶段是分开的。在路由阶段,您不能只选择第一个匹配操作并停止进一步的查找。发现的动作(严格地说是方法)可以在后期进行过滤。例如,它可能不能满足应用的动作选择器(例如,NonAction属性)。

这就是为什么基本操作选择算法如下:

  1. 通过配置的路由传递请求URL并选择所有匹配的操作。
  2. 通过操作选择器传递所有匹配操作,筛选出不匹配。
  3. 通过路由顺序命令候选操作。

现在有以下选择:

  1. 没有找到匹配的操作。请求结果为404错误。
  2. 多个匹配操作共享相同的最高顺序。抛出异常(“当前请求在下列操作方法之间不明确.”)。
  3. 确切地说,一个匹配操作具有最高的顺序(或者一个操作完全匹配)。该操作被选中并执行。

如果您对通信ASP.NET MVC源代码感兴趣,以下是一些参考资料:

IRouteConstraint.Match()ProcessConstraint()方法在System.Web.Routing.Route中调用。调用堆栈中最接近的方法(在路由收集级别上操作)是System.Web.Mvc.Routing.RouteCollectionRoute类中的System.Web.Mvc.Routing.RouteCollectionRoute方法:

这是它的源代码

代码语言:javascript
复制
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() (源代码)中:

代码语言:javascript
复制
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);
    }
}
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/49869484

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档