手动将url传递给modelbinder以获取RouteData参数

时间:2016-01-24 15:08:13

标签: c# asp.net-mvc asp.net-mvc-routing

我有一个复杂的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。我根本不知道该怎么做。有人可以帮忙吗?

1 个答案:

答案 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);