0

ASP.NET WebAPI のコントローラーの PUT アクション メソッド内で例外をスローする動作が、他のアクションや動詞の種類と異なる理由を知っている人はいますか?

基本的に、私は以下のコードを持っています (私は通常、例外フィルターをグローバルに登録していますが、それが原因ではないことを確認するためにそれを無効にしました)。

public class JourneysController : ApiController
{
    private IJourneyRepository repository = null;

    public JourneysController(IJourneyRepository repository)
    {
        this.repository = repository;
    }

    public async Task<Journey> GetById(string id)
    {
        throw new BusinessException("test1");

        var item = await repository.Get(id);
        if (item == null) throw new HttpResponseException(HttpStatusCode.NotFound);
        return item;
    }

    public async Task<HttpResponseMessage> Post(HttpRequestMessage request, [FromBody]Journey value)
    {
        throw new BusinessException("test2");

        value = await repository.Add(value);

        var response = request.CreateResponse<Journey>(HttpStatusCode.Created, value);

        string uri = Url.Link("DefaultApi", new { id = value.Id });
        response.Headers.Location = new Uri(uri);
        return response;
    }

    public async void Put(string id, [FromBody]Journey value)
    {
        throw new BusinessException("test3");

        value.Id = id;
        if (!await repository.Update(value)) throw new HttpResponseException(HttpStatusCode.NotFound);
    }

    public HttpResponseMessage Delete(string id)
    {
        throw new BusinessException("test4");

        repository.Remove(id);
        return new HttpResponseMessage(HttpStatusCode.NoContent);
    }
}

(Chrome Advanced REST クライアントを使用して) GET、POST、および DELETE 動詞を実行すると、次のようなペイロードが得られます (クライアントからコピー/貼り付けする簡単な方法はありません)。

500 Internal Server Error 

Date: Tue, 25 Sep 2012 15:37:56 GMT 
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Content-Length: 813 
Pragma: no-cache 

{
    "Message": "An error has occurred.",
    "ExceptionMessage": "test4",
    "ExceptionType": "KieranBenton.LeaveNow.Services.Model.BusinessException",
    "StackTrace": " <snip>"
}

ただし、PUT アクションは、次のような死亡ペイロードの黄色の画面を返します。

<span><H1>Server Error in '/' Application.<hr width=100% size=1 color=silver></H1>

        <h2> <i>test3</i> </h2></span>

        <font face="Arial, Helvetica, Geneva, SunSans-Regular, sans-serif ">

        <b> Description: </b>An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

        <b> Exception Details:    </b>KieranBenton.LeaveNow.Services.Model.BusinessException: test3

なぜこれが起こっているのか、または実際にバグに出くわしたのか、誰にもわかりませんか?

ありがとう。

4

2 に答える 2

3

の 1 つのガイドラインasyncは、避けることasync voidです。

asyncを返す同期メソッドに相当するのは、をvoid返すasyncメソッドTaskです。async voidは、イベント ハンドラーが存在するようにのみ存在しますasync

お気づきのとおり、例外処理が異なります。から発生したすべての例外は、メソッドの開始時に最新だった にasync void直接送信されます。SynchronizationContextこれはイベント ハンドラーでは当然のことですが、他のシナリオでは混乱を招きます。

ASP.NETは、現在の HTTP 要求を表す を確立するSynchronizationContextため、メソッドからの例外はasync void、コントローラーを実行している WebAPI コードに渡されません。WebAPI フレームワークを介して直接 ASP.NET 要求コンテキストに渡されます。

于 2012-09-26T13:32:22.157 に答える
1

そして、私は答えを見つけました:)

これは、私の PUT メソッドが async void とマークされた唯一のメソッドだったためです。これを async Task に変更すると、正常に動作します (パイプラインの残りの部分が、スローされた例外が Task にラップされていることを検出できるため、間違いありません)。

ますます async void は本当に悪い考えのように思えます!

于 2012-09-25T15:55:00.437 に答える