いいえ、私はこれが割れていると思います。私は認証シナリオでこれを説明しています。ユーザーを非同期で認証し、その結果を使用して401を返すか、メッセージハンドラチェーンを続行するかを決定します。
主な問題は、非同期認証の結果が得られるまで内部ハンドラSendAsync()を呼び出すことができないことです。
私の主な洞察は、TaskCompletionSource(TCS)を使用して実行フローを制御することでした。これにより私はTCSからタスクを返し、好きなときに結果を設定できました。そして、最も重要なのは、SendAsync()を必要なことがわかるまで待つことです。
私はTCSをセットアップしてから、承認を行うタスクを開始しました。これに続き、私は結果を見る。承認されている場合は、内側のハンドラチェーンを呼び出し、(スレッドがブロックされないようにする)に続けて、TCSを完成させるを付けます。認証が失敗した場合は、TCSを完了してから401を実行するだけです。
この結果、両方の非同期タスクがスレッドブロッキングなしで順番に実行されます。私はこれをロードしてロードし、それは正常に動作するようです。
.NET 4.5では、async/awaitの構文を使った方がはるかにいいです... TCSのアプローチは基本的には基本的にはカバーではありますが、コードははるかに簡単です。
お楽しみください!
最初のスニペットは、.NET APIを使用して.NET 4.0でビルドされました.Web API Betaは.NET 4.5/Web API RCで2番目のスニペットです。ここで
protected override Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request, CancellationToken cancellationToken)
{
var taskCompletionSource = new TaskCompletionSource<HttpResponseMessage>();
// Authorize() returns a started
// task that authenticates the user
// if the result is false we should
// return a 401 immediately
// otherwise we can invoke the inner handler
Task<bool> authenticationTask = Authorize(request);
// attach a continuation...
authenticationTask.ContinueWith(_ =>
{
if (authenticationTask.Result)
{
// authentication succeeded
// so start the inner handler chain
// and write the result to the
// task completion source when done
base.SendAsync(request, cancellationToken)
.ContinueWith(t => taskCompletionSource.SetResult(t.Result));
}
else
{
// authentication failed
// so complete the TCS immediately
taskCompletionSource.SetResult(
new HttpResponseMessage(HttpStatusCode.Unauthorized));
}
});
return taskCompletionSource.Task;
}
がある新しいとたくさんセクシーです.NET 4.5 /ウェブAPIのリリース候補版非同期/のawait構文:
protected override async Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request, CancellationToken cancellationToken)
{
// Authorize still has a Task<bool> return type
// but await allows this nicer inline syntax
var authorized = await Authorize(request);
if (!authorized)
{
return new HttpResponseMessage(HttpStatusCode.Unauthorized)
{
Content = new StringContent("Unauthorized.")
};
}
return await base.SendAsync(request, cancellationToken);
}
はどのようにあなたが 'Authorize'を実現したのですか?あなたは新しい 'HttpClient'をインスタンス化しましたか? – JobaDiniz
Authorizeの実装はここでは関係ありません。要求を許可するかどうかを決定するのは単なる非同期関数なので、実装する方法はあなた次第です。例えば、現在のユーザがいくつかの注文されたビジネスルールに基づいて現在のリクエストを行うためのアクセス権を持っているかどうかを確認するために、データベースをチェックすることができます。 –
もう一つのhttpリクエストを作成するかどうかは不思議でした。私のシナリオでは、現在のものより前に別のhttpコールを行う必要があり、別の 'HttpClient'がインスタンス化されています。私は、ハンドラの中で現在のものを再利用できるかどうか疑問に思っていましたが、それはできないようです。 – JobaDiniz