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;
        }
    }

  

 

posted @ 2013-09-12 17:45  のんきネコ  阅读(909)  评论(0编辑  收藏  举报