好吧,我想我有這個破解。我用身份驗證方案說明了這一點:我想異步驗證用戶,並使用結果來決定是返回401還是繼續使用消息處理程序鏈。
的中心問題是,你不能調用內處理SendAsync(),直到你從異步驗證結果。
對我來說,關鍵的洞察是使用TaskCompletionSource(TCS)來控制執行流程。這使我能夠從TCS返回任務,並隨時在其上設置結果 - 並且最重要的是將呼叫延遲SendAsync(),直到我知道我需要它爲止。
因此,我設置了TCS,然後開始執行授權任務。在繼續這個,我看看結果。如果被授權,我調用內部處理程序鏈並附加一個延續到這個完成TCS的(避免任何線程阻塞)。如果驗證失敗,我只是完成了TCS那裏,然後用這個401
結果是異步任務又沒有任何線程阻塞執行。我加載測試這個,它似乎工作得很好。
雖然.NET 4.5中的異步/等待語法雖然...雖然TCS的方法仍然基本上在封面上發生,但代碼要簡單得多。
享受!
第一個片段是基於.NET 4.0和Web API Beta構建的 - 第二個是.NET 4.5/Web API RC。
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調用之前進行另一個http調用,並且實例化另一個'HttpClient'。我想知道是否可以在處理程序中重新使用當前的程序,但似乎我不能 – JobaDiniz