WebApiのエラーメッセージをどうカスタマイズです?
本来是发布在客户的Wiki上,所以就用日语写。
------------------------------------------------------------------------
Web Pageの場合、Web.configで
<customErrors mode="On" defaultRedirect="~/Error/HttpError"> <error statusCode="404" redirect="~/Error/NotFound"/> <error statusCode="503" redirect="~/Error/Maintenance"/> </customErrors>
を配置すれば、404或いは503エラーの場合、カスタマイズのエラーページに遷移されます。
WebApiの場合はどうする?
特にWeb PageとWebApiのRouteが分かれている場合、Apiへのアクセスが間違っても、カスタマイズのエラーページに遷移しません。
技術不足で、Web.configでどう配置すれば分からないですが、ControllerとActionのほうだけで工夫して仕方がないです。
MVCでは、APIをサクセスする時、まずControllerを探してから、Actionを探します。ControllerとActionが合っていると、Actionに入って、該当するロジックを実行します。
こっちの考えでは、APIをサクセスする時、該当するController或いはActionを検出されない場合、カスタマイズのエラーを返します。
まず「HttpControllerSelector」というControllerを検出するものを実装する。
public class MyHttpControllerSelector : DefaultHttpControllerSelector { public MyHttpControllerSelector(HttpConfiguration configuration) : base(configuration) { } public override HttpControllerDescriptor SelectController(HttpRequestMessage request) { HttpControllerDescriptor descriptor = null; try { descriptor = base.SelectController(request); } catch(Exception e) { APIResult<string> apiResult = new APIResult<string>() { StatusCode = StatusCode.UnexpectedError }; var response = new HttpResponseMessage(HttpStatusCode.OK) { Content = new ObjectContent<APIResult<string>>(apiResult, new JsonMediaTypeFormatter()) }; Trace.WriteLine(e.Message); // Controllerが検出されない場合、直接カスタマイズのResponseを返します。 throw new HttpResponseException(response); } return descriptor; } }
以上のやつを実装終われば、「Global.asax.cs」にレジストなくてはなりません。
protected void Application_Start() { GlobalConfiguration.Configuration.Services.Replace(typeof(IHttpControllerSelector), new MyHttpControllerSelector(GlobalConfiguration.Configuration)); }
次はActionの検知処理です。
public class BaseApiController : ApiController { public override Task<HttpResponseMessage> ExecuteAsync(HttpControllerContext controllerContext, System.Threading.CancellationToken cancellationToken) { Task<HttpResponseMessage> result; try { result = base.ExecuteAsync(controllerContext, cancellationToken); } catch(Exception e) { APIResult<string> apiResult = new APIResult<string>() { StatusCode = StatusCode.UnexpectedError }; var response = new HttpResponseMessage(HttpStatusCode.OK) { Content = new ObjectContent<APIResult<string>>(apiResult, new JsonMediaTypeFormatter()) }; var tsc = new TaskCompletionSource<HttpResponseMessage>(); tsc.SetResult(response); Trace.WriteLine(e.Message); return tsc.Task; } return result; } }