• 2.接口输入校验、输出格式、及异常处理——SnailAspNetCoreFramework快速开发框架之后端设计


    输入校验

    • 在控制器上加上[ApiController]特性,让接口自动校验模型,不必再调用ModelState.IsValid
    • 一般的校验,用自带的校验Attribute即可,如Required,StringLength,Range,RegularExpression等
    • 示例如下
        /// <summary>
        /// dto输入校验
        /// </summary>
        /// <remarks>
        /// 可参考:https://docs.microsoft.com/zh-cn/aspnet/core/mvc/models/validation?view=aspnetcore-3.1
        /// </remarks>
        public class DtoValidateSample : IDto, IValidatableObject
        {
            [Required(ErrorMessage ="必填")]
            public string Reqired { get; set; }
            [StringLength(8, ErrorMessage = "长度不能超过8")]
            public string StringLen { get; set; }
            public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
            {
                var errors = new List<ValidationResult>();
                #region 这里写dto的校验逻辑,如果有问题则加入到errors里
                //errors.Add(new ValidationResult("这是错误内容",new List<string> { "这是核验不通过的字段" }));
                #endregion
                return errors;
            }
        }
    

    统一输出格式

    • 格式约定如下
    {
    	"Code":2000,//这是接口的状态,只有2000才为成功,其它为失败,失败的原因为msg
    	"Data":xxx,//这是真实返回的数据
    	"Msg":""//错误信息
    }
    
    • 用ResultFilter实现,在所有的接口返回结果时,统一对结果进行标准格式封闭,GlobalResultFilterAttribute
       /// <summary>
        /// 只有没有进入到ExceptFilter里的才会进入此过滤器
        /// </summary>
        public class GlobalResultFilterAttribute : ResultFilterAttribute
        {
            public override void OnResultExecuting(ResultExecutingContext context)
            {
                if (context.Result is ObjectResult objectResult)//正常返回
                {
                    context.Result = new ObjectResult(ApiResultDto.SuccessResult(objectResult.Value));
                }
                else if (context.Result is EmptyResult emptyResult)
                {
                    context.Result = new ObjectResult(ApiResultDto.SuccessResult(null));
                }
            }
        }
    
    
    • 将GlobalResultFilterAttribute加入到全局过滤器
    • action只需正常返回Data里的类型值即可

    异常处理

    • 通常我们项目中的异常会分几种,
      1、业务上的自己定义的异常信息(本文暂称它为业务异常),这些异常信息通常都是要给用户看的。
      2、未捕获的程序异常(本文暂称它为程序异常),这类异常要在开发环境让开发者看到,但在生产环境时,会隐藏异常的详细信息
    • 通常会在如下几个地方对上面的异常进行处理
      1、在MVC管道里
      2、在asp.net core管道里
      下面是两个管道里处理这两种异常的代码

    MVC管道处理异常

    在接口或接口调用的方法里如果手动throw BusinessException(BusinessException为业务异常的类),会被MVC管理捕获

     public class GlobalExceptionFilterAttribute : ExceptionFilterAttribute
        {
            private ILogger _logger;
            public GlobalExceptionFilterAttribute(ILogger<GlobalExceptionFilterAttribute> logger)
            {
                _logger = logger;
            }
            public override void OnException(ExceptionContext context)
            {
    
                if (context.Exception is BusinessException businessException)
                {
                    // 业务类的异常,返回4000状态,并返回异常内容。模型校验也会返回4000状态和内容
                    context.Result = new ObjectResult(ApiResultDto.BadRequestResult(businessException.Message));
                    if (_logger != null)
                    {
                        _logger.LogWarning(businessException, "businessException");
                    }
                }
                else
                {
                    context.Result = new ObjectResult(ApiResultDto.ServerErrorResult("未知异常"));
                    if (_logger != null)
                    {
                        _logger.LogError("exception:{exception} 
     innerException:{innerException}", context.Exception?.ToString(), context.Exception?.InnerException?.ToString());
                    }
                }
    
            }
        }
    

    asp.net core管道处理异常

    asp.net core 的管理配置是在Startup.cs的Configure方法里,管道异常处理代码如下

    //开发环境用异常处理程序页,让开发者能看到异常信息详细
     if (env.IsDevelopment())
    {
        app.UseMiniProfiler();
        app.UseDeveloperExceptionPage(); //开发环境用异常处理程序页,让开发者能看到异常信息详细
    }
    else
    {
        // 生产环境异常处理,隐藏异常详细信息,并记录日志
        app.UseExceptionHandler(errorApp =>
        {
    
            errorApp.Run(async context =>
            {
                var loggerFactory = (ILoggerFactory)context.RequestServices.GetService(typeof(ILoggerFactory));
                var logger = loggerFactory.CreateLogger("UnKnowException");
                var exceptionHandlerPathFeature =
                    context.Features.Get<IExceptionHandlerPathFeature>();
                //业务异常
                ApiResultDto responseResultModel;
                if (exceptionHandlerPathFeature?.Error is BusinessException businessException)
                {
                    responseResultModel = ApiResultDto.BadRequestResult(businessException.Message);
                    if (logger != null)
                    {
                        logger.LogError(exceptionHandlerPathFeature?.Error?.ToString());
                    }
                }
                else
                {
                    responseResultModel = ApiResultDto.BadRequestResult($"程序出错,出于安全考虑,出错信息未能返回,请联系IT进行处理,错误时间{DateTime.Now}");
                    if (logger != null)
                    {
                        logger.LogError(exceptionHandlerPathFeature?.Error?.ToString());
                    }
                }
                context.Response.ContentType = "application/json";
                context.Response.StatusCode = (int)HttpStatusCode.OK;
                await context.Response.WriteAsync(JsonConvert.SerializeObject(responseResultModel));
            });
        });
    
    
        //HTTP严格传输安全 让网站可以通知浏览器它不应该再使用HTTP加载该网站,而是自动转换该网站的所有的HTTP链接至更安全的HTTPS。它包含在HTTP的协议头 Strict-Transport-Security 中,在服务器返回资源时带上,换句话说,它告诉浏览器将URL协议从HTTP更改为HTTPS(会更安全),并要求浏览器对每个请求执行此操作。
        //正式环境官方建议用UseHsts和UseHttpsRedirection,
        // 如果反方代理服务器,如ngix已经有配置过http重定向https或是设置hsts,则不需要设置这两句
        //参考: https://docs.microsoft.com/en-us/aspnet/core/security/enforcing-ssl?view=aspnetcore-3.1&tabs=visual-studio
        app.UseHsts();
        app.UseHttpsRedirection();//将所有的http重定向https
    }
    
    
  • 相关阅读:
    html5 audio vedio and video.js
    webpack的require是如何工作的?
    webpack HMR是如何工作的?
    vuejs code splitting with webpack 3种模式
    how webpack Hot Module Replacement works
    C# checkedlistbox 控件 有bug
    C# DataGridView 更改类型 重绘
    C# webapi
    C# 遍历控件名称
    C# 转json
  • 原文地址:https://www.cnblogs.com/shengyu-kmust/p/13453791.html
Copyright © 2020-2023  润新知