4

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

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

请求管道

在此图像上,MessageHandler1是一个全局消息处理程序,而MessageHandler2特定于Route 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'sPutMe方法。
实际上,如前所述,消息处理程序在将请求传递给HttpRoutingDispatched.

最后,这里是如何HttpPutOnlyConstraint定义 const 的:

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在浏览器中请求时,程序首先进入HttpPutOnlyConstraint'Match方法,这是错误的。

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

因此,当然,Match返回false并且没有为请求找到控制器/操作,发生 404。

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

难道我做错了什么?为了做这样的事情,是否有一个秘密的配置参数需要知道?:-)

如果有人需要整个项目,可以在此处获得 [7KB zip 文件]

谢谢你。

4

1 回答 1

3

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

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

于 2012-12-19T18:54:06.043 回答