zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    HDOJ 4259 Double Dealing
    第三课 MongoDB 数据更新
    百度语音识别API初探
    几种常见排序算法的java实现
    HDU 1051 Wooden Sticks 贪心题解
    离线安装Cloudera Manager5.3.4与CDH5.3.4
    Unix哲学
    如何在管理层变动中存活下来
    SWTError: No more handles [gtk_init_check() failed] running platform tests (on Linux)
    "xxadmin" user: No protocol specified 错误
  • 原文地址:https://www.cnblogs.com/refuge/p/8378767.html
Copyright © 2011-2022 走看看