4

HttpClient を使用して API コンシューマを構築しています。プロバイダーはコンシューマーがダイジェスト認証を使用して認証する必要があるため、以下のようなカスタム DelegatingHandler を記述する必要があります。

public class DigestAuthDelegatingHandler : DelegatingHandler
{
    public DigestAuthDelegatingHandler(HttpMessageHandler innerHandler) : base(innerHandler) { }
    protected async override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        var response = await base.SendAsync(request, cancellationToken);
        if (!response.IsSuccessStatusCode && response.StatusCode == HttpStatusCode.Unauthorized)//This line of code is never reached
        {
            //Generate the Digest Authorization header string and add to the request header,
            //then try to resend the request to the API provider
        }
        return response;
    }
}

HttpClient を作成し、カスタム DelegatingHandler をメッセージ ハンドラー pineline に追加します。

HttpClient httpClient = new HttpClient(new DigestAuthDelegatingHandler(new HttpClientHandler()));            
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
httpClient.BaseAddress = new Uri("http://127.0.0.1/");
HttpResponseMessage response = httpClient.GetAsync("api/getTransactionInfo?TransactionNumber=1000).Result;   

それを行った後、私の消費者は永久に実行されているように見えます。上記のコード行の await base.SendAsync の後にブレーク ポイントを追加すると、コードが返されないことがわかります。そのため、Digest 承認ヘッダーの詳細を抽出するために、応答が 401 の承認を受けていないかどうかを確認する方法がありません。従来の WebHttpRequest サポート Digest Authenticate を使用して別の API コンシューマー サイトを正常に構築したため、API プロバイダーに問題はありません。

重要な注意: コンシューマをコンソール アプリケーションとして記述するように切り替えると、うまく機能します。それで、よくわかりませんが、非同期モードで実行している場合、ASP.NET スレッドに関連する問題だと思いますか?

私がやっていることは何か間違っていますか?

4

3 に答える 3

1

ダレルに同意します-おそらく、タスクに障害があり、結果はありません...明示的な継続を使用して、タスクの状態を検査できます-たとえば、

return base.SendAsync(request, cancellationToken).ContinueWith(task =>
    {
        // put the code to check the task state here...
    });

DelegatingHandler別のメモとして、認証用のカスタムを作成する必要があるかどうかはわかりません... CredentialsHttpClientHandlerプロパティで使用してみてください(またはUseDefaultCredentialsを使用して現在のユーザーのデフォルトの資格情報を渡します)

var httpClient = new HttpClient(new HttpClientHandler() {
       PreAuthenticate = true,
       Credentials = new NetworkCredentials(...
   }); 

編集:資格情報キャッシュを使用して http クライアントで使用されているダイジェスト認証の例を見つけました-この SO Q & A を参照してください: HttpRequestMessage とダイジェスト認証

これにより、独自のハンドラーを作成せずに、ダイジェスト認証に関する実際の問題を解決できます。

于 2012-10-26T10:54:35.257 に答える
0

My guess is the .Result is blocking the continuation in your handler. Try changing the .Result to a .ContinueWith

于 2012-10-25T04:15:25.490 に答える
0

この同じ問題に遭遇したので、これが私にとってうまくいったものです。問題は、エンドポイントが 500 内部サーバー エラーをスローし、スレッドがブロックされたことです。

protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        return await base.SendAsync(request, cancellationToken)
                         .ContinueWith<HttpResponseMessage>(task =>
        {
            return task.Result;
        });
    }

anon 関数内の return は SendAsync 関数に戻り、実際に Result を返すことに注意してください。

于 2018-01-22T14:52:24.683 に答える