通过modelbinder手动传递url以获取RouteData参数 [英] Manually pass a url through the modelbinder to obtain the RouteData parameters
问题描述
我有一个复杂的ASP.NET MVC路由方案,我希望能够使用现有路由来解析从"Referrer"请求标头中提取的URL.
I have a complex ASP.NET MVC routing scenario and I want to be able to parse a URL that I pull from the 'Referrer' request header using the existing routes.
我收到的传入请求看起来像这样:
I have incoming requests that look like this:
http://hostname/{scope}/{controller}/{action}
具有相应的路由映射:
routes.MapRoute(
name: "scoped",
url: "{scope}/{controller}/{action}/{id}",
defaults: new { controller = "Equipment", action = "Index", id = UrlParameter.Optional, scope = "shared" }
);
routes.MapRoute(
name: "scoped",
url: "{scope}/{controller}/{action}/{id}",
defaults: new { controller = "Equipment", action = "Index", id = UrlParameter.Optional, scope = "shared" }
);
在我的控制器基类的OnActionExecuting
方法中,我从RouteData中拉出结果scope
:
In the OnActionExecuting
method of the base class of my controllers I pull the resulting scope
from the RouteData:
var scope= (filterContext.RouteData.Values["scope"] as string).ToLower();
然后,我使用作用域为我的数据库查询构造一些过滤器.在我将所有返回Json的方法移至另一套WebApi2控制器之前,一切工作都很好.我现在也有一条路线:
I then use the scope to construct some filters for my database queries. It all worked perfectly fine until I moved all my Json-returning methods to a separate set of WebApi2 controllers. I now also have a route:
config.Routes.MapHttpRoute( 名称:"DefaultApi", routeTemplate:"api/{controller}/{action}" );
config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/{action}" );
现在所有的ajax请求都向api控制器发出,这意味着我没有可用的scope
值.我想通过使用请求标头中的"Referrer" URL来解决此问题,该URL通常是确实包含scope
的URL.
All ajax requests are now made to the api controllers, which means that I do not have the scope
value available. I want to solve this by using the 'Referrer' URL from the request header, which is is usually a URL that does include the scope
.
当ApiController初始化时,我想做的是这样的事情:
What I would like to do is something like this when the ApiController initializes:
public void PullCurrentScopeDomainFromRequestHeader(System.Net.Http.Headers.HttpRequestHeaders headers) {
var refererUrl = headers.GetValues("Referer").First();
//do some magic to get the scope
}
困难之处在于,如果诸如" http之类的url,则范围还可以具有默认值(共享").//hostname/controller/action " get.传入任何URL的最佳(和DRYest)方法都是通过某种方式使用我在路由配置中映射的作用域"路由进行解析网址.我只是不知道该怎么做.有人可以帮忙吗?
The difficulty is that the scope can also have a default value ("shared"), in case a url like "http://hostname/controller/action" get's passed in. The best (and DRYest) way to get the scope from any URL, would be by somehow using the "scoped" route that I mapped in the routing config to parse the URL somehow. I just have no idea how to do that. Can anyone help?
推荐答案
您只需要根据您的URL构建一个伪造的HTTP上下文,然后使用静态RouteTable
将URL解析为RouteValueDictionary
./p>
You just need to build up a fake HTTP context based on your URL and then use the static RouteTable
to parse the URL into a RouteValueDictionary
.
// Create a fake HttpContext using your URL
var uri = new Uri("http://hostname/controller/action", UriKind.Absolute);
var request = new HttpRequest(
filename: string.Empty,
url: uri.ToString(),
queryString: string.IsNullOrEmpty(uri.Query) ? string.Empty : uri.Query.Substring(1));
// Create a TextWriter with null stream as a backing stream
// which doesn't consume resources
using (var nullWriter = new StreamWriter(Stream.Null))
{
var response = new HttpResponse(nullWriter);
var httpContext = new HttpContext(request, response);
var fakeHttpContext = new HttpContextWrapper(httpContext);
// Use the RouteTable to parse the URL into RouteData
var routeData = RouteTable.Routes.GetRouteData(fakeHttpContext);
var values = routeData.Values;
// The values dictionary now contains the keys and values
// from the URL.
// Key | Value
//
// controller | controller
// action | action
// id | {}
}
请注意,您还可以通过指定RouteTable
的名称来使用它的特定路由.
Note that you can also use a specific route from the RouteTable
by specifying its name.
var routeData = RouteTable.Routes["scoped"].GetRouteData(fakeHttpContext);
这篇关于通过modelbinder手动传递url以获取RouteData参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!