首页 > 技术文章 > .net常用的模型验证

Qintai 2021-06-29 11:41 原文

在 日常的后端api开发过程中呢,可能我待的公司不多,其实微软已经在框架中已经封装好了 模型验证,公司项目在实际使用中,感觉就知道的人感觉很少,这……
这么好用的参数验证器,为啥都不使用呢,呵呵!
模型验证高级用法请参照官网,下面介绍下自定义的简单用法

比如:

public class Persion
{
   public int Id{get;set;}
   public string Name{get;set;}
}

public TResopnse GetkkByIdd(Persion input)
{
   //很多人习惯会这样写
    if(input.Id <= 0)
    {
        return new TResopnse("参数Id错误");
    }
    if(string.isNullOrStringEmpry(input.Name))
    {
        return new TResopnse("参数Name错误");
    }		
}

很显然,这样写,如果参数非常多,那这个 方法的验证代码不会显得很臃肿吗??
于是,我见到升级版本的写法

public class Persion
{
   public int Id{get;set;}
   public string Name{get;set;}
  
   public (int code,string msg) Verification()
   {
       if(input.Id <= 0)
        {
            return (-1,"参数Id错误");
        }
        if(string.IsNullOrEmpty(input.Name))
        {
            return (-1,"参数Name错误");
        }	
   }
}

public TResopnse GetkkByIdd(Persion input)
{
   (int code,string msg) = input.Verification();
   if(code== -1 )
   {
       return new TResopnse(msg);
   }
}

对此,感觉好像高级了些 (¬、¬) (¬_¬) 呵呵呵

设置参数校验方式(netcore 和 netFramework通用)

netcore 和 netFramework 都有验证属性,引用命名空间:using System.ComponentModel.DataAnnotations;
例:[StringLength] 等其他自行百度 ,如果 特性验证不能满足你的需求,你还可以 自定义验证方式 继承 IValidatableObject ,实现他的方法

// 简易版
public class Persion
{
   [Range(6, 21, ErrorMessage = "密码长度不够")]
   public int Id{get;set;}
   
   //[Required(ErrorMessage = "姓名不能为空")]
   // StringLength
   public string Name{get;set;}
}

//自定义版本
public class Persion :IValidatableObject
{
    public int Id{get;set;}
    public string Name{get;set;}
    
    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
    {
        if(input.Id <= 0)
        {
            yield return new ValidationResult("姓名不能为空", new[] { nameof(Name) })
        }

        if (Name.IsNullOrEmpty())
        {
            yield return new ValidationResult("姓名不能为空", new[] { nameof(Name) })
        }
    }
}

拦截验证参数

netcore 在中间件统一拦截验证,也可以通过Filter验证

对本次请求的参数验证不通过统一返回出去,不再进入 action ,对 action 代码 无代码入侵,这样不就挺好的吗,即实现了参数校验,又能保证 action 代码的整洁,完成了 参数校验代码的解耦,也是不是能体现除单一职责的模式呢!哈哈

public class ControllerActionFilter : ActionFilterAttribute
 {
        public override async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
        {
            if (!context.ModelState.IsValid)
            {
                foreach (var item in context.ModelState.Values)
                {
                    if (item.Errors.Count > 0)
                    {
                        var result = ReturnMsg.Success(-1, item.Errors[0].ErrorMessage);
                        context.Result = new JsonResult(result);
                        return;
                    }
                }
            }
            var callBackResult = await next(); //继续管道
        }
    }

netFramework 在Filter统一拦截验证

using System.Web.Http.Filters; 
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
public class RecordLogAttribute : ActionFilterAttribute
{
        public override void OnActionExecuting(HttpActionContext actionContext)
        {
            if (actionContext.ActionArguments.Count > 0)
            {
                if (!actionContext.ModelState.IsValid)
                {
                    string parmsMsg = null;
                    var error = actionContext.ModelState.Values.Where(p => p.Errors.Count > 0);
                    foreach (var item in error)
                    {
                        parmsMsg = item.Errors.FirstOrDefault().ErrorMessage;
                        break;
                    }
                    if (!string.IsNullOrWhiteSpace(parmsMsg))
                    {
                        CommonResponse<bool> result = CommonResponse<bool>.GetResult(0, parmsMsg, false);
                        actionContext.Response = new HttpResponseMessage(HttpStatusCode.OK)
                        {
                            Content = new StringContent(Newtonsoft.Json.JsonConvert.SerializeObject(result), null, "application/json")
                        };
                        return;
                    }
                }
            }
        }
}









推荐阅读