通过modelbinder手动传递一个url获取RouteData参数

Manually pass a url through the modelbinder to obtain the RouteData parameters

我有一个复杂的 ASP.NET MVC 路由场景,我希望能够使用现有的 'Referrer' 请求 header 解析 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" } );

在我的控制器的基础 class 的 OnActionExecuting 方法中,我从 RouteData:

中提取结果 scope
var scope= (filterContext.RouteData.Values["scope"] as string).ToLower();

然后我使用作用域为我的数据库查询构造一些过滤器。在我将所有 Json-returning 方法移至一组单独的 WebApi2 控制器之前,一切都运行良好。我现在也有一条路线:

config.Routes.MapHttpRoute( 姓名:"DefaultApi", 路线模板:"api/{controller}/{action}" );

所有 ajax 请求现在都发送给 api 控制器,这意味着我没有可用的 scope 值。我想通过使用请求 header 中的 'Referrer' URL 来解决这个问题,这通常是一个 URL,它确实包含 scope.

当 ApiController 初始化时,我想做的是这样的事情:

public void PullCurrentScopeDomainFromRequestHeader(System.Net.Http.Headers.HttpRequestHeaders headers) {
    var refererUrl = headers.GetValues("Referer").First();

    //do some magic to get the scope

}

困难在于范围也可以有一个默认值("shared"),以防传入一个像“http://hostname/controller/action”这样的url。最好的(和DRYest ) 从任何 URL 获取范围的方法是使用我在路由配置中映射的 "scoped" 路由以某种方式解析 URL。我只是不知道该怎么做。有人可以帮忙吗?

你只需要根据你的 URL 建立一个假的 HTTP 上下文,然后使用静态 RouteTable 将 URL 解析为 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);