ASP.NETWebAPIリクエストパイプラインの実行順序に問題があります。
ASP.NET Web APIドキュメント(ここで入手可能)によると、グローバルメッセージハンドラーはルーティングメカニズムの前に実行されることになっています。
この画像でMessageHandler1
は、はグローバルメッセージハンドラですが、ルート2MessageHandler2
に固有です。
実行順序に問題があるように見えることを示すために、非常に簡単な例を作成しました…または、重要な何かが本当に欠けています。
私はこのコントローラーを持っています
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
PutMe
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
、ブラウザ内でリクエストすると、プログラムが最初にHttpPutOnlyConstraint
のMatch
メソッドを入力することです。これは間違っています。
以前にリンクされた画像を参照すると、メッセージハンドラーが最初に実行されることになっていますが、残念ながらそうではありません。
したがって、もちろん、Match
戻りfalse
、要求に対するコントローラー/アクションが見つからない場合、404が発生します。
ルート定義から制約を削除すると、プログラムが入力SimpleMethodOverrideHandler
され、リクエストのメソッドが正常に変更され、コントローラーのメソッドと一致して実行できるようになります。
私は何か間違ったことをしていますか?そのようなことをするために知っておくべき秘密の構成パラメーターはありますか?:-)
プロジェクト全体が必要な場合は、ここ[7KBzipファイル]から入手できます。
ありがとうございました。