by WebSurfer
7. June 2020 14:12
.NET Framework 版の ASP.NET Web API を要求する際、要求ヘッダの Accept に application/xml が含まれると応答は JSON ではなく XML になります。
知ってました? 実は自分は知らなかったです。(汗) ちなみに、MVC の Json メソッド、および Core 3.1 Web API と MVC の Json メソッドは、要求ヘッダの Accept に application/xml が含まれていても JSON が返ってきます。
Web API の応答をチェックするには Postman などのツールを使うのが一般的なようです。でも、GET 要求ならブラウザのアドレスバーに直接 URL を入力して応答を見ることでも十分だったので自分は IE11 を使ってそうしてました。それで期待した通り JSON 文字列が返ってきてました。
ところが、Chrome, Edge, Firefox では応答が JSON ではなく XML になってしまいます。理由は要求ヘッダの Accept に application/xml が含まれるからのようです。ハマったのは上の画像のようなサーバーエラーとなってしまったことです(HTTP 500 応答が返ってきます。上の画像は形式は XML ですが中身はエラーメッセージです)。
エラーメッセージ "The 'ObjectContent`1' type failed to serialize the response body for content type 'application/xml; charset=utf-8'." によるとシリアライズに失敗したということです。
IE11 や jQuery ajax を使った検証ではシリアライズには問題はないことは確認しており、ブラウザに Chrome などを使ったからと言ってそれがシリアライズの部分に影響があるとは考えられなかったです。何故なのでしょう?
循環参照の問題でした。
上の画像の InnerException のエラーメッセージにある Blog_E36679EB... D5AD0 という文字列が、先の記事「JSON シリアライズの際の循環参照エラー」にもあったのを思い出して気が付きました。
.NET Framework 版の ASP.NET Web API の JSON シリアライザは Newtonsoft の Json.NET のもので、JsonIgnoreAttribute クラスという属性が利用できます。なので、問題のプロパティに [JsonIgnore] を付与してシリアライズの際の循環参照エラーは回避していました。
でも [JsonIgnore] が有効なのは JSON にシリアライズするときのみで、XML にシリアライズするときは循環参照の問題は回避できません。
Chrome, Edge などを使った時は、ASP.NET Web API は要求ヘッダの Accept に application/xml が含まれるのを見て、XML にシリアライズしようとして循環参照の問題に陥ったということのようです。