官方建议用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之异常相关推荐

  1. 针对ASP.NET Core Web API的先进架构

    \ 本点要点 \\ 与传统的ASP.NET相比,ASP.NET Core的新架构提供了一些好处\\t ASP.NET Core从一开始就包含对依赖注入的支持\\t 单一职责原则简化了实施和设计.\\t ...

  2. ASP.NET Core Web APi获取原始请求内容

    前言 我们讲过ASP.NET Core Web APi路由绑定,本节我们来讲讲如何获取客户端请求过来的内容. ASP.NET Core Web APi捕获Request.Body内容 [HttpPos ...

  3. 重温.NET下Assembly的加载过程 ASP.NET Core Web API下事件驱动型架构的实现(三):基于RabbitMQ的事件总线...

    重温.NET下Assembly的加载过程 最近在工作中牵涉到了.NET下的一个古老的问题:Assembly的加载过程.虽然网上有很多文章介绍这部分内容,很多文章也是很久以前就已经出现了,但阅读之后发现 ...

  4. 在 ASP.NET Core Web API中使用 Polly 构建弹性容错的微服务

    在 ASP.NET Core Web API中使用 Polly 构建弹性容错的微服务 https://procodeguide.com/programming/polly-in-aspnet-core ...

  5. ASP.NET Core Web API下事件驱动型架构的实现(三):基于RabbitMQ的事件总线

    在上文中,我们讨论了事件处理器中对象生命周期的问题,在进入新的讨论之前,首先让我们总结一下,我们已经实现了哪些内容.下面的类图描述了我们已经实现的组件及其之间的关系,貌似系统已经变得越来越复杂了. 其 ...

  6. ASP.NET Core Web API下事件驱动型架构的实现(二):事件处理器中对象生命周期的管理

    在ASP.NET Core Web API下事件驱动型架构的实现(一):一个简单的实现中,我介绍了事件驱动型架构的一种简单的实现,并演示了一个完整的事件派发.订阅和处理的流程.这种实现太简单了,百十行 ...

  7. 加速ASP.NET Core WEB API应用程序——第2部分

    目录 应用程序生产力 异步设计模式 数据规范化与SQL查询效率 NCHAR与NVARCHAR 使用MSSQL服务器的全文引擎 存储过程 优化存储过程 预编译和重用存储过程执行计划 使用Entity F ...

  8. 加速ASP.NET Core WEB API应用程序。 第三部分

    深度重构和完善ASP.NET Core WEB API应用程序代码 (Deep refactoring and refinement of ASP.NET Core WEB API applicati ...

  9. 如何测试ASP.NET Core Web API

    在本文中,我们将研究如何测试你的ASP .NET Core 2.0 Web API解决方案.我们将了解使用单元测试进行内部测试,使用全新的ASP .NET Core的集成测试框架来进行外部测试. 本文 ...

最新文章

  1. 2018年的上半年目标之一:培养阅读的兴趣和爱好
  2. 分布式内存数据库--Redis事务
  3. 基于Boost::beast模块的异步HTTP客户端
  4. Docker 开发环境的滑坡
  5. 一篇博客读懂设计模式之---单例模式
  6. linux怎么不更新内核,Linux升级时不升级内核的方法
  7. LR逻辑斯蒂回归 — 机器学习面试
  8. 2021全网最全Activiti7教程01(Activiti7详细介绍-欢迎收藏)
  9. WSO2 ESB 5.0.0 配置 JMS 传输(ActiveMQ)- 主题消息发布与订阅
  10. 强迫症 之 Android Studio 格式化 XML
  11. 自由职业者节税方案来了!
  12. echarts生成图表超出父容器问题解决
  13. SKY85728-11低噪声放大器skyworks 高度集成 5 GHz前端模块(FEM)
  14. linux 修改sh文件生效,Linux-shell脚本基础
  15. firstChild,lastChild,NextSibling,previousSibling的使用
  16. 太极框架阴阳之门(设备管理员)激活的种种困难
  17. 惠普之路——HP公司发展史
  18. 将多个MP4通过FFmpeg工具合并成一个MP4文件
  19. 基于centos7打造个人服务器(二):系统初始化
  20. 取消标签a的默认点击事件

热门文章

  1. django自定义用户表
  2. OOD之问题空间到解空间—附FP的建模
  3. SDNU 1217 CD收藏——并查集
  4. MVC学习九:MVC 特性本质
  5. centos安装禅道的步骤
  6. Delphi应用程序在命令行下带参数执行返回命令行提示的问题
  7. cdh中使用hue使用教程_我可以在户外使用Philips Hue灯泡吗?
  8. 如何重新打开Windows防火墙提示?
  9. macos剪切_如何使用macOS的内置“ Kill and Yank”作为替代剪切和粘贴
  10. vue3.0、cli4项目引入element plus