我遇到了 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 文件]。
谢谢你。