[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

[Web API] 如何让 Web API 统一回传格式以及例外处理[转]的更多相关文章

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

    [Web API] 如何让 Web API 统一回传格式以及例外处理 前言 当我们在开发 Web API 时,一般的情况下每个 API 回传的数据型态或格式都不尽相同,如果你的项目从头到尾都是由你一个 ...

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

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

  3. 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问 ...

  4. 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 ...

  5. ASP.NET Web API与Rest web api(一)

    本文档内容大部分来源于:http://www.cnblogs.com/madyina/p/3381256.html HTTP is not just for serving up web pages. ...

  6. 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 ...

  7. Web服务器Raspkate的RESTful API

    基于轻量型Web服务器Raspkate的RESTful API的实现 在上一篇文章中,我们已经了解了Raspkate这一轻量型Web服务器,今天,我们再一起了解下如何基于Raspkate实现简单的RE ...

  8. ASP.NET MVC Web API 学习笔记---Web API概述及程序示例

    1. Web API简单说明 近来很多大型的平台都公开了Web API.比如百度地图 Web API,做过地图相关的人都熟悉.公开服务这种方式可以使它易于与各种各样的设备和客户端平台集成功能,以及通过 ...

  9. web API简介(一):API,Ajax和Fetch

    概述 今天逛MDN,无意中看到了web API简介,觉得挺有意思的,就认真读了一下. 下面是我在读的时候对感兴趣的东西的总结,供自己开发时参考,相信对其他人也有用. 什么是API API (Appli ...

随机推荐

  1. 【tyvj】P1049 最长不下降子序列

    时间: 1000ms / 空间: 131072KiB / Java类名: Main 描述 求最长不下降子序列的长度 输入格式 第一行为n,表示n个数 第二行n个数 输出格式 最长不下降子序列的长度 测 ...

  2. sparse coding稀疏表达入门

    最近在看sparse and redundant representations这本书,进度比较慢,不过力争看过的都懂,不把时间浪费掉.才看完了不到3页吧,书上基本给出了稀疏表达的概念以及传统的求法. ...

  3. 【Linux高频命令专题(16)】less

    概述 less 工具也是对文件或其它输出进行分页显示的工具,应该说是linux正统查看文件内容的工具,功能极其强大.less 的用法比起 more 更加的有弹性.在 more 的时候,我们并没有办法向 ...

  4. HTML5入门十---Canvas画布实现画图(一)

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...

  5. [翻译] - <Entity Framework> - 直接执行数据库命令

    原文:[翻译] - <Entity Framework> - 直接执行数据库命令 纯属学习上的记录, 非专业翻译, 如有错误欢迎指正! 原文地址: http://msdn.microsof ...

  6. FastDFS_v5.05安装配置

    废话不多讲,启动FastDFS文件服务器的命令是 #/usr/bin/fdfs_trackerd /etc/fdfs/tracker.conf #/usr/bin/fdfs_storaged /etc ...

  7. 基于条件随机场(CRF)的命名实体识别

    很久前做过一个命名实体识别的模块,现在有时间,记录一下. 一.要识别的对象 人名.地名.机构名 二.主要方法 1.使用CRF模型进行识别(识别对象都是最基础的序列,所以使用了好评率较高的序列识别算法C ...

  8. 在BSP的.bat文件下設置全局變量方法

    用于多個產品共用一個BSP的時候,在BSP的.bat文件中設置全局變量,去掉不需要加載的驅動和不同點是很好的方法. 一,舉例:BSP中.bat的一段code: set BSP_SMDK2443=1 s ...

  9. php整理(三): 面向对象

    PHP学习(三)----面向对象   首先,还是建立一个好的理解模型: 1.什么是面向对象? 面向对象分为两个部分,那就是:什么是对象和什么是面向? 什么是对象: 对象的出现就是为了用代码更好的绘制我 ...

  10. svn: E180001: Unable to open an ra_local session to URL问题解决方案

    在使用Android Studio的SVN导入项目时,出现了: svn: E180001: Unable to open an ra_local session to URLsvn: E180001: ...