[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": "尝试以零除。"
总结
就这样我们又成功解决了一个简单的案例,不过这边也需要提醒一下读者,一般在处理例外这边是不会直接将例外讯息回传给用户的,因为如果假设你今天丢出的例外有包含了一些比较敏感的信息,例如:数据库名称或数据表名称…等等,这样一来你的程序就间接的有了漏洞了,所以如果真的要用此程序代码记得后面例外捕捉那边还要在包装一下。
[Web API] 如何让 Web API 统一回传格式以及例外处理的更多相关文章
- [Web API] 如何让 Web API 统一回传格式以及例外处理[转]
[Web API] 如何让 Web API 统一回传格式以及例外处理 前言 当我们在开发 Web API 时,一般的情况下每个 API 回传的数据型态或格式都不尽相同,如果你的项目从头到尾都是由你一个 ...
- 【ASP.NET Web API2】初识Web API
Web Api 是什么? MSDN:ASP.NET Web API 是一种框架,用于轻松构建可以访问多种客户端(包括浏览器和移动设备)的 HTTP 服务 百度百科:Web API是网络应用程序接口. ...
- Request Entity Too Large for Self Hosted ASP.Net Web API在Selfhost的api后台怎么解决Request Entity Too Large问题
Request Entity Too Large for Self Hosted ASP.Net Web API在Selfhost的api后台怎么解决Request Entity Too Large问 ...
- ASP.NET Web API与Rest web api(一)
HTTP is not just for serving up web pages. It is also a powerful platform for building APIs that exp ...
- ASP.NET Web API与Rest web api(一)
本文档内容大部分来源于:http://www.cnblogs.com/madyina/p/3381256.html HTTP is not just for serving up web pages. ...
- 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 ...
- Web服务器Raspkate的RESTful API
基于轻量型Web服务器Raspkate的RESTful API的实现 在上一篇文章中,我们已经了解了Raspkate这一轻量型Web服务器,今天,我们再一起了解下如何基于Raspkate实现简单的RE ...
- ASP.NET MVC Web API 学习笔记---Web API概述及程序示例
1. Web API简单说明 近来很多大型的平台都公开了Web API.比如百度地图 Web API,做过地图相关的人都熟悉.公开服务这种方式可以使它易于与各种各样的设备和客户端平台集成功能,以及通过 ...
- web API简介(一):API,Ajax和Fetch
概述 今天逛MDN,无意中看到了web API简介,觉得挺有意思的,就认真读了一下. 下面是我在读的时候对感兴趣的东西的总结,供自己开发时参考,相信对其他人也有用. 什么是API API (Appli ...
随机推荐
- java小程序:求完全数
如果一个数等于它的不包括自身的所有因数之和,那么这个数就叫完全数.例如,6的不包括自身的所有因数为1,2,3,而且6=1+2+3,所以6是完全数. 大约2200多年前,欧几里德提出:如果2n-1是质数 ...
- LR_问题_脚本运行时提示没有参数化
问题描述 将loadrunner中的参数删除,并且删除脚本目录下对应的bak,执行脚本,出现下面的错误: “错误: 表“XX\phonenumbser.dat”不存在. [MsgId: ...
- MariaDB10.2.X-新特性2-支持check约束and with as
前几天写了一篇MariaDB10.2支持分析函数,大家印象中MySQL不支持with as ,check约束,那么MariaDB10.2也同样给你惊喜 1.with as MariaDB [test1 ...
- 配置centos 7 mysql
http://www.cnblogs.com/starof/p/4680083.html 一.系统环境 yum update升级以后的系统版本为 [root@yl-web yl]# cat /etc/ ...
- 如何使用 Java 测试 IBM Systems Director 的 REST API
转自: http://www.ibm.com/developerworks/cn/aix/library/au-aix-systemsdirector/section2.html 如何使用 Java ...
- PL/SQL database character set(AL32UTF8) and Client character set(ZHS16GBK) are different 2012-04-11 13:01
启动PL/SQL Developer 报字符编码不一致错误 Database character set (AL32UTF8) and Client character set (ZHS16GBK) ...
- 11月下旬poj其他题
poj1000,poj1003,poj1004,poj1064,poj1218 水题 poj1012:0<k<14——漂亮的打表 poj1651:与能量项链很像的dp poj1159:回文 ...
- 数据库编程与C#编程互译
今天有一段代码,先是用程序实现. 闲来无聊,又用存储过程实现了一次. 程序中实现. /// <summary> /// 根据区域和用户名获取可访问的国家 /// </summary& ...
- linq 之左连接
List<ArticleModel> articleList = articleRepository.GetAllArticle(); List<UsersModel> use ...
- UVa 11997 (优先队列 多路归并) K Smallest Sums
考虑一个简单的问题,两个长度为n的有序数组A和B,从每个数组中各选出一个数相加,共n2中情况,求最小的n个数. 将这n2个数拆成n个有序表: A1+B1≤A1+B2≤... A2+B1≤A2+B2≤. ...