为什么在控制器上下文之外获取路由值如此困难?
本文关键字:路由 获取 控制器 上下文 为什么 | 更新日期: 2023-09-27 18:13:36
我不明白这背后的交易是什么,为什么很容易在控制器的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架构中模型、视图和控制器的职责。你可以看到,只有控制器有责任将路由映射到视图,反之亦然。这是MVC架构中唯一需要路由的部分。因此,很容易理解为什么在Controller中查找路由值如此容易。
现在是实现细节。是的,当然微软的人已经做了大量的工作来使它在控制器内部容易访问,只是一个简单的属性。但如果你想在控制器外使用它,你仍然可以使用它,但这是一项艰巨的工作。这是相当可观的,因为除非你试图弄乱架构的抽象层,否则无论如何你都不需要控制器外部的路由。
第二部分:
现在是第二个答案-
有人能确认这是唯一的方法来获得路由数据外控制器?
当然还有其他方法。事实上,我自己也不明白为什么你要通过这么努力的工作来获得路由值?你不是在控制器中编写动作方法吗?如果是这样,为什么不直接使用它作为参数呢?-
[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
类的属性,或者您可以从其他地方获得它。
GetRouteData是System.Net.Http.HttpRequestMessageExtensions
类中的一个扩展方法。