ASP.NET WEB API 自定义模型校验过滤器

  对外公开WEB接口时,对模型校验是常见的安全常识,常见的写法是在controller中判断ModelState.IsValid,以注册用户API为例。

Model:

public class RegisterCustomerModel
{
        [Required(ErrorMessage = "姓名不能为空")]
        [StringLength(10,ErrorMessage = "姓名长度不能超过10个字")]
        public string Name { get; set; }

        [Required(ErrorMessage = "电话不能为空")]
        [RegularExpression(@"^1[34578]\d{9}$", ErrorMessage = "电话号码格式不正确")]
        public string Phone { get; set; }

        [Required(ErrorMessage = "密码不能为空")]
        [StringLength(48, ErrorMessage = "密码长度不能超过48个字符")]
        public string Password { get; set; }

}

打印校验失败的错误消息代码:

public static class ModelStateExtension
   {
        public static string ToErrorMessage(this ModelStateDictionary modelStateDictionary)
        {
            var stringBuilder = new StringBuilder();

            foreach (var value in modelStateDictionary.Values)
            {
                foreach (var error in value.Errors)
                {
                    stringBuilder.AppendLine(error.ErrorMessage);
                }
            }

            return stringBuilder.ToString();
        }
   }

Controller:

public ResponseProtocol Register(RegisterCustomerModel registerCustomerModel)
  {
            if (!ModelState.IsValid)
            {
                return new ResponseProtocol((int)ResponseResultEnum.ValidateError, ModelState.ToErrorMessage(), string.Empty);
            }

            Customer customer = new Customer
            {
                Name = registerCustomerModel.Name,
                Phone = registerCustomerModel.Phone,
                WeiXinNo = registerCustomerModel.WeiXinNo,
                Company = registerCustomerModel.Company,
                UpdateTime = DateTime.Now
            };

            _customerService.Add(customer);

            return new ResponseProtocol((int)ResponseResultEnum.Success, "注册成功", string.Empty);
    }

  以上写法是在controller里进行校验,缺点是每个需要进行校验的controller都要写一次,为了消除重复,可以将校验代码写入全局过滤器中,由过滤器进行统一模型校验,修改后的代码:

public class ValidationModelFilter : ActionFilterAttribute
    {
        public override void OnActionExecuting(HttpActionContext actionContext)
        {
            //get方法不进行模型校验
            if (actionContext.Request.Method.Method=="GET")
            {
                return;
            }

            if (!actionContext.ModelState.IsValid)
            {
                var error = JsonConvert.SerializeObject(new ResponseProtocol()
                {
                    Code =(int)ResponseResultEnum.ValidateError,
                    Message = actionContext.ModelState.ToErrorMessage(),
                    Data = string.Empty
                });

                var httpResponseMessage = new HttpResponseMessage
                {
                    Content = new StringContent(error)
                };

                httpResponseMessage.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
                actionContext.Response = httpResponseMessage;
            }
        }
    }

  然后在全局过滤器(WebApiConfig)注册一下: config.Filters.Add(new ValidationModelFilter());