asp.net web api グローバル例外対応

参考

miso-soup3.hateblo.jp

サンプル

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        // Web API の設定およびサービス
        config.Filters.Add(new GlobalExceptionFilterAttribute());
        config.Services.Add(typeof(IExceptionLogger), new GlobalExceptionLogger());
        config.Services.Replace(typeof(IExceptionHandler), new GlobalExceptionHandler());

        // Web API ルート
        config.MapHttpAttributeRoutes();

        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );
    }
}
public class GlobalExceptionFilterAttribute : ExceptionFilterAttribute
{
    public override void OnException(HttpActionExecutedContext actionExecutedContext)
    {
        // TODO アクションのエラー
        base.OnException(actionExecutedContext);
    }
}
public class GlobalExceptionHandler : ExceptionHandler
{
    // TODO 例外が発生した場合、レスポンスの内容を指定できる場合に呼び出されるみたい…(呼び出されないケースは、先述の例外フィルター属性と併用した時しか確認できていません。)
    public override void Handle(ExceptionHandlerContext context)
    {
        Debug.WriteLine(String.Format("★呼び出し {0} - {1}",
            System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName,
            System.Reflection.MethodBase.GetCurrentMethod().Name));

        HttpRequestMessage request = context.Request;
        Exception ex = context.Exception;

        //レスポンスの内容を指定
        //context.Result = new ResponseMessageResult(
        //    request.CreateResponse(HttpStatusCode.InternalServerError,
        //    "MyExceptionHandler で設定したレスポンス"));

        var error = new { status=(int)HttpStatusCode.OK, msg = "errorです" };
        context.Result = new ResponseMessageResult(
               request.CreateResponse(HttpStatusCode.InternalServerError,
               error));
       // [body]
       //{
       // "status": 200,
       // "msg": "errorです"
       // }

    }
}
public class GlobalExceptionLogger : ExceptionLogger
{
    // TODO Web API 内で発生した例外をロギングする場合に使う、例外が発生した場合、必ず呼び出されます。
    public override void Log(ExceptionLoggerContext context)
    {
        Debug.WriteLine(String.Format("★呼び出し {0} - {1}",
            System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName,
            System.Reflection.MethodBase.GetCurrentMethod().Name));

        Exception ex = context.Exception;
        // ログをとります
        Debug.WriteLine("例外発生");
        Debug.WriteLine("Method : " + context.Request.Method);
        Debug.WriteLine("Url : " + context.Request.RequestUri);
        Debug.WriteLine("Exception : " + context.Exception);
    }
}