35

MVC 4 Web API フレームワークを使用して取り組んでいる Web API があります。例外がある場合は、現在新しい HttpResponseException をスローしています。すなわち:

if (!Int32.TryParse(id, out userId))
    throw new HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.BadRequest, "Invalid id")); 

これは、単純なオブジェクトをクライアントに返します。{"message":"Invalid id"}

より詳細なオブジェクトを返すことで、例外に対するこの応答をさらに制御したいと考えています。何かのようなもの

{
 "status":-1,
 "substatus":3,
 "message":"Could not find user"
 }

どうすればこれを行うことができますか?エラー オブジェクトをシリアル化し、応答メッセージに設定する最良の方法はありますか?

私も少し調べて、ModelStateDictionaryこのちょっとした「ハック」を思いつきましたが、まだきれいな出力ではありません:

var msd = new ModelStateDictionary();
msd.AddModelError("status", "-1");
msd.AddModelError("substatus", "3");
msd.AddModelError("message", "invalid stuff");
throw new HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.BadRequest, msd));

編集
はカスタムのように見えHttpErrorます。これは、私のビジネスレイヤーから拡張可能にするために、トリックを行うようです...

var error = new HttpError("invalid stuff") {{"status", -1}, {"substatus", 3}};
throw new HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.BadRequest, error));
4

3 に答える 3

46

これらの答えは、必要以上に複雑です。

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        config.Filters.Add(new HandleApiExceptionAttribute());
        // ...
    }
}

public class HandleApiExceptionAttribute : ExceptionFilterAttribute
{
    public override void OnException(HttpActionExecutedContext context)
    {
        var request = context.ActionContext.Request;

        var response = new
        {
             //Properties go here...
        };

        context.Response = request.CreateResponse(HttpStatusCode.BadRequest, response);
    }
}

それだけです。また、単体テストも簡単です。

[Test]
public async void OnException_ShouldBuildProperErrorResponse()
{
    var expected = new 
    {
         //Properties go here...
    };

    //Setup
    var target = new HandleApiExceptionAttribute()

    var contextMock = BuildContextMock();

    //Act
    target.OnException(contextMock);

    dynamic actual = await contextMock.Response.Content.ReadAsAsync<ExpandoObject>();

    Assert.AreEqual(expected.Aproperty, actual.Aproperty);
}

private HttpActionExecutedContext BuildContextMock()
{
    var requestMock = new HttpRequestMessage();
    requestMock.Properties.Add(HttpPropertyKeys.HttpConfigurationKey, new HttpConfiguration());

    return new HttpActionExecutedContext()
    {
        ActionContext = new HttpActionContext
        {
            ControllerContext = new HttpControllerContext
            {
                Request = requestMock
            }

        },
        Exception = new Exception()
    };
}
于 2014-02-27T22:04:31.927 に答える
2

次の記事をご覧ください。Web API の例外とエラー メッセージ (Web API 、HttpError、および例外の動作) を制御するのに役立ちます。

于 2013-06-06T03:44:36.083 に答える