1、常规的异常处理

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

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

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

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

  1. /// <summary>
  2. /// 接口返回的错误信息
  3. /// </summary>
  4. public class BaseResultJson
  5. {
  6. /// <summary>
  7. /// 错误代码
  8. /// </summary>
  9. public int errcode { get; set; }
  10.  
  11. /// <summary>
  12. /// 如果不成功,返回的错误信息
  13. /// </summary>
  14. public string errmsg { get; set; }
  15.  
  16. /// <summary>
  17. /// 是否成功
  18. /// </summary>
  19. public bool success { get; set; }
  20. }

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

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

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

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

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

  1. /// <summary>
  2. /// 所有接口基类
  3. /// </summary>
  4.  
  5. [ExceptionHandling]
  6. public class BaseApiController : ApiController

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

  1. /// <summary>
  2. /// API自定义错误过滤器属性
  3. /// </summary>
  4. public class ExceptionHandlingAttribute : ExceptionFilterAttribute
  5. {
  6. /// <summary>
  7. /// 统一对调用异常信息进行处理,返回自定义的异常信息
  8. /// </summary>
  9. /// <param name="context">HTTP上下文对象</param>
  10. public override void OnException(HttpActionExecutedContext context)
  11. {
  12. //自定义异常的处理
  13. MyApiException ex = context.Exception as MyApiException;
  14. if (ex != null)
  15. {
  16. throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.InternalServerError)
  17. {
  18. //封装处理异常信息,返回指定JSON对象
  19. Content = new StringContent(new BaseResultJson(ex.Message, false, ex.errcode).ToJson()),
  20. ReasonPhrase = "Exception"
  21. });
  22.  
  23. }
  24.  
  25. //记录关键的异常信息
  26. Debug.WriteLine(context.Exception);
  27.  
  28. //常规异常的处理
  29. string msg = string.IsNullOrEmpty(context.Exception.Message) ? "接口出现了错误,请重试或者联系管理员" : context.Exception.Message;
  30. throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.InternalServerError)
  31. {
  32. Content = new StringContent(msg),
  33. ReasonPhrase = "Critical Exception"
  34. });
  35. }
  36. }

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

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

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

  1. HttpHelper helper = new HttpHelper();
  2. helper.ContentType = "application/json";
  3.  
  4. string content = helper.GetHtml(url, postData, true);
  5. VerifyErrorCode(content);
  6.  
  7. T result = JsonConvert.DeserializeObject<T>(content);
  8. return result;

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

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

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

2、地址接口异常处理

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

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

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

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

  1. public static class WebApiConfig
  2. {
  3. public static void Register(HttpConfiguration config)
  4. {
  5.  
  6. ..............
  7.  
  8. config.MessageHandlers.Add(new CustomErrorMessageDelegatingHandler());

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

  1. /// <summary>
  2. /// API自定义错误消息处理委托类。
  3. /// 用于处理访问不到对应API地址的情况,对错误进行自定义操作。
  4. /// </summary>
  5. public class CustomErrorMessageDelegatingHandler : DelegatingHandler
  6. {
  7. protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
  8. {
  9. return base.SendAsync(request, cancellationToken).ContinueWith<HttpResponseMessage>((responseToCompleteTask) =>
  10. {
  11. HttpResponseMessage response = responseToCompleteTask.Result;
  12. HttpError error = null;
  13. if (response.TryGetContentValue<HttpError>(out error))
  14. {
  15. //添加自定义错误处理
  16. //error.Message = "Your Customized Error Message";
  17. }
  18.  
  19. if (error != null)
  20. {
  21. //获取抛出自定义异常,有拦截器统一解析
  22. throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.NotFound)
  23. {
  24. //封装处理异常信息,返回指定JSON对象
  25. Content = new StringContent(new BaseResultJson(error.Message, false, 404).ToJson()),
  26. ReasonPhrase = "Exception"
  27. });
  28. }
  29. else
  30. {
  31. return response;
  32. }
  33. });
  34. }
  35. }

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

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

  1. {"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

Web API--自定义异常结果的处理的更多相关文章

  1. Web API应用架构在Winform混合框架中的应用(2)--自定义异常结果的处理

    在上篇随笔<Web API应用架构在Winform混合框架中的应用(1)>中我介绍了关于如何在Winfrom里面整合WebAPI,作为一个新型数据源的接入方式,从而形成了三种不同的数据提供 ...

  2. Web API项目中使用Area对业务进行分类管理

    在之前开发的很多Web API项目中,为了方便以及快速开发,往往把整个Web API的控制器放在基目录的Controllers目录中,但随着业务越来越复杂,这样Controllers目录中的文件就增加 ...

  3. Web API系列(三)统一异常处理

    前面讲了webapi的安全验证和参数安全,不清楚的朋友,可以看看前面的文章,<Web API系列(二)接口安全和参数校验>,本文主要介绍Web API异常结果的处理.作为内部或者是对外提供 ...

  4. Web APi之异常处理(Exception)以及日志记录(NLog)(十六)

    前言 上一篇文章我们介绍了关于日志记录用的是Log4net,确实也很挺强大,但是别忘了我们.NET有专属于我们的日志框架,那就是NLog,相对于Log4net而言,NLog可以说也是一个很好的记录日志 ...

  5. Web API应用架构在Winform混合框架中的应用(5)--系统级别字典和公司级别字典并存的处理方式

    在我这个系列中,我主要以我正在开发的云会员管理系统为例进行介绍Web API的应用,由于云会员的数据设计是支持多个商家公司,而每个公司又可以包含多个店铺的,因此一些字典型的数据需要考虑这方面的不同.如 ...

  6. Web API应用架构在Winform混合框架中的应用(4)--利用代码生成工具快速开发整套应用

    前面几篇介绍了Web API的基础信息,以及如何基于混合框架的方式在WInform界面里面整合了Web API的接入方式,虽然我们看似调用过程比较复杂,但是基于整个框架的支持和考虑,我们提供了代码生成 ...

  7. Web API应用架构在Winform混合框架中的应用(3)--Winfrom界面调用WebAPI的过程分解

    最近一直在整合WebAPI.Winform界面.手机短信.微信公众号.企业号等功能,希望把它构建成一个大的应用平台,把我所有的产品线完美连接起来,同时也在探索.攻克更多的技术问题,并抽空写写博客,把相 ...

  8. Web API接口设计经验总结

    在Web API接口的开发过程中,我们可能会碰到各种各样的问题,我在前面两篇随笔<Web API应用架构在Winform混合框架中的应用(1)>.<Web API应用架构在Winfo ...

  9. Web API应用架构在Winform混合框架中的应用(1)

    在<Web API应用架构设计分析(1)>和<Web API应用架构设计分析(2)>中对WebAPI的架构进行了一定的剖析,在当今移动优先的口号下,传统平台都纷纷开发了属于自己 ...

  10. ASP.NET Web API 2中的错误处理

    前几天在webapi项目中遇到一个问题:Controller构造函数中抛出异常时全局过滤器捕获不到,于是网搜一把写下这篇博客作为总结. HttpResponseException 通常在WebAPI的 ...

随机推荐

  1. IOS应用内存释放机制

    这是由iOS系统管理决定的,但APP退出在后台后,只有10秒的持续运行时间,然后暂停.但该APP还在内存中,当出现内存警告,也就是别的APP要运行,而此时内存又不足的情况下,系统会回收停在后台APP所 ...

  2. MySQL 5.7:非结构化数据存储的新选择

    本文转载自:http://www.innomysql.net/article/23959.html (只作转载, 不代表本站和博主同意文中观点或证实文中信息) 工作10余年,没有一个版本能像MySQL ...

  3. SharePoint 2013 Designer系列之数据视图筛选

    在SharePoint中,我们经常需要对列表进行简单的筛选,这时,数据视图就有作用了,我们可以定制对于字段的筛选,来进行展示:特别的,筛选不同于搜索,并没有对于附件或者文档的全文检索,如果需要全文检索 ...

  4. IOS开发之支付功能概述

    前言:本随笔将对IOS开发的支付功能进行一个概述. 内容大纲: 一.常见的支付方案简介 二.第三方支付SDK 三.苹果官方支付方案 四.Web支付方案 正文: 一.常见的支付方案简介 在微信支付中 微 ...

  5. postgresql 服务器端编程之hello word

    create or replace function addjifen( iuserid text, iamout INTEGER) returns text AS \[ BEGIN return ' ...

  6. Vs2013 html5开发WP8.1 APP之jquery

    仿安卓原生界面,先使用JQM,最新的JQM使用了JQ1.8.5 然后在WP8以上就会遇到动态创建控件的安全性问题 换成JQ2.X即可,但在WP8.1中一定不要删除了 <script src=&q ...

  7. Java中的阻塞队列

    1. 什么是阻塞队列? 阻塞队列(BlockingQueue)是一个支持两个附加操作的队列.这两个附加的操作是:在队列为空时,获取元素的线程会等待队列变为非空.当队列满时,存储元素的线程会等待队列可用 ...

  8. Linux SendMail发送邮件失败诊断案例(二)

    Linux上Sendmail经常由于一些配置问题,导致邮件发送失败,下面整理.收集了一些邮件发送失败.异常的案例. 案例1:在新服务器上测试sendmail发送邮件时,发现邮件发送不成功,检查/var ...

  9. python2不同版本安装json模块

    1.常用json库主要有json-py和simplejson 1) json-py 包含json和minjson,用法一样 Python (#, Jan , ::) [GCC (Red Hat -)] ...

  10. Elasticsearch配置文件说明

    一.Cluster  setting Cluster indices.ttl.interval  允许设置多久过期的文件会被自动删除.默认值是60秒. indices.cache.filter.siz ...