【问题标题】:Why is it so hard to get route values outside controller context?为什么在控制器上下文之外获取路由值这么难?
【发布时间】:2026-01-08 03:05:02
【问题描述】:

我不明白这背后的原因是什么,为什么在控制器的Request 中获取路由值如此容易,但在HttpContext.Current.Request 上却几乎不可能做同样的事情?

也许我只是不知道更好的方法并且它存在。有人可以确认这是在控制器之外获取路由数据的唯一方法吗?

示例

[Route("{id}"), HttpGet]
public IHttpActionResult Test()
{
    // Simple and easy
    var route1 = Request.GetRouteData().Values["id"];

    // Wat. This is also ~6 times slower
    var routeValues = (IHttpRouteData[]) HttpContext.Current.Request.RequestContext.RouteData.Values["MS_SubRoutes"];
    var route2 = routeValues.SelectMany(x => x.Values).Where(x => x.Key == "id").Select(x => x.Value).FirstOrDefault();

    return Ok(route1 == route2); // true
}

【问题讨论】:

    标签: c# asp.net asp.net-web-api routes asp.net-web-api2


    【解决方案1】:

    第一部分

    问题的答案——

    为什么在控制器的 Request 中获取路由值那么容易,但是 几乎不可能在 HttpContext.Current.Request 上做同样的事情?

    我不会详细介绍类实现和其他的所有细节。让我们只考虑模型、视图和控制器在 MVC 架构中的责任。您可以看到只有 Controller 负责将路由映射到视图,反之亦然。这是 MVC 架构中唯一需要路由的部分。所以很容易理解,为什么在Controller里面很容易找到路由值。

    现在是实现细节。是的,当然,MS 人员已经做了大量工作以使其在控制器中易于访问,只是一个简单的属性。但如果你想在控制器之外使用它,你仍然可以拥有它,但这是一项艰苦的工作。这是相当大的,因为除非你试图搞乱架构的抽象层,否则无论如何你都不需要控制器外部的路由。

    第二部分

    现在是第二个答案 -

    有人可以确认这是在控制器之外获取路由数据的唯一方法吗?

    当然还有其他方法。事实上,我自己也无法理解你为什么要通过这么努力的工作来获得路线价值?您不是在控制器中编写操作方法吗?如果是这样,那么为什么不将其用作参数呢? -

    [Route("{id}"), HttpGet]
    public IHttpActionResult Test(int? id) //the easiest way to get route value for {id}
    {
        // Simple and easy
        var route1 = Request.GetRouteData().Values["id"];
    
        // Wat. This is also ~6 times slower
        var routeValues = (IHttpRouteData[]) HttpContext.Current.Request.RequestContext.RouteData.Values["MS_SubRoutes"];
        var route2 = routeValues.SelectMany(x => x.Values).Where(x => x.Key == "id").Select(x => x.Value).FirstOrDefault();
    
        return Ok(route1 == route2 == id.Value); // true //should be true, and of course you should add null check since it is int? not int. But that is not significant here so I didn't do it.
    }
    

    【讨论】:

      【解决方案2】:

      试试下面的代码获取路线数据:

      var routeValues = Request.GetRouteData().Values["MS_SubRoutes"];
      

      注意:

      请求的类型是System.Net.Http.HttpRequestMessage。它是System.Web.Http.ApiController 类的属性,或者你可以从 eleswhere 获取。

      GetRouteDataSystem.Net.Http.HttpRequestMessageExtensions 类中的扩展方法。

      【讨论】:

      • 是的,我明白了。但是如果我想在控制器之外获取路由怎么办?然后我只能访问HttpContext.Current
      • 我不知道其他方式,但 (IHttpRouteData[]) HttpContext.Current.Request.RequestContext.RouteData.Values["MS_SubRoutes"] 在这种情况下在控制器之外