博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Web API--自定义异常结果的处理
阅读量:5010 次
发布时间:2019-06-12

本文共 5949 字,大约阅读时间需要 19 分钟。

1、常规的异常处理

统一的异常处理,把正确的信息返回给调用者很重要,可以让接口开发人员或者用户,了解具体的原因所在,这样可以得到有效的错误处理。

参考微信API的处理,微信API,对于调用都有一个错误信息返回,不会直接裸露未经处理的异常,因此它们都是经过了一定的拦截处理,然后把错误信息包装提供给接口调用方的。如下是微信的一些接口处理错误。

错误时微信会返回错误码等信息,JSON数据包示例如下(该示例为AppID无效错误):{"errcode":40013,"errmsg":"invalid appid"}

我们根据自己的需要,定义了一个统一的错误信息实体类,如下所示。

///     /// 接口返回的错误信息    ///     public class BaseResultJson    {        ///         /// 错误代码        ///         public int errcode { get; set; }        ///         /// 如果不成功,返回的错误信息        ///         public string errmsg { get; set; }        ///         /// 是否成功        ///         public bool success { get; set; }    }

这样我们就可以把拦截到的错误信息,转换为这样一个方便使用的实体类信息了。

拦截Web API的调用异常,一般可以结合Try Catch的方法,以及异常拦截器进行处理,如下是主动抛出的一些异常信息处理。

//如果没有通过,则抛出异常,由异常过滤器统一处理            if (!result.success)            {                throw new MyApiException(result.errmsg, result.errcode);            }

其中MyApiException是自定义的一个异常信息,用来承载自定义错误信息的异常类。

异常拦截器,我们在Web API里面可以通过Attribute这种标签特性进行处理,如下是我在Web API的基类里面定义了一个异常处理器。

///     /// 所有接口基类    ///     [ExceptionHandling]    public class BaseApiController : ApiController

这个特性对象的定义,它的代码如下所示。

///     /// API自定义错误过滤器属性    ///     public class ExceptionHandlingAttribute : ExceptionFilterAttribute    {        ///         /// 统一对调用异常信息进行处理,返回自定义的异常信息        ///         /// HTTP上下文对象        public override void OnException(HttpActionExecutedContext context)        {            //自定义异常的处理            MyApiException ex = context.Exception as MyApiException;            if (ex != null)            {                                throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.InternalServerError)                {                    //封装处理异常信息,返回指定JSON对象                    Content = new StringContent(new BaseResultJson(ex.Message, false, ex.errcode).ToJson()),                    ReasonPhrase = "Exception"                });            }            //记录关键的异常信息            Debug.WriteLine(context.Exception);                        //常规异常的处理            string msg = string.IsNullOrEmpty(context.Exception.Message) ? "接口出现了错误,请重试或者联系管理员" : context.Exception.Message;            throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.InternalServerError)            {                Content = new StringContent(msg),                ReasonPhrase = "Critical Exception"            });        }    }

根据这些代码,我们就可以实现对调用异常的统一封装处理,让它给我们返回统一的对象信息了,如下是其中一个调用异常,转换为自定义异常信息后的结果输出。

{"errcode":404,"errmsg":"请求的资源不支持 http 方法“POST”。","success":false}

这样我们在处理Web API的返回结果的时候,可以先处理它的异常信息,具体的处理代码如下所示。

HttpHelper helper = new HttpHelper();            helper.ContentType = "application/json";            string content = helper.GetHtml(url, postData, true);            VerifyErrorCode(content);            T result = JsonConvert.DeserializeObject
(content); return result;

我们在上面红色部分的代码就是先处理异常定义信息,如果有这些异常,我们可以在界面中进行异常处理显示了。

例如,如果自定义异常存在,我们转换后,把对应的信息显示出来,重新抛出异常即可。

BaseResultJson errorResult = JsonConvert.DeserializeObject
(content); //非成功操作才记录异常,因为有些操作是返回正常的结果({"errcode": 0, "errmsg": "ok"}) if (errorResult != null && !errorResult.success) { string error = string.Format("请求发生错误!错误代码:{0},说明:{1}", (int)errorResult.errcode, errorResult.errmsg); LogTextHelper.Error(errorResult.ToJson()); throw new Exception(error);//抛出错误 }

 

2、地址接口异常处理

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

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

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

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

public static class WebApiConfig    {        public static void Register(HttpConfiguration config)        {                ..............            config.MessageHandlers.Add(new CustomErrorMessageDelegatingHandler());

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

///     /// API自定义错误消息处理委托类。    /// 用于处理访问不到对应API地址的情况,对错误进行自定义操作。    ///     public class CustomErrorMessageDelegatingHandler : DelegatingHandler    {        protected override Task
SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { return base.SendAsync(request, cancellationToken).ContinueWith
((responseToCompleteTask) => { HttpResponseMessage response = responseToCompleteTask.Result; HttpError error = null; if (response.TryGetContentValue
(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}

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

 

http://www.cnblogs.com/wuhuacong/p/4843422.html

转载于:https://www.cnblogs.com/soundcode/p/6228698.html

你可能感兴趣的文章
js 实现论坛评论模块原理
查看>>
MyEclipse Workspace编码与网页/编辑器 中文乱码问题
查看>>
c++函数回顾
查看>>
【深度学习最优化方法】
查看>>
弹出框始终保持居中(包括有滚动条和窗体缩放时)
查看>>
C#访问数据库增删查改代码
查看>>
mysql 8小时超时设置
查看>>
安卓真机ADB shell添加slite3命令
查看>>
php中引用&的真正理解-变量引用、函数引用、对象引用
查看>>
关于<form> autocomplete 属性
查看>>
OutOfMemory
查看>>
LeetCode:组合总数III【216】
查看>>
Thinkphp框架回顾(三)之怎么实现平常的sql操作数据库
查看>>
asp.net利用剪切板导出excel
查看>>
ASP.NET Core文件上传与下载(多种上传方式)
查看>>
编译Console程序时,可以指定Main入口函数
查看>>
虚函数的效率问题
查看>>
POJ 1860 Currency Exchange(SPFA 判断有无“正”环)
查看>>
angular6项目中使用scss
查看>>
书籍阅读目录(给愚钝的自己)
查看>>