webdevqa.jp.net

Owinセルフホストの使用時にWeb APIコントローラーからHttpResponseExceptionをスローする

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を生成しているため、戻り値の型を変更することはできません。

12
Kristoffer Ahl

問題はHttpResponseExceptionを投げることにあるとは思いません。投稿したスタックトレースを見ると、MoveNext()の呼び出しに問題があるようです。これは、あなたが持っているyieldステートメントの内部C#表現です。

私は間違っている可能性がありますが、これを確認する最も簡単な方法は、最初のyieldステートメントにブレークポイントを設定し、それがヒットするかどうかを確認することです。私の推測では、これはHttpResponseExceptionをスローしません。また、コードを一時的に変更して常にHttpResponseExceptionをスローし、それがどのように処理されるかを確認します。

私は現在OWINを使用してセルフホストされているプロジェクトに取り組んでおり、HttpResponseExceptionsを問題なくスローできます。

関連する注意事項として、 グローバル例外処理 を調査する必要があります。すべての例外処理を1か所に集中させると非常に便利です。 HttpResponseExceptionは特殊なケースであり、グローバル例外ハンドラーによって処理されないことに注意してください。

4
djikay

Postmanを使用してWeb APIをテストしているときにこれを経験し、リクエストタイプがapplication/jsonではなくプレーンテキストに設定されました。

8
dhysong

私にとっては、apiヘッダーにcontent-typeがありませんでした。 content-typeをapplication/jsonとして追加すると、この問題は解決しました。これで他の人を助けるかもしれません。

2
briefcasejoe

100%確実ではありませんが、アクションがIEnumerable <>を返すため、これが発生した可能性があります

IHttpActionResultに変更してみてください

これを試して

  [ResponseType(typeof(AccountCodeAssignment))]
         public IHttpActionResult AssignAccountCodesToInvoiceById (int id)
        {

         var invoice = _invoiceRepository.Get(id);

                if (invoice == null) {

                return NotFound();
         }



               return Ok(invoice);
            }
1
sylwester

OnException()の例外にブレークポイントを設定し、context.Exception.Responseを表示して、「理由句」を確認できます説明のために。

コードを使用してアクセスすることもできます。

((System.Web.Http.HttpResponseException)context.Exception).Response.ReasonPhrase

私にとっては

サポートされていないメディアタイプ

テキストリクエストはデフォルトでは処理されないため、テキストリクエストを実行すると、他の人がすでに言及したことが起こります。テキストを許可したい場合は、以下を参照してください: プレーンテキストをASP.NET Web APIエンドポイントに投稿する方法

0
Andrew