路由&消息处理程序:请求处理订单问题

时间:2012-12-19 18:35:24

标签: c# asp.net asp.net-web-api

我遇到了ASP.NET Web API请求管道的执行顺序问题。

根据ASP.NET Web API文档(可用here),全局消息处理程序应该在路由机制之前执行。

Request pipeline

在此图片上,MessageHandler1是全局消息处理程序,而MessageHandler2特定于路由2


我创建了一个非常简单的例子来表明执行顺序中似乎存在问题...或者我真的错过了一些重要的事情。

我有这个控制器

public class FooController : ApiController {
    [HttpPut]
    public string PutMe() {
        return Request.Method.Method;
    }
}

它只接受PUT次请求。

应用程序配置如下:

protected void Application_Start() {
    var configuration = GlobalConfiguration.Configuration;

    configuration.MessageHandlers.Add( new SimpleMethodOverrideHandler() );
    configuration.Configuration.Routes.MapHttpRoute(
        name: "Foo",
        routeTemplate: "api/foo",
        defaults: new { controller = "foo", action = "putme" },
        constraints: new { put = new HttpPutOnlyConstraint() }
    );
}

SimpleMethodOverrideHandler是一个非常简单的DelegatingHandler,只是根据查询字符串中的"method"参数更改了请求的方法。

public class SimpleMethodOverrideHandler : DelegatingHandler {
    protected override Task<HttpResponseMessage> SendAsync( HttpRequestMessage request, CancellationToken cancellationToken ) {
        var method = request.RequestUri.ParseQueryString()["method"];
        if( !string.IsNullOrEmpty( method ) ) {
            request.Method = new HttpMethod( method );
        }
        return base.SendAsync( request, cancellationToken );
    }
}

基本上,在我的浏览器中请求/api/foo?method=put会启动FooController的{​​{1}}方法。
实际上,如前所述,消息处理程序在请求传递给PutMe之前处理请求。

最后,这里是如何定义constaint HttpRoutingDispatched

HttpPutOnlyConstraint

问题是,当我在浏览器中请求public class HttpPutOnlyConstraint : IHttpRouteConstraint { public bool Match( HttpRequestMessage request, IHttpRoute route, string parameterName, IDictionary<string, object> values, HttpRouteDirection routeDirection ) { return request.Method == HttpMethod.Put; } } 时,程序首先输入/api/foo?method=put的{​​{1}}方法,这是错误的。

如果我们引用先前链接的图像,则应该首先执行消息处理程序,不幸的是它不是。

因此,当然,HttpPutOnlyConstraint会返回Match,并且找不到请求的控制器/操作,404会发生。

如果我从路由定义中删除约束,程序进入Match,请求的方法会成功更改,并且能够匹配并执行我的控制器方法。

我做错了吗?是否有秘密配置参数要知道才能做这些事情? : - )

如果有人需要整个项目,则可以使用here [7KB zip file]

谢谢。

1 个答案:

答案 0 :(得分:3)

您将路由引擎与Web API管道混淆。 HttpRoutingDispatcher不是路由引擎概念。将首先处理路径约束,因为您的基础主机需要构建路由表并匹配您的请求的路由。

HttpRoutingDispatcher只是HttpMessageHandler的另一个实现,它所做的只是检查已匹配的路由的IHttpRoute,并选择接下来要调用的消息处理程序。如果不存在每个路由处理程序,它会将处理委派给HttpControllerDispatcher