Web Api 过滤器之 ExceptionFilter 异常过滤器

一.服务器出现异常,会统一向客户端返回 500 的错误.

    [RoutePrefix("api/test")]
    public class TestController : ApiController
    {
        public IHttpActionResult Get()
        {
            throw new Exception("出错了!");
        }
    }

 

二.全局过滤器

1.在 App_Start 里面新建一个全局过滤器

 public class MyExceptionFilterAttribute : ExceptionFilterAttribute
    {
        public override void OnException(HttpActionExecutedContext actionExecutedContext)
        {
            //设置返回的HTTP状态码为 Bad Request 即 400
            actionExecutedContext.Response = new System.Net.Http.HttpResponseMessage(System.Net.HttpStatusCode.BadRequest)
            {
                //设置返回的异常内容
                Content = new StringContent(actionExecutedContext.Exception.Message)
            };
            base.OnException(actionExecutedContext);
        }
    }

 

2.在 Global.asax 里面的 Application_Start 方法中添加该全局过滤器

    public class WebApiApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            GlobalConfiguration.Configure(WebApiConfig.Register);

            //添加全局过滤器
            GlobalConfiguration.Configuration.Filters.Add(new MyExceptionFilterAttribute());
        }
    }

测试结果:

 

 

三.Action 过滤器

    [RoutePrefix("api/test")]
    public class TestController : ApiController
    {
        public IHttpActionResult Get()
        {
            throw new Exception("出错了!");
        }

        //将自定义过滤器特性加在action上
        [MyExceptionFilter]
        public IHttpActionResult Post()
        {
            throw new Exception("怎么又出错了!");
        }
    }

同时注释这行代码  //GlobalConfiguration.Configuration.Filters.Add(new MyExceptionFilterAttribute());

测试结果:

 

 

四.Controller 过滤器

原理同 Action 过滤器

五.自定义异常信息

        public void Get()
        {
            throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.Unauthorized)
            {
                Content = new StringContent("哈哈,猪啊"),
                ReasonPhrase = "pig"
            });
        }

 

 

 

六.地址接口异常处理

对于常规的异常,我们通过上面的处理方式,就可以很好进行拦截并处理了,如果接口异常是全局性的,如访问地址簿正确,或者参数多了几个信息,那么调用的接口就不是有效的地址,这样的话,返回的信息就不会被上面的拦截器进行处理了。

如我们给一个无效的API调用路径,在浏览器中获得下面错误结果。

上面结果就无法被我们的常规异常拦截器所捕获,因此不会输出经过封装好的异常信息。

如果需要拦截,我们需要增加自己的消息代理处理,用来捕获这些特殊的异常信息。

复制代码
复制代码
    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
    
            ..............

            config.MessageHandlers.Add(new CustomErrorMessageDelegatingHandler());
复制代码
复制代码

上面红色部分就是我们自己添加的消息代理处理类,用来处理一些特殊的异常信息,如下代码所示。

复制代码
复制代码
    /// <summary>
    /// API自定义错误消息处理委托类。
    /// 用于处理访问不到对应API地址的情况,对错误进行自定义操作。
    /// </summary>
    public class CustomErrorMessageDelegatingHandler : DelegatingHandler
    {
        protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
        {
            return base.SendAsync(request, cancellationToken).ContinueWith<HttpResponseMessage>((responseToCompleteTask) =>
            {
                HttpResponseMessage response = responseToCompleteTask.Result;
                HttpError error = null;
                if (response.TryGetContentValue<HttpError>(out error))
                {
                    //添加自定义错误处理
                    //error.Message = "Your Customized Error Message";
                }

                if (error != null)
                {
                    //获取抛出自定义异常,有拦截器统一解析
                    throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.NotFound)
                    {
                        //封装处理异常信息,返回指定JSON对象
                        Content = new StringContent(new BaseResultJson(error.Message, false, 404).ToJson()),
                        ReasonPhrase = "Exception"
                    });
                }
                else
                {
                    return response;
                }
            });
        }
    }
复制代码
复制代码

经过了上面的处理后,我们进一步测试一下不存在的地址的异常处理结果,可以看到输出的内容是经过了自定义对象的转换了。

常规的调用,如果接口不对应,那么错误也是类似下面的消息

{"errcode":404,"errmsg":"找不到与请求 URI“http://localhost:9001/api/SystemType/Delete?signature=72f8d706c79dc14d70fc3f080d4706748d754021&timestamp=1443194061&nonce=0.650359861855563&appid=website_9A39C2A8&token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiIxIiwiaWF0IjoxNDQzMTk0MDM4LCJqdGkiOiI1YmEyYmE5Ni0yZTA4LTQ1ZTgtYTAwNy01MmY3OTkzYTg2NzEiLCJuYW1lIjoiYWRtaW4iLCJjaGFubmVsIjoiMCIsInNoYXJlZGtleSI6IjEyMzRhYmNkIn0.RRXQmmSCJzDK5Or6rmBL5wjd-YIJoEQFc0pOzqhR6IU”匹配的 HTTP 资源。","success":false}

有了这些信息,我们就可以统一我们的调用规则,并进行异常记录和显示了,非常方便。

 

补充: 

 public override void OnException(HttpActionExecutedContext actionExecutedContext)
        {
            //设置返回的HTTP状态码为 Bad Request 即 400
            actionExecutedContext.Response = new System.Net.Http.HttpResponseMessage(System.Net.HttpStatusCode.BadRequest)
            {
                //设置返回的异常内容
                Content = new StringContent(actionExecutedContext.Exception.Message),
                ReasonPhrase = "hello world"
            };
            base.OnException(actionExecutedContext);
        }

 

注意这个  hello world

posted @ 2018-01-29 18:18  热敷哥  阅读(1104)  评论(0)    收藏  举报