EnsureSuccessStatusCodeの使用とそれがスローするHttpRequestExceptionの処理


103

の使用パターンはHttpResponseMessage.EnsureSuccessStatusCode()何ですか?メッセージのContentを破棄してスローしますHttpRequestExceptionが、一般的な方法とは異なる方法でプログラムで処理する方法はわかりませんException。たとえば、HttpStatusCode便利なは含まれていません。

それからより多くの情報を得る方法はありますか?誰もが両方EnsureSuccessStatusCode()とHttpRequestExceptionの関連する使用パターンを示すことができますか?

回答:


155

の慣用的な使用法はEnsureSuccessStatusCode、特定の方法で失敗のケースを処理したくない場合に、リクエストの成功を簡潔に検証することです。これは、クライアントのプロトタイプをすばやく作成したい場合に特に便利です。

障害のケースを特定の方法で処理する場合は、次のことは行わないでください。

var response = await client.GetAsync(...);
try
{
    response.EnsureSuccessStatusCode();
    // Handle success
}
catch (HttpRequestException)
{
    // Handle failure
}

これはすぐにそれをキャッチするために例外をスローしますが、意味がありません。のIsSuccessStatusCodeプロパティはHttpResponseMessageこの目的のためにあります。代わりに以下を実行してください。

var response = await client.GetAsync(...);
if (response.IsSuccessStatusCode)
{
    // Handle success
}
else
{
    // Handle failure
}

1
実際の整数のステータスコードを取得する方法はありますか?これを試すと、404ステータスコードの代わりに「NotFound」などの文字列が表示されます。
NickG 2016

12
@NickG (int)response.StatusCodemsdn.microsoft.com/en-us/library/…を参照)
Timothy Shields

1
EnsureSuccessStatusCode()によってスローされるデフォルトのHttpRequestExceptionには理由フレーズが含まれることに注意してください。しかし、成功しなければ、応答でとにかくそのプロパティにアクセスできます。
Stefan Zvonar 2017

@StefanZvonarあなたが書いたものとして例外の理由フレーズを見つけることができません。
KansaiRobot

1
@NickG(int)response.StatusCodeを使用して、HTTPステータスコードの数値を取得できます
Henrik HolmgaardHøyerMay

95

意味のある何も返さないので、EnsureSuccessStatusCodeは好きではありません。それが私が自分の拡張機能を作成した理由です:

public static class HttpResponseMessageExtensions
{
    public static async Task EnsureSuccessStatusCodeAsync(this HttpResponseMessage response)
    {
        if (response.IsSuccessStatusCode)
        {
            return;
        }

        var content = await response.Content.ReadAsStringAsync();

        if (response.Content != null)
            response.Content.Dispose();

        throw new SimpleHttpResponseException(response.StatusCode, content);
    }
}

public class SimpleHttpResponseException : Exception
{
    public HttpStatusCode StatusCode { get; private set; }

    public SimpleHttpResponseException(HttpStatusCode statusCode, string content) : base(content)
    {
        StatusCode = statusCode;
    }
}

MicrosoftのEnsureSuccessStatusCodeのソースコードはここにあります

SOリンクに基づく同期バージョン:

public static void EnsureSuccessStatusCode(this HttpResponseMessage response)
{
    if (response.IsSuccessStatusCode)
    {
        return;
    }

    var content = response.Content.ReadAsStringAsync().GetAwaiter().GetResult();

    if (response.Content != null)
        response.Content.Dispose();

    throw new SimpleHttpResponseException(response.StatusCode, content);
}

IsSuccessStatusCodeについて私が気に入らないのは、「うまく」再利用できないことです。たとえば、pollyのようなライブラリを使用して、ネットワークの問題が発生した場合にリクエストを繰り返すことができます。その場合は、pollyまたは他のライブラリが処理できるように、コードで例外を発生させる必要があります...


1
同意してください。デフォルトのコードには機能がありません。リターンから意味のあるメッセージを取得します。
LT

2
お使いのバージョンは、の元の実装とは異なりEnsureSuccessStatusCodeます。あなたはいつも処分response.Content(最終的にした後も、常に呼び出されるためreturn;の文)と、それはfuther読書のためのコンテンツを破壊します。元の実装では、ステータスコードが成功の結果を示さない場合にのみコンテンツが破棄されます。
Lukas.Navratil

4
なぜあなたが最初await response.Content.ReadAsStringAsync()にそれから次にチェックするのか分かりませんif (response.Content != null)
mafu

3
Pollyは、この種のシナリオを支援するために、例外だけでなく戻り結果も処理するようになりました。HttpRequestコールを保護するようにPollyを設定し、特定の例外と特定HttpResponseCodeのを処理するようにポリシーを設定できます。こちらのポリーのreadmeの例を
山岳旅行者

2
response.Contentメソッドが呼び出された直後にnullになる可能性があるのはなぜですか?
Ian Warburton

1

同じメソッドで例外を処理したくない場合は、EnsureSuccessStatusCodeを使用します。

public async Task DoSomethingAsync(User user)
{
    try
    {
        ...
        var userId = await GetUserIdAsync(user)
        ...
    }
    catch(Exception e)
    {
        throw;
    }
}

public async Task GetUserIdAsync(User user)
{
    using(var client = new HttpClient())
    {
        ...
        response = await client.PostAsync(_url, context);

        response.EnsureSuccesStatusCode();
        ...
    }
}

GetUserIdAsyncでスローされる例外は、DoSomethingAsyncで処理されます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.