[Web API] 如何让 Web API 统一回传格式以及例外处理

前言

当我们在开发 Web API 时,一般的情况下每个 API 回传的数据型态或格式都不尽相同,如果你的项目从头到尾都是由你一个人独力完成,那也许还可以说声「阿密陀佛」,但如果是有其他人需要和你共享你的 Api ,而回传的数据格式又不一样,相信是会增加使用者的困扰,也大大增加了程序的复杂度与维护上的难度。所以本篇也纪录一下自己在实作上的经验,一方面留个纪录也希望帮助更多人,废物不多说我们开始吧!

了解架构并实作

原本在找数据时找到这篇 使用Asp.NET MVC打造Web Api (16) – 统一输入/出格式以及异常处理策略,不过发现里面的所用到的方法似乎是 For ASP.Net MVC,而非 Web API (不知道笔者这样认知有没有错误,如果有还麻烦前辈们指教),而本篇的思考模式跟这篇是一样的,只是把它改成 Web API 能用的方法而已。

[]

按照上图所示当使用者请求不同的 API 时,返回页面之前会将数据重新打包后再传回页面给使用者,如此一来用户所看到的数据格式就会是固定的。

1.所以首先我们需要先自定义一个 Model 来当作我们的包装的容器,其类别的定义如下:

{
    public HttpStatusCode Status { get; set; }
    public object Data { get; set; }
    public string ErrorMessage { get; set; }
2.相信写过 ASP.NET MVC 的朋友一定会知道,一般我们会将一些在 Action 中固定的逻辑,利用 Filter 来套用到每一个
Action 上面,例如:Authorize。如果你对 Filter 不是很熟悉可以参考一下网络上前辈所写的文章:[VS2010]
ASP.NET MVC with Action Filters。 所以这边我们也需要使用同样的技巧来重新打包我们回传的数据格式,我们先新增一个
ApiResultAttribute.cs 的档案,且继承
System.Web.Http.Filters.ActionFilterAttribute,并且复写OnActionExecuted 的方法,如下:
{
       {
            base.OnActionExecuted(actionExecutedContext);     
}

3.而 OnActionExecuted 会在 Action 执行之后呼叫,也表示我们将资料送进这个方法里面,接着处理我们主要打包的程序逻辑,程序代码如下:

{
    base.OnActionExecuted(actionExecutedContext);
 
    ApiResultModel result = new ApiResultModel();
 
    result.Status = actionExecutedContext.ActionContext.Response.StatusCode;
    result.Data = actionExecutedContext.ActionContext.Response.Content.ReadAsAsync<object>().Result;
    actionExecutedContext.Response = actionExecutedContext.Request.CreateResponse(result.Status, result);
4.而为了要让所有的 Web API 都能套用我们自定义的 Filter,所以我们需要到 App_Start → WebApiConfig.cs→ Register 来注册全局的 Web API Filter。(注意:若要注册 Web API 的 Filter 需在
WebApiConfig.cs 中注册,而非 FilterConfig.cs 中)
config.Filters.Add(new ApiResultAttribute());

5.重新建置之后我们再重新执行一次原先的 Web API 程序,就会看到回传的格式已经变成我们自定义的格式了:

    "Data": [
            "Account": "taxi",
            "Name": "王大明",
            "AccountStatus": true
        {
            "Mark": "",
            "Telephone": "0922335111",
        },
            "Account": "q121234567",
            "Name": "0000",
            "AccountStatus": true
    ],
例外处理

前面我们已经将讯息打包成我们要的格式了,不过我们还没确切地去处理有关例外的程序代码,一般当程序发生错误产生例外时,我们当然也希望接收端能知道程序发生错误,进而显示该显示的讯息,而不是活生生地看着程序 Crash 或是停顿,这样将带给你的客户不好的体验,而在 ASP.NET MVC 中也有提供专门处理例外的 ExceptionFilterAttribute,所以接着来看看该如何打包我们的例外讯息吧。

1.新增一个 ApiErrorHandleAttribute.cs 并且继承 System.Web.Http.Filters.ExceptionFilterAttribute,接着复写 OnException 当例外发生时执行的方法,程序代码如下:

{
       {
           base.OnException(actionExecutedContext);
}

2.透过 OnException 的方法能让我们捕捉当例外发生时要处理的事情,一般系统我们也会在这边将发生错误的时间、登入的用户以及错误的状况记录下来 (例如:系统事件、存入数据库、写入 .txt 档 … 等),不过这边不是我们讨论的重点,我们先来看看该如何打包我们的例外讯息,程序代码如下:

{
base.OnException(actionExecutedContext);
// 取得发生例外时的错误讯息
var errorMessage = actionExecutedContext.Exception.Message;
{
ErrorMessage = errorMessage
};
actionExecutedContext.Response = actionExecutedContext.Request
.CreateResponse(result.Status, result);

3.而因为程序丢出例外后会先回到 OnActionExcuted 在进到例外的处理,所以我们稍微修改一下原本的 OnActionExcuted 这个方法,让发生例外时就直接跳过不再这边打包我们的讯息,程序代码如下:

{
if (actionExecutedContext.Exception != null)
return;
base.OnActionExecuted(actionExecutedContext);
ApiResultModel result = new ApiResultModel();
result.Status = actionExecutedContext.ActionContext.Response.StatusCode;
result.Data = actionExecutedContext.ActionContext.Response.Content.ReadAsAsync<object>().Result;
actionExecutedContext.Response = actionExecutedContext.Request.CreateResponse(result.Status, result);
3.接着我们一样要将此自定义的 Filter 注册到程序当中,所以一样到 App_Start → WebApiConfig.cs → Register 来注册我们的 Filter:
config.Filters.Add(new ApiErrorHandleAttribute());

4.重新建置后,当我们程序发生例外时也会依照我们的格式回传给使用者:

"Status": 400,
"ErrorMessage": "尝试以零除。"
总结

就这样我们又成功解决了一个简单的案例,不过这边也需要提醒一下读者,一般在处理例外这边是不会直接将例外讯息回传给用户的,因为如果假设你今天丢出的例外有包含了一些比较敏感的信息,例如:数据库名称或数据表名称…等等,这样一来你的程序就间接的有了漏洞了,所以如果真的要用此程序代码记得后面例外捕捉那边还要在包装一下。

原文地址:http://blog.csdn.net/for12/article/details/49685567

转载于:https://www.cnblogs.com/jimcsharp/p/6085738.html

[Web API] 如何让 Web API 统一回传格式以及例外处理[转]相关推荐

  1. JAX-RS(Java API for RESTful Web Services)常用注解

    为什么80%的码农都做不了架构师?>>>    概述 JAX-RS(Java API for RESTful Web Services)是Java 提供用于开发RESTful Web ...

  2. 【ASP.NET Web API2】初识Web API

    Web Api 是什么? MSDN:ASP.NET Web API 是一种框架,用于轻松构建可以访问多种客户端(包括浏览器和移动设备)的 HTTP 服务 百度百科:Web API是网络应用程序接口. ...

  3. 如何用R和API免费获取Web数据?

    API是获得Web数据的重要途径之一.想不想了解如何用R调用API,提取和整理你需要的免费Web数据呢?本文一步步为你详尽展示操作流程. 权衡 俗话说"巧妇难为无米之炊".即便你已 ...

  4. 架构师之路 — API 经济 — Web、HTTP Server、API Service、Application

    目录 文章目录 目录 Web HTTP Server API Service Application Web Web(World Wide Web,全球广域网),也称:万维网,它是一种基于 HTML( ...

  5. jboss7 Java API for RESTful Web Services (JAX-RS) 官方文档

    原文:https://docs.jboss.org/author/display/AS7/Java+API+for+RESTful+Web+Services+(JAX-RS) Content Tuto ...

  6. 1.1.2 以Web Host方式寄宿Web API

       采用Web Host方式寄宿Web API的宿主程序WebHost是一个空的ASP.NET应用,除了让它引用定义ContactsController项目的WebApi 我们还需要引用几个必须的程 ...

  7. api怎么写_使用Node.js原生API写一个web服务器

    Node.js是JavaScript基础上发展起来的语言,所以前端开发者应该天生就会一点.一般我们会用它来做CLI工具或者Web服务器,做Web服务器也有很多成熟的框架,比如Express和Koa.但 ...

  8. java官方 jax rs_jboss7 Java API for RESTful Web Services (JAX-RS) 官方文档

    原文:https://docs.jboss.org/author/display/AS7/Java+API+for+RESTful+Web+Services+(JAX-RS) Content Tuto ...

  9. larvel 中的api.php_laravel route api.php 与 web.php 的区别

    如果是一个纯粹的网站项目,只需要使用 web.php 里的路由就可以了.ajax 需要使用到的 route 也是定义在 web.php 中. 如果是一个非网页项目,例如微信小程序,Android / ...

最新文章

  1. 70亿美金!英伟达欲竞购这家以色列芯片公司!
  2. linux的pthread.h
  3. stm32 USART_IT_IDLE中断 一帧数据
  4. java中日期类型与字符串相互转换
  5. pl/sql下DBMS_OUTPUT.PUT_LINE的输出位置
  6. Idea报错,但是项目可以正常启动运行
  7. Oracle数据库自动存储管理(ASM)
  8. java多线程的安全_java-多线程的安全问题
  9. 入门微信小程序[第六篇]微信小程序 -- 大樱桃的安排
  10. [蓝桥杯]试题 基础练习 龟兔赛跑预测
  11. 【RobotStudio学习笔记】(七)工件坐标
  12. Taro webview中的h5页面如何使用原生小程序API
  13. shapley和树的shap
  14. office2010卸载不掉解决办法
  15. IDEA配置JAVA11
  16. 基于centos7制作安装好环境的iso镜像文件
  17. Kruise Rollout v0.2.0 版本发布:支持 Gateway API、StatefulSet 分批发布等能力
  18. 目标检测综述(二:古典方法对比现代方式以及目标检测算法相关概述)
  19. □ 影片名:《樱桃小丸子》(36004) 在线播放
  20. agios插件之监控AEP主机InBound和Awaiting数量

热门文章

  1. 小米4公布会视频地址
  2. 【2016.12.04】JavaScript笔记
  3. 让CPU占用率听你指挥
  4. Maven 的 settings.xml 配置中的mirror节点
  5. 工业计算机断层扫描原理,工业计算机断层扫描(CT).doc
  6. linux 自定义目录,linux – cron命令的自定义目录
  7. leetcode算法题--全排列
  8. idea 快速搭建spring boot 多模块项目(底部附源码)
  9. 搭建“双11”大型网站架构必须掌握的 5 个核心知识
  10. 源码阅读之Java栈的实现