C#を用いたWebアプリケーション開発やAPI連携において、避けては通れないのがHTTPステータスコードにまつわるトラブルシューティングです。
特に、ASP.NET CoreなどでAPIを構築している際に、クライアントからのリクエストに対して「415 Unsupported Media Type」というエラーが返されることがあります。
このエラーは、サーバー側が受け取ったリクエストのデータ形式を理解できない、あるいはサポートしていないことを示しています。
開発者にとって、このエラーは一見単純そうに見えて、原因の切り分けに時間を要することが少なくありません。
本記事では、C#における415エラーの根本的な原因から、サーバー側・クライアント側それぞれの具体的な解決策までを詳しく解説します。
415 Unsupported Media Typeエラーとは何か
HTTP 415エラーは、クライアントが送信したペイロードのフォーマットが、サーバー上のリソースでサポートされていない場合に発生するレスポンス状態コードです。
例えば、サーバーがJSON形式のデータのみを待ち受けているのに対し、クライアントがXML形式やプレーンテキスト形式でデータを送信した場合にこのエラーが返されます。
この通信の不一致を判断するために、HTTPヘッダーの「Content-Type」が重要な役割を果たします。
サーバーはリクエストヘッダーに含まれる Content-Type を参照し、自身のハンドラがその形式を処理できるかを確認します。
もし適切なフォーマッタが見つからない場合、ASP.NET Coreのフレームワークは自動的に415エラーを生成してレスポンスを返します。
つまり、415エラーは「データの送信形式に関するミスマッチ」が発生しているシグナルなのです。
C#(ASP.NET Core)で415エラーが発生する主な原因
C#でAPIを開発している際、415エラーが発生する原因はいくつか典型的なパターンに分類されます。
まずは、どのような状況でこの問題が起きやすいのかを確認してみましょう。
1. Content-Typeヘッダーの指定漏れまたは間違い
最も多い原因は、クライアント側がリクエストを送信する際に Content-Type ヘッダーを正しく設定していないことです。
特に HttpClient を使用して手動でリクエストを作成する場合、デフォルトではヘッダーが空のまま送信されることがあります。
JSONを送信しているつもりでも、サーバー側がそれを認識できなければエラーとなります。
2. サーバー側の[ApiController]属性とモデルバインディング
ASP.NET Coreでは、コントローラーに [ApiController] 属性を付与することが推奨されています。
この属性が付与されている場合、フレームワークは非常に厳格にコンテンツタイプをチェックするようになります。
アクションメソッドの引数に [FromBody] を指定している場合、デフォルトで application/json などの特定の形式を期待します。
3. 入力フォーマッタの設定不足
独自のデータ形式を扱いたい場合、ASP.NET Coreのパイプラインに適切な「入力フォーマッタ」が登録されていないと415エラーが発生します。
例えば、XML形式のデータを扱いたい場合は、明示的にXMLフォーマッタを追加する必要があります。
原因のまとめ表
| 原因のカテゴリ | 具体的な内容 | 解決の方向性 |
|---|---|---|
| クライアント側 | Content-Typeヘッダーの欠落 | application/jsonなどの明示 |
| サーバー側(属性) | [FromBody]や[Consumes]の不一致 | 属性指定の確認と修正 |
| 構成設定 | JSON/XMLフォーマッタの未登録 | Program.csでのサービス追加 |
クライアント側(HttpClient)での解決策
C#の HttpClient を使用してAPIを呼び出す場合、正しいメディアタイプを指定することが不可欠です。
まずは、エラーが発生しやすい不適切なコード例を見てみましょう。
// エラーが発生しやすい例(Content-Typeが設定されていない)
var client = new HttpClient();
var content = new StringContent("{\"name\":\"test\"}");
// デフォルトのContent-Typeは text/plain になることが多い
var response = await client.PostAsync("https://example.com/api/data", content);
上記のコードでは、StringContent の第2引数を省略しているため、サーバーが期待する application/json として認識されません。
これを修正するには、以下のように 明示的にメディアタイプを指定 する必要があります。
// 修正後の正しい例
using System.Net.Http.Json; // System.Net.Http.Jsonを使用
var client = new HttpClient();
var data = new { Name = "test" };
// PostAsJsonAsyncを使用すると自動的に application/json が設定される
var response = await client.PostAsJsonAsync("https://example.com/api/data", data);
if (response.StatusCode == System.Net.HttpStatusCode.UnsupportedMediaType)
{
Console.WriteLine("415エラーが発生しました。メディアタイプを確認してください。");
}
また、HttpRequestMessage を直接使用してヘッダーを細かく制御する方法も有効です。
// 手動でヘッダーを設定する方法
var request = new HttpRequestMessage(HttpMethod.Post, "https://example.com/api/data");
var jsonString = "{\"name\":\"test\"}";
request.Content = new StringContent(jsonString, System.Text.Encoding.UTF8, "application/json");
var result = await client.SendAsync(request);
サーバー側(ASP.NET Core API)での解決策
サーバー側で415エラーを回避するためには、コントローラーの設定とサービス構成の両面を確認する必要があります。
1. [Consumes] 属性による許可型の明示
特定のアクションメソッドが受け入れるコンテンツタイプを制限、あるいは明示したい場合は [Consumes] 属性を使用します。
[ApiController]
[Route("api/[controller]")]
public class DataController : ControllerBase
{
[HttpPost]
[Consumes("application/json")] // JSONのみを受け入れることを明示
public IActionResult PostData([FromBody] MyModel model)
{
return Ok(model);
}
}
2. Program.cs でのフォーマッタ設定
もしAPIでXML形式もサポートしたい場合は、AddControllers メソッドのオプションで設定を変更します。
// Program.cs の設定例
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers()
.AddXmlSerializerFormatters(); // XMLサポートを追加
var app = builder.Build();
このように設定することで、クライアントが Content-Type: application/xml でデータを送信してきた場合でも、415エラーを返さずに処理できるようになります。
3. [FromBody] 属性の挙動を理解する
[FromBody] 属性は、リクエストボディからデータを読み取ってオブジェクトにバインドしようとします。
この際、Content-Type が指定されていないと、フレームワークはどのフォーマッタを使ってデシリアライズすべきか判断できず、415エラーを投げます。
もしデータがJSONでない可能性がある場合は、モデルバインドの方法を再検討する必要があります。
トラブルシューティングの実践的な手順
415エラーが解消されない場合は、以下のステップでデバッグを行ってください。
ステップ1:リクエストヘッダーの監視
FiddlerやPostman、またはブラウザの開発者ツールを使用して、実際に送信されている Content-Type ヘッダーの値を正確に把握してください。
綴りミスがないか、余計な空白が含まれていないかを確認することが重要です。
ステップ2:サーバーログの確認
ASP.NET Coreのログレベルを Information や Debug に設定すると、なぜフォーマッタが拒否されたのかの詳細な理由が出力されることがあります。
「No input formatter was found to support the content type ‘xxx’」といったメッセージが出ていれば、そのタイプが未登録であることが確定します。
ステップ3:Minimal APIの場合の注意点
C#の最新の機能である Minimal API を使用している場合、引数のバインドルールが従来のコントローラーとは若干異なります。
複雑な型を引数に取る場合、暗黙的にリクエストボディからの読み取りが試みられますが、この場合も正しい Content-Type が必須となります。
// Minimal API の例
app.MapPost("/data", (MyModel model) =>
{
return Results.Ok(model);
});
このコードに対しても、application/json 以外の形式でリクエストを投げると 415 エラーが発生します。
まとめ
C#開発における「415 Unsupported Media Type」エラーは、そのほとんどがクライアントとサーバー間の「通信規約(プロトコル)の不一致」に起因します。
解決のためには、まずクライアント側で送信している Content-Typeヘッダーが適切であるか を最優先で確認してください。
次に、サーバー側のコントローラーにおいて、[FromBody] 属性や [Consumes] 属性の設定が、期待するデータ形式と矛盾していないかをチェックしましょう。
XMLなどの標準以外の形式を扱う場合は、プロジェクトの構成ファイル(Program.cs)にて適切なフォーマッタを追加することを忘れないでください。
HTTPヘッダーの役割を正しく理解し、型安全なAPI開発を心がけることで、415エラーに悩まされる時間を大幅に削減できるはずです。
日頃から PostAsJsonAsync のような便利な拡張メソッドを活用し、設定ミスが起こりにくいコードを記述することが、安定したシステム構築への近道となります。
