webapi框架搭建-webapi异常处理
webapi框架搭建系列博客
前言
上一篇我们已经完成了项目的日志管理,在项目开发中日志会经常记录程序中的异常,供后续问题排查使用。本篇讲如何在webapi里加入异常处理机制。
目的和原则
1、程序任何地方都不能catch掉异常,如果要catch也请重新throw异常或是将异常记录到日志里。避免异常被“吃掉“,导致无法排查程序的bug。
2、webapi接口的”请求成功“和”请求失败“以一定的标准规范提供给外部
我的规范为:
所有的成功请求返回200(response的status为200),返回的结果以json封装
所有的失败请求返回非200,错误以json返回,错误的内容为Message的值,如{"Message":"这里是异常的内容描述"}
3、如果为已知异常(即我们代码里写的throw异常)可简单的记录到日志,但如果是未知异常(我们不知道是哪里抛出的异常,往往也是程序的bug)则记录到特殊的日志文件里,如上篇的log/error目录下。
参考
微软webapi异常处理:https://docs.microsoft.com/zh-cn/aspnet/web-api/overview/error-handling/
步骤如下
自定义异常类
此异常类即是”已知“异常,约定程序里我们自己抛出的异常都用此类,Message属性记录异常的描述信息
using System;
using System.Runtime.Serialization; namespace webapi.Exceptions
{
public class KnownException : Exception
{
public KnownException():base()
{
} public KnownException(string message) : base(message)
{
} public KnownException(string message, Exception innerException) : base(message, innerException)
{
} protected KnownException(SerializationInfo info, StreamingContext context) : base(info, context)
{
}
}
}
创建webapi异常过滤器
创建WebApiExceptionFilterAttribute类,代码如下
using System.Net;
using System.Net.Http;
using System.Web.Http.Filters;
using log4net; namespace webapi.Exceptions
{
public class WebApiExceptionFilterAttribute : ExceptionFilterAttribute
{
public override void OnException(HttpActionExecutedContext actionExecutedContext)
{
var exception = actionExecutedContext.Exception;//获取产生的异常对象
var exceptionMessage = exception.Message;
var logMessage =
$@"controller.action={actionExecutedContext.ActionContext.ControllerContext.ControllerDescriptor.ControllerName}.{actionExecutedContext.ActionContext.ActionDescriptor.ActionName}:exception="
+ exception.Message;//异常内容
ILog log = LogManager.GetLogger(actionExecutedContext.ActionContext.ControllerContext.Controller.GetType());
if (exception is KnownException)
{
log.Debug(logMessage);
}
else
{
log.Error(logMessage, exception);
}
actionExecutedContext.Response = actionExecutedContext.Request.CreateErrorResponse(HttpStatusCode.BadRequest, exceptionMessage);
} }
}
在webapi里使用异常过滤最简单的方法就是继承自ExceptionFilterAttribute类,并重写OnException方法并写入自己的异常处理逻辑
将异常过滤器加到webapi里
修改之前的WebApiConfig.OwinWebApiConfiguration方法,代码如下
/// <summary>
/// 返回webapi的httpconfiguration配置
/// 用于webapi应用于owin技术时使用
/// </summary>
/// <returns></returns>
public static HttpConfiguration OwinWebApiConfiguration(HttpConfiguration config)
{
config.MapHttpAttributeRoutes();//开启属性路由
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
config.Filters.Add(new WebApiExceptionFilterAttribute());
return config;
}
增加的只是config.Filters.Add(new WebApiExceptionFilterAttribute());这一句
测试结果
创建用于测试的控制器,写两个接口分别模拟程序bug抛出的未知异常和自己抛出的已知异常
using System;
using System.Web.Http;
using webapi.Exceptions; namespace webapi.example
{
[RoutePrefix("api/exceptionTest")]
public class ExceptionTestController : ApiController
{
/// <summary>
/// 模拟程序bug抛出的异常
/// </summary>
/// <returns></returns>
[Route("unknown"),HttpGet]
public IHttpActionResult UnKnow()
{
throw new Exception("未知的异常");
}
/// <summary>
/// 模拟主动抛出的业务异常
/// </summary>
/// <returns></returns>
[Route("known"), HttpGet]
public IHttpActionResult Know()
{
throw new KnownException("已知的异常");
}
}
}
返问两个接口会得到内容为{"Message":"xxx"},status为400的respose,和我们的约定规则一样。
webapi框架搭建-webapi异常处理的更多相关文章
- webapi框架搭建系列博客
webapi框架搭建系列博客 webapi框架搭建-创建项目(一) webapi框架搭建-创建项目(二)-以iis为部署环境的配置 webapi框架搭建-创建项目(三)-webapi owin web ...
- webapi框架搭建-依赖注入之autofac
前言 c#的依赖注入框架有unity.autofac,两个博主都用过,感觉unity比较简单而autofac的功能相对更丰富(自然也更复杂一点),本篇将基于前几篇已经创建好的webapi项目,引入au ...
- webapi框架搭建-创建项目(三)-webapi owin
上一篇:创建项目(二) 在上一篇里,我们已经创建好了webapi应用,并已经部署到iis里,本篇讲如何用owin自宿主或是iis宿主来部署webapi应用. owin介绍 传统的asp.net网站只能 ...
- webapi框架搭建-创建项目(二)-以iis为部署环境的配置
上篇:webapi快速框架搭建-创建项目(一) 在"创建项目(一)"这一篇里已经创建了一个空的项目,但项目上什么都没有,本篇描述如何将webapi配置成部署在iis上. 步骤 用n ...
- webapi框架搭建-日志管理log4net
前言 本篇讲怎么在前几篇已经创建好的项目里加上日志处理机制,我们采用Log4net技术.跟多的log4net技术的细节请查阅log4net的官网. log4net官网:http://logging.a ...
- webapi框架搭建-安全机制(四)-可配置的基于角色的权限控制
webapi框架搭建系列博客 在上一篇的webapi框架搭建-安全机制(三)-简单的基于角色的权限控制,某个角色拥有哪些接口的权限是用硬编码的方式写在接口上的,如RBAuthorize(Roles = ...
- webapi框架搭建-安全机制(三)-简单的基于角色的权限控制
webapi框架搭建系列博客 上一篇已经完成了“身份验证”,如果只是想简单的实现基于角色的权限管理,我们基本上不用写代码,微软已经提供了authorize特性,直接用就行. Authorize特性的使 ...
- webapi框架搭建-安全机制(二)-身份验证
webapi框架搭建系列博客 身份验证(authentication)的责任是识别出http请求者的身份,除此之外尽量不要管其它的事.webapi的authentication我用authentica ...
- webapi框架搭建-安全机制(一)
本系列博客链接:webapi框架搭建系列博客 前言 webapi接口是开放给外部使用的,包括接口的地址,传参的规范,还有返回结果的说明.正因为接口的开放性,使得接口的安全很重要.试想一下,用抓包工具( ...
随机推荐
- [buaa-SE-2017]个人项目
个人项目 Part1:github https://github.com/Aria-K-Alethia/Sudoku Part2:解题思路描述 关于数独的解法 我选择的是暴力搜索算法. (1)关于 - ...
- Android提供的layout文件存放位置
在编程的过程中,会用到android.R.layout下的一些常量.与这些常量对应的,Android提供了对应点的layout布局文件. android.jar中有对应的xml文件,但是打开的时候通常 ...
- 解决Ubuntu中vi命令的编辑模式下不能正常使用方向键和退格键的问题
在Ubuntu中,进入vi命令的编辑模式,发现按方向键不能移动光标,而是会输出ABCD,以及退格键也不能正常删除字符.这是由于Ubuntu预装的是vim-tiny,而我们需要使用vim-full,解决 ...
- python模块_hashlib详解
hashlib 摘要算法简介 Python的hashlib提供了常见的摘要算法,如MD5,SHA1等等. 什么是摘要算法呢?摘要算法又称哈希算法.散列算法.它通过一个函数,把任意长度的数据转换为一个长 ...
- [Java] Thread的start()和run()函数区别
1.start()方法来启动线程,真正实现了多线程运行,这时无需等待run方法体代码执行完毕而直接继续执行下面的代码: 通过调用Thread类的start()方法来启动一个线程,这时此线程是处于就绪状 ...
- python之zip函数和sorted函数
# zip()函数和sorted()函数 # zip()函数:将两个序列合并,返回zip对象,可强制转换为列表或字典 # sorted()函数:对序列进行排序,返回一个排序后的新列表,原数据不改变 # ...
- day11 匿名函数
格式 lambda 形参 :逻辑运算方式 lambda x:x+1 普通的方式计算 卧槽.这么长! def calc(x): return x+1 res = calc(10) print(res) ...
- [luogu4265][USACO18FEB]Snow Boots silver
题目大意 求出最少需要丢去多少双靴子才能到达终点. 解法 解法一: 看到数据的范围,非常清楚\(O(n^3)\)能过掉所有的数据,那么我们就果断暴力. 解法二: 比较容易会想到用DP做,我一开始定义\ ...
- 打开SharePoint 2013 web application显示iis 欢迎页面
当我打开SP web application时,页面显示如下: 查看event log,发现有一些8315-8317之类的error,发现把request management service停掉后, ...
- /dev/null 2>&1 什么意思
在Unix中,标准输入设备 stdin是0, stdout 是1, stderr是 2. /dev/null 2>&1这样的写法意思是将标准输出和错误输出全部重定向到/dev/nu ...