概要
HttpClient を使用してWebリクエストを送信した際、通信自体は成功しても、サーバー側で「ページが見つからない(404)」や「内部エラー(500)」が発生している場合があります。
HttpResponseMessage.StatusCode プロパティを確認することで、サーバーからの応答結果に応じた適切な分岐処理(成功時のデータ読み込み、失敗時のログ出力など)を実装します。
仕様(入出力)
- 入力: アクセス先のURL。
- 出力: HTTPステータスコード(数値および名前)と、判定結果に応じた処理メッセージ。
- 前提: .NET標準ライブラリ(
System.Net.Http)を使用。
基本の使い方
GetAsync 等の戻り値である HttpResponseMessage オブジェクトから StatusCode プロパティを参照し、HttpStatusCode 列挙型と比較します。
HttpResponseMessage response = await client.GetAsync(url);
// 200 OK かどうかを判定
if (response.StatusCode == HttpStatusCode.OK)
{
// 成功時の処理
}
// 404 Not Found かどうかを判定
else if (response.StatusCode == HttpStatusCode.NotFound)
{
// エラー処理
}
コード全文
ここでは、異なるステータスコード(正常、404エラー、その他エラー)をシミュレーションし、それぞれの状況に合わせてコンソール出力を切り替える実装例です。
using System;
using System.Net; // HttpStatusCodeを使うために必要
using System.Net.Http;
using System.Threading.Tasks;
class Program
{
private static readonly HttpClient _client = new HttpClient();
static async Task Main()
{
// 1. 正常なURLへのアクセス (200 OK)
await CheckUrlAsync("http://httpbin.org/status/200");
Console.WriteLine();
// 2. 存在しないURLへのアクセス (404 Not Found)
await CheckUrlAsync("http://httpbin.org/status/404");
Console.WriteLine();
// 3. サーバーエラーが発生するURLへのアクセス (503 Service Unavailable)
await CheckUrlAsync("http://httpbin.org/status/503");
}
static async Task CheckUrlAsync(string url)
{
Console.WriteLine($"アクセス中: {url} ...");
try
{
// GetAsyncは、404や500が返ってきても例外を投げず、responseを返します
using var response = await _client.GetAsync(url);
// ステータスコードの表示
// (int)キャストすると数値(例: 200)、そのまま出力すると列挙型名(例: OK)になります
Console.WriteLine($"結果: {(int)response.StatusCode} {response.StatusCode}");
// ステータスコードに応じた分岐処理
switch (response.StatusCode)
{
case HttpStatusCode.OK:
string content = await response.Content.ReadAsStringAsync();
Console.WriteLine("成功: データを取得しました。");
break;
case HttpStatusCode.Created:
Console.WriteLine("成功: リソースが作成されました。");
break;
case HttpStatusCode.NotFound:
Console.WriteLine("エラー: 指定されたページは見つかりませんでした。");
break;
case HttpStatusCode.InternalServerError:
Console.WriteLine("エラー: サーバー内部でエラーが発生しています。");
break;
case HttpStatusCode.ServiceUnavailable:
Console.WriteLine("エラー: サーバーはメンテナンス中か高負荷状態です。");
break;
default:
// IsSuccessStatusCodeプロパティを使えば、200番台(200-299)をまとめて判定できます
if (response.IsSuccessStatusCode)
{
Console.WriteLine("成功: その他の正常応答です。");
}
else
{
Console.WriteLine("失敗: その他のエラーです。");
}
break;
}
}
catch (HttpRequestException ex)
{
Console.WriteLine($"通信エラー(DNS解決失敗など): {ex.Message}");
}
}
}
HttpStatusCode 代表的な値一覧
よく使用されるステータスコードの一覧です。
| フィールド | 値 (int) | 意味 |
| OK | 200 | リクエストは成功しました。最も一般的な成功レスポンスです。 |
| Created | 201 | リクエストは成功し、新しいリソースが作成されました(POST等)。 |
| NoContent | 204 | リクエストは成功しましたが、返すコンテンツはありません。 |
| MovedPermanently | 301 | リクエストされたリソースは恒久的に移動しました(転送)。 |
| BadRequest | 400 | リクエスト構文が誤っているため、サーバーが処理できませんでした。 |
| Unauthorized | 401 | 認証が必要です。または認証に失敗しました。 |
| Forbidden | 403 | リソースへのアクセス権限がありません(認証されていても拒否)。 |
| NotFound | 404 | リクエストされたリソースが見つかりませんでした。 |
| Conflict | 409 | リクエストが現在のサーバーの状態と競合しています。 |
| InternalServerError | 500 | サーバー内部で予期せぬエラーが発生しました。 |
| ServiceUnavailable | 503 | サーバーは現在利用できません(過負荷やメンテナンス)。 |
カスタムポイント
- 成功かどうかの簡易判定: 特定のコードではなく「成功したかどうか(200-299)」だけを知りたい場合は、
response.IsSuccessStatusCodeプロパティ(bool型)を使用するのが便利です。 - 強制例外: ステータスコードがエラーの場合に即座に例外を発生させたい場合は、
response.EnsureSuccessStatusCode()を呼び出します。これにより、404や500の時にHttpRequestExceptionがスローされます。 - 整数による判定:
HttpStatusCode列挙型に定義されていない特殊なコードが返ってくる可能性がある場合は、(int)response.StatusCodeで数値として取得し、判定を行ってください。
注意点
- 例外との違い:
GetAsyncメソッドは、サーバーから応答(404や500を含む)がある限り例外を投げません。例外が発生するのは「DNS解決失敗」「タイムアウト」「ネットワーク切断」などの通信レベルのエラー時のみです。したがって、try-catchだけでなくStatusCodeのチェックが必須です。 - リダイレクト:
HttpClientのデフォルト設定では、301や302のリダイレクトは自動的に追跡(新しいURLへ移動)され、最終的なページのステータスコード(通常は200)が返ります。3xx系を検知したい場合は、HttpClientHandler.AllowAutoRedirect = falseの設定が必要です。
応用
処理の成功を保証するパターン
エラー時に処理を中断させたい場合、EnsureSuccessStatusCode を使うとコードを短く記述できます。
var response = await _client.GetAsync(url);
// 200-299以外ならここで例外が発生し、catchブロックへ飛ぶ
response.EnsureSuccessStatusCode();
// ここに来る=成功していることが保証される
var html = await response.Content.ReadAsStringAsync();
まとめ
Web API連携やスクレイピングにおいて、HTTPステータスコードの確認はエラーハンドリングの要です。正常系(200 OK)だけでなく、リソース不在(404)やサーバーエラー(500系)を明示的にハンドリングすることで、アプリケーションの堅牢性が向上します。基本的には列挙型 HttpStatusCode を使用して可読性を高め、必要に応じて IsSuccessStatusCode や EnsureSuccessStatusCode を使い分ける実装が推奨されます。
