2014 年 1 月 26 日編集: Microsoftは、最新の WebAPI 2.1 アップデートに「グローバル エラー処理」を追加しました。
わかりました、私はそれを手に入れたと思います。それにはいくつかの部分があります。
最初: エラー用のコントローラーを作成します。HTTP エラー コードに従ってアクションに名前を付けました。
public class ErrorController : ApiController {
[AllowAnonymous]
[ActionName("Get")]
public HttpResponseMessage Get() {
return Request.CreateErrorInfoResponse(HttpStatusCode.InternalServerError, title: "Unknown Error");
}
[AllowAnonymous]
[ActionName("404")]
[HttpGet]
public HttpResponseMessage Status404() {
return Request.CreateErrorInfoResponse(HttpStatusCode.NotFound, description: "No resource matches the URL specified.");
}
[AllowAnonymous]
[ActionName("400")]
[HttpGet]
public HttpResponseMessage Status400() {
return Request.CreateErrorInfoResponse(HttpStatusCode.BadRequest);
}
[AllowAnonymous]
[ActionName("500")]
[HttpGet]
public HttpResponseMessage Status500() {
return Request.CreateErrorInfoResponse(HttpStatusCode.InternalServerError);
}
}
次に、GenericExceptionFilterAttribute
HttpActionExecutedContext.Exception が設定されているかどうか、および応答がまだ空であるかどうかを確認する を作成しました。両方のケースが true の場合、応答が生成されます。
public class GenericExceptionFilterAttribute : ExceptionFilterAttribute {
public GenericExceptionFilterAttribute()
: base() {
DefaultHandler = (context, ex) => context.Request.CreateErrorInfoResponse(System.Net.HttpStatusCode.InternalServerError, "Internal Server Error", "An unepected error occoured on the server.", exception: ex);
}
readonly Dictionary<Type, Func<HttpActionExecutedContext, Exception, HttpResponseMessage>> exceptionHandlers = new Dictionary<Type, Func<HttpActionExecutedContext, Exception, HttpResponseMessage>>();
public Func<HttpActionExecutedContext, Exception, HttpResponseMessage> DefaultHandler { get; set; }
public void AddExceptionHandler<T>(Func<HttpActionExecutedContext, Exception, HttpResponseMessage> handler) where T : Exception {
exceptionHandlers.Add(typeof(T), handler);
}
public override void OnException(HttpActionExecutedContext context) {
if (context.Exception == null) return;
try {
var exType = context.Exception.GetType();
if (exceptionHandlers.ContainsKey(exType))
context.Response = exceptionHandlers[exType](context, context.Exception);
if(context.Response == null && DefaultHandler != null)
context.Response = DefaultHandler(context, context.Exception);
}
catch (Exception ex) {
context.Response = context.Request.CreateErrorInfoResponse(HttpStatusCode.InternalServerError, description: "Error while building the exception response.", exception: ex);
}
}
}
私の場合は、主要な例外の種類ごとにサポートを登録し、それらの例外の種類を特定の HTTP 応答コードにマップできる単一の汎用ハンドラーを使用しました。例外タイプとハンドラーをこのフィルターでグローバルに登録しますglobal.asax.cs
。
// These filters override the default ASP.NET exception handling to create REST-Friendly error responses.
var exceptionFormatter = new GenericExceptionFilterAttribute();
exceptionFormatter.AddExceptionHandler<NotImplementedException>((context, ex) => context.Request.CreateErrorInfoResponse(System.Net.HttpStatusCode.InternalServerError, "Not Implemented", "This method has not yet been implemented. Please try your request again at a later date.", exception: ex));
exceptionFormatter.AddExceptionHandler<ArgumentException>((context, ex) => context.Request.CreateErrorInfoResponse(System.Net.HttpStatusCode.BadRequest, exception: ex));
exceptionFormatter.AddExceptionHandler<ArgumentNullException>((context, ex) => context.Request.CreateErrorInfoResponse(System.Net.HttpStatusCode.BadRequest, exception: ex));
exceptionFormatter.AddExceptionHandler<ArgumentOutOfRangeException>((context, ex) => context.Request.CreateErrorInfoResponse(System.Net.HttpStatusCode.BadRequest, exception: ex));
exceptionFormatter.AddExceptionHandler<FormatException>((context, ex) => context.Request.CreateErrorInfoResponse(System.Net.HttpStatusCode.BadRequest, exception: ex));
exceptionFormatter.AddExceptionHandler<NotSupportedException>((context, ex) => context.Request.CreateErrorInfoResponse(System.Net.HttpStatusCode.BadRequest, "Not Supported", exception: ex));
exceptionFormatter.AddExceptionHandler<InvalidOperationException>((context, ex) => context.Request.CreateErrorInfoResponse(System.Net.HttpStatusCode.BadRequest, "Invalid Operation", exception: ex));
GlobalConfiguration.Filters.Add(exceptionFormatter)
次に、キャッチオール ルートを作成して、すべての未知のリクエストを新しいエラー ハンドラに送信します。
config.Routes.MapHttpRoute(
name: "DefaultCatchall",
routeTemplate: "{*url}",
defaults: new {
controller = "Error",
action = "404"
}
);
そして、すべてをまとめるために、これをに追加して、IIS が ASP.NET を介してすべての要求を処理できるようにしますweb.config
。
<configuration>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true" />
</system.webServer>
</configuration>
オプションで、 のcustomErrors
セクションを使用して、web.config
すべてのエラーを新しいエラー ハンドラにリダイレクトすることもできます。