• 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());
    });
      想要更快更方便的了解相关知识,可以关注微信公众号 
     

     

  • 相关阅读:
    hive默认配置 .hiverc
    hive 行列转换
    hive 全表全字段对比
    shell 获取hive表结构
    粘包现象与解决方案
    win 关闭正在使用的端口
    pycharm格式报错: Remove redundant parentheses
    博客系统作业
    django中间件
    django的用户认证组件
  • 原文地址:https://www.cnblogs.com/axzxs2001/p/15857401.html
Copyright © 2020-2023  润新知