Owinを使用してホストしているWebApiを構築しています。以前は、コントローラーアクションで404ステータスコードなどを返すためにHttpResponseExceptionを使用しており、正常に動作しています。
ただし、Owin(セルフホスト)での作業を開始したとき、このアプローチで問題が発生し、HttpResponseExceptionがjson/xmlにシリアル化され、ステータスコードが404から500(内部サーバーエラー)に変更されます。これが私たちが持っているコードです:
public class InvoicesController : ApiController
{
private readonly IInvoiceRepository _invoiceRepository;
public InvoicesController(IInvoiceRepository invoiceRepository)
{
_invoiceRepository = invoiceRepository;
}
[HttpGet]
public IEnumerable<AccountCodeAssignment> AssignAccountCodesToInvoiceById(int id)
{
var invoice = _invoiceRepository.Get(id);
if (invoice == null) throw new HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.NotFound, "Invoice not found"));
yield return new AccountCodeAssignment(1, ...);
yield return new AccountCodeAssignment(2, ...);
yield return new AccountCodeAssignment(3, ...);
yield return new AccountCodeAssignment(4, ...);
}
}
これは、500応答コードとともに返される応答です。
{
"Message": "An error has occurred.",
"ExceptionMessage": "Processing of the HTTP request resulted in an exception. Please see the HTTP response returned by the 'Response' property of this exception for details.",
"ExceptionType": "System.Web.Http.HttpResponseException",
"StackTrace": " at AccountCodeAssignmentService.Controllers.InvoicesController.<AssignAccountCodesToInvoiceById>d__0.MoveNext() in c:\\Projects\\AccountCodeAssignmentService\\Source\\AccountCodeAssignmentService\\Controllers\\InvoicesController.cs:line 38\r\n at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeList(JsonWriter writer, IEnumerable values, JsonArrayContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)\r\n at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeValue(JsonWriter writer, Object value, JsonContract valueContract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty)\r\n at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.Serialize(JsonWriter jsonWriter, Object value, Type objectType)\r\n at Newtonsoft.Json.JsonSerializer.SerializeInternal(JsonWriter jsonWriter, Object value, Type objectType)\r\n at System.Net.Http.Formatting.BaseJsonMediaTypeFormatter.WriteToStream(Type type, Object value, Stream writeStream, Encoding effectiveEncoding)\r\n at System.Net.Http.Formatting.JsonMediaTypeFormatter.WriteToStream(Type type, Object value, Stream writeStream, Encoding effectiveEncoding)\r\n at System.Net.Http.Formatting.BaseJsonMediaTypeFormatter.WriteToStream(Type type, Object value, Stream writeStream, HttpContent content)\r\n at System.Net.Http.Formatting.BaseJsonMediaTypeFormatter.WriteToStreamAsync(Type type, Object value, Stream writeStream, HttpContent content, TransportContext transportContext, CancellationToken cancellationToken)\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at System.Web.Http.Owin.HttpMessageHandlerAdapter.<BufferResponseContentAsync>d__13.MoveNext()"
}
Owinセルフホスティングを使用しているときに、何が間違っているのか、HttpResponseExceptionはサポートされていませんか?
編集: WebApiを使用することの大きな利点の1つは、独自の型を操作して返すことができることです。そのため、戻りの型を変更する必要がないようにします。現在、AccountCodeAssignmentを生成しているため、戻り値の型を変更することはできません。
問題はHttpResponseException
を投げることにあるとは思いません。投稿したスタックトレースを見ると、MoveNext()
の呼び出しに問題があるようです。これは、あなたが持っているyield
ステートメントの内部C#表現です。
私は間違っている可能性がありますが、これを確認する最も簡単な方法は、最初のyieldステートメントにブレークポイントを設定し、それがヒットするかどうかを確認することです。私の推測では、これはHttpResponseException
をスローしません。また、コードを一時的に変更して常にHttpResponseException
をスローし、それがどのように処理されるかを確認します。
私は現在OWINを使用してセルフホストされているプロジェクトに取り組んでおり、HttpResponseException
sを問題なくスローできます。
関連する注意事項として、 グローバル例外処理 を調査する必要があります。すべての例外処理を1か所に集中させると非常に便利です。 HttpResponseException
は特殊なケースであり、グローバル例外ハンドラーによって処理されないことに注意してください。
Postmanを使用してWeb APIをテストしているときにこれを経験し、リクエストタイプがapplication/jsonではなくプレーンテキストに設定されました。
私にとっては、apiヘッダーにcontent-typeがありませんでした。 content-typeをapplication/jsonとして追加すると、この問題は解決しました。これで他の人を助けるかもしれません。
100%確実ではありませんが、アクションがIEnumerable <>を返すため、これが発生した可能性があります
IHttpActionResultに変更してみてください
これを試して
[ResponseType(typeof(AccountCodeAssignment))]
public IHttpActionResult AssignAccountCodesToInvoiceById (int id)
{
var invoice = _invoiceRepository.Get(id);
if (invoice == null) {
return NotFound();
}
return Ok(invoice);
}
OnException()
の例外にブレークポイントを設定し、context.Exception.Responseを表示して、「理由句」を確認できます説明のために。
コードを使用してアクセスすることもできます。
((System.Web.Http.HttpResponseException)context.Exception).Response.ReasonPhrase
私にとっては
サポートされていないメディアタイプ
テキストリクエストはデフォルトでは処理されないため、テキストリクエストを実行すると、他の人がすでに言及したことが起こります。テキストを許可したい場合は、以下を参照してください: プレーンテキストをASP.NET Web APIエンドポイントに投稿する方法