asp.net core web api之异常
官方建议用app.UseExceptionHandler("/error")来集中处理异常,本例是一个具体的应用。
比如项目中有一个ViewModel,要求Name最大长度为5
/// <summary>/// 用户模型/// </summary>public class UserModel{/// <summary>/// ID/// </summary>public int ID { get; set; }/// <summary>///名称/// </summary> [MaxLength(5, ErrorMessage = "长度不能超过5")]public string Name { get; set; }}
在TestController中有两个Action,都有异常的机率,Get方法中,一个异常是系统内置的0被整除,另一个是我们自定义的业务层级异常(.NET架构小技巧(8)中有涉及);AddUser是有Model验证有可能Name超过5个字符后报异常。Error方法一个错误处理Action,根据上下文的异常来分流系统内置异常,还是自定业务异常。
/// <summary>/// get接口/// </summary>/// <returns></returns>[HttpGet]public IActionResult Get(){var ran = new Random();switch (ran.Next(1, 4)){case 1:int i = 0;var j = 10 / i;return Ok();case 2:throw new RegisteredException("这是一个错误");default:return Ok();}}/// <summary>/// 添加用户接口/// </summary>/// <param name="user"></param>/// <returns></returns>[HttpPost("/adduser")]public IActionResult AddUser([FromBody] UserModel user){return Ok(user);}/// <summary>/// 错误处理页/// </summary> /// <returns></returns>[HttpGet("/error")]public IActionResult Error(){var context = HttpContext.Features.Get<IExceptionHandlerFeature>();//如果是业务自定义异常,进行特殊处理if (context.Error is DaMeiException){return Problem(detail: context.Error.StackTrace, title: $"{context.Error.Message}", type: "HIS");}else{return Problem(detail: context.Error.StackTrace, title: context.Error.Message);}}
层级异常类
using System;
namespace WebApiError
{/// <summary>/// 产品异常/// </summary>public class DaMeiException : ApplicationException{/// <summary>/// /// </summary>/// <param name="message"></param>public DaMeiException(string message) : base(message){}}/// <summary>/// His项目异常/// </summary>public class HisException : DaMeiException{/// <summary>/// /// </summary>/// <param name="message"></param>public HisException(string message) : base(message){}}/// <summary>/// Lis项目异常/// </summary>public class LisException : DaMeiException{/// <summary>/// /// </summary>/// <param name="message"></param>public LisException(string message) : base(message){}}/// <summary>/// 模块异常/// </summary>public class RegisteredException : HisException{/// <summary>/// /// </summary>/// <param name="message"></param>public RegisteredException(string message) : base(message){}}
}
Error的Action之所有调用到,是因为Configure中添加如下代码,把所有异常交给"/error"来处理。
app.UseExceptionHandler("/error");
添加DaMeiProblemDetailsFactory来兼容各类异常,自定义异常和Model验证异常
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Infrastructure;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using System.Collections.Generic;namespace WebApiError
{/// <summary>/// /// </summary>public class DaMeiProblemDetailsFactory : ProblemDetailsFactory{/// <summary>/// 处理业务错误/// </summary>/// <param name="httpContext"></param>/// <param name="statusCode"></param>/// <param name="title"></param>/// <param name="type"></param>/// <param name="detail"></param>/// <param name="instance"></param>/// <returns></returns>public override ProblemDetails CreateProblemDetails(HttpContext httpContext, int? statusCode = null, string title = null, string type = null, string detail = null, string instance = null){var problem = new ProblemDetails(){Title = string.IsNullOrEmpty(type) ? title : $"业务异常错误:{title}",Detail = detail,Status = statusCode,Instance = instance,Type = type};return problem;}/// <summary>/// 处理model验证错误/// </summary>/// <param name="httpContext"></param>/// <param name="modelStateDictionary"></param>/// <param name="statusCode"></param>/// <param name="title"></param>/// <param name="type"></param>/// <param name="detail"></param>/// <param name="instance"></param>/// <returns></returns>public override ValidationProblemDetails CreateValidationProblemDetails(HttpContext httpContext, ModelStateDictionary modelStateDictionary, int? statusCode = null, string title = null, string type = null, string detail = null, string instance = null){var problem = new ValidationProblemDetails(){Title = "Model验证错误",Detail = detail,Status = statusCode,Instance = instance,Type = type};foreach (var a in modelStateDictionary){var errorList = new List<string>();foreach (var error in a.Value.Errors){errorList.Add(error.ErrorMessage);}problem.Errors.Add(new KeyValuePair<string, string[]>(a.Key, errorList.ToArray()));}return problem;}}
}
在ConfigureServices中需要注入DaMeiProblemDetailsFactory
services.AddTransient<ProblemDetailsFactory, DaMeiProblemDetailsFactory>();
其实还可以用Action过滤器来统一管理异常
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;namespace WebApiError
{/// <summary>/// 自定义过滤器处理异常/// </summary>public class DaMeiExceptionFilter : IActionFilter, IOrderedFilter{/// <summary>/// /// </summary>public int Order { get; } = int.MaxValue - 10;/// <summary>/// /// </summary>/// <param name="context"></param>public void OnActionExecuting(ActionExecutingContext context) { }/// <summary>/// /// </summary>/// <param name="context"></param>public void OnActionExecuted(ActionExecutedContext context){if (context?.Exception != null){context.Result = new ObjectResult(context.Exception.Message){StatusCode = 500};context.ExceptionHandled = true;} }}
}
另外一种方式是通过Action过滤器来处理
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;namespace WebApiError
{/// <summary>/// 自定义过滤器处理异常/// </summary>public class DaMeiExceptionFilter : IActionFilter, IOrderedFilter{/// <summary>/// /// </summary>public int Order { get; } = int.MaxValue - 10;/// <summary>/// /// </summary>/// <param name="context"></param>public void OnActionExecuting(ActionExecutingContext context){}/// <summary>/// /// </summary>/// <param name="context"></param>public void OnActionExecuted(ActionExecutedContext context){if (context?.Exception != null){if (context.Exception is DaMeiException){context.Result = new ObjectResult(context.Exception.Message){Value = $"业务异常:{ context.Exception.Message}",StatusCode = 500};}else{context.Result = new ObjectResult(context.Exception.Message){Value = context.Exception.Message,StatusCode = 500};}context.ExceptionHandled = true;}}}
}
添加全局过滤器
services.AddControllers(options =>
{options.Filters.Add(new DaMeiExceptionFilter());
});
asp.net core web api之异常相关推荐
- 针对ASP.NET Core Web API的先进架构
\ 本点要点 \\ 与传统的ASP.NET相比,ASP.NET Core的新架构提供了一些好处\\t ASP.NET Core从一开始就包含对依赖注入的支持\\t 单一职责原则简化了实施和设计.\\t ...
- ASP.NET Core Web APi获取原始请求内容
前言 我们讲过ASP.NET Core Web APi路由绑定,本节我们来讲讲如何获取客户端请求过来的内容. ASP.NET Core Web APi捕获Request.Body内容 [HttpPos ...
- 重温.NET下Assembly的加载过程 ASP.NET Core Web API下事件驱动型架构的实现(三):基于RabbitMQ的事件总线...
重温.NET下Assembly的加载过程 最近在工作中牵涉到了.NET下的一个古老的问题:Assembly的加载过程.虽然网上有很多文章介绍这部分内容,很多文章也是很久以前就已经出现了,但阅读之后发现 ...
- 在 ASP.NET Core Web API中使用 Polly 构建弹性容错的微服务
在 ASP.NET Core Web API中使用 Polly 构建弹性容错的微服务 https://procodeguide.com/programming/polly-in-aspnet-core ...
- ASP.NET Core Web API下事件驱动型架构的实现(三):基于RabbitMQ的事件总线
在上文中,我们讨论了事件处理器中对象生命周期的问题,在进入新的讨论之前,首先让我们总结一下,我们已经实现了哪些内容.下面的类图描述了我们已经实现的组件及其之间的关系,貌似系统已经变得越来越复杂了. 其 ...
- ASP.NET Core Web API下事件驱动型架构的实现(二):事件处理器中对象生命周期的管理
在ASP.NET Core Web API下事件驱动型架构的实现(一):一个简单的实现中,我介绍了事件驱动型架构的一种简单的实现,并演示了一个完整的事件派发.订阅和处理的流程.这种实现太简单了,百十行 ...
- 加速ASP.NET Core WEB API应用程序——第2部分
目录 应用程序生产力 异步设计模式 数据规范化与SQL查询效率 NCHAR与NVARCHAR 使用MSSQL服务器的全文引擎 存储过程 优化存储过程 预编译和重用存储过程执行计划 使用Entity F ...
- 加速ASP.NET Core WEB API应用程序。 第三部分
深度重构和完善ASP.NET Core WEB API应用程序代码 (Deep refactoring and refinement of ASP.NET Core WEB API applicati ...
- 如何测试ASP.NET Core Web API
在本文中,我们将研究如何测试你的ASP .NET Core 2.0 Web API解决方案.我们将了解使用单元测试进行内部测试,使用全新的ASP .NET Core的集成测试框架来进行外部测试. 本文 ...
最新文章
- 2018年的上半年目标之一:培养阅读的兴趣和爱好
- 分布式内存数据库--Redis事务
- 基于Boost::beast模块的异步HTTP客户端
- Docker 开发环境的滑坡
- 一篇博客读懂设计模式之---单例模式
- linux怎么不更新内核,Linux升级时不升级内核的方法
- LR逻辑斯蒂回归 — 机器学习面试
- 2021全网最全Activiti7教程01(Activiti7详细介绍-欢迎收藏)
- WSO2 ESB 5.0.0 配置 JMS 传输(ActiveMQ)- 主题消息发布与订阅
- 强迫症 之 Android Studio 格式化 XML
- 自由职业者节税方案来了!
- echarts生成图表超出父容器问题解决
- SKY85728-11低噪声放大器skyworks 高度集成 5 GHz前端模块(FEM)
- linux 修改sh文件生效,Linux-shell脚本基础
- firstChild,lastChild,NextSibling,previousSibling的使用
- 太极框架阴阳之门(设备管理员)激活的种种困难
- 惠普之路——HP公司发展史
- 将多个MP4通过FFmpeg工具合并成一个MP4文件
- 基于centos7打造个人服务器(二):系统初始化
- 取消标签a的默认点击事件