为什么在控制器上下文之外获取路由值如此困难?

我不明白这背后的交易是什么,为什么在控制器的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 } 

第一部分

问题的答案 –

为什么在控制器的请求中获取路由值如此容易,但在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. } 

尝试以下代码获取路径数据:

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

注意:

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

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