我有一个复杂的ASP.NET MVC路由方案,我希望能够使用现有路由解析我从'Referrer'请求标头中提取的URL。
我的传入请求看起来像这样:
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" }
);
在我的控制器的基类的OnActionExecuting
方法中,我从RouteData中拉出结果scope
:
var scope= (filterContext.RouteData.Values["scope"] as string).ToLower();
然后我使用范围为我的数据库查询构建一些过滤器。这一切都完美无缺,直到我将所有Json返回方法移动到一组单独的WebApi2控制器。我现在也有路线:
config.Routes.MapHttpRoute( 名称:“DefaultApi”, routeTemplate:“api / {controller} / {action}” );
现在所有的ajax请求都发送到api控制器,这意味着我没有可用的scope
值。我想通过使用请求标头中的“推荐人”网址解决此问题,该网址通常是包含scope
的网址。
当ApiController初始化时,我想做的是这样的事情:
public void PullCurrentScopeDomainFromRequestHeader(System.Net.Http.Headers.HttpRequestHeaders headers) {
var refererUrl = headers.GetValues("Referer").First();
//do some magic to get the scope
}
难度在于范围也可以有一个默认值(“共享”),以防万一像“http://hostname/controller/action”这样的网址被传入。最好的(和DRYest)方式从任何地方获取范围URL,将以某种方式使用我在路由配置中映射的“范围”路由以某种方式解析URL。我根本不知道该怎么做。有人可以帮忙吗?
答案 0 :(得分:1)
您只需根据您的网址构建虚假的HTTP上下文,然后使用静态RouteTable
将网址解析为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
中的特定路线。
var routeData = RouteTable.Routes["scoped"].GetRouteData(fakeHttpContext);