[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. 李洪强iOS开发之OC语言类的深入和分类

    OC语言类的深入和分类 一.分类 (一)分类的基本知识  概念:Category  分类是OC特有的语言,依赖于类. 分类的作用:在不改变原来的类内容的基础上,为类增加一些方法. 添加一个分类: 文件 ...

  2. 李洪强漫谈iOS开发[C语言-009] - C语言关键字

    // //  main.m //  04 - C语言关键字 // //  Created by vic fan on 16/7/12. //  Copyright © 2016年 李洪强. All r ...

  3. 欧拉工程第64题:Odd period square roots

    题目链接 找循环位数是奇数的数有多少个 这个自己很难写出来,完全不能暴力 维基百科链接 维基百科上面说的很好,上面的算法实现就好了. 就是上面的 Java程序: package project61; ...

  4. 为什么重写equals方法还要重写hashcode方法?

    我们都知道Java语言是完全面向对象的,在java中,所有的对象都是继承于Object类.Ojbect类中有两个方法equals.hashCode,这两个方法都是用来比较两个对象是否相等的. 在未重写 ...

  5. Android:布局单位换算

    一.px 像素,是屏幕上显示数据的最基本的点. 二.dpi dpi(Dots Per Inch):每英寸点数,也可称为像素密度,即屏幕对角线像素值÷英寸值 比如480x800分辨率4.0英寸的手机计算 ...

  6. Android:界面设计工具DroidDraw

    DroidDraw是款强大的安卓界面设计软件,基于Java Swing开发,可以通过它拖动控件.设置层属性.设置颜色等步骤轻松地生成复杂的安卓XML布局文件. >>>>> ...

  7. openfire开发

    openfire github地址:https://github.com/igniterealtime/Openfire 1.下载源代码:http://www.igniterealtime.org/d ...

  8. Android studio在真机上进行调试

    1.在Android Studio中,把app的默认启动目标改为USB device,点击[app]→[app configuration],在[Target Device]选择[USB device ...

  9. Web内容管理系统 Magnolia 启程-挖掘优良的架构(3)

    Author and Public instances 第一个关键观念:instance-实例.每一个项目都必须至少有一个Author实例和至少一个Public实例.下面将告诉你为什么: 基本概念:J ...

  10. hdu 4864 Task (贪心 技巧)

    题目链接 一道很有技巧的贪心题目. 题意:有n个机器,m个任务.每个机器至多能完成一个任务.对于每个机器,有一个最大运行时间xi和等级yi, 对于每个任务,也有一个运行时间xj和等级yj.只有当xi& ...