ASP.NET Core Web API 中整数值的自定义模型验证器
Custom Model Validator for Integer value in ASP.NET Core Web API
我开发了一个自定义验证器属性 class 用于检查我的模型 classes 中的整数值。但问题是这个 class 不起作用。我已经调试了我的代码,但在调试代码期间没有命中断点。这是我的代码:
public class ValidateIntegerValueAttribute : ValidationAttribute
{
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
if (value != null)
{
int output;
var isInteger = int.TryParse(value.ToString(), out output);
if (!isInteger)
{
return new ValidationResult("Must be a Integer number");
}
}
return ValidationResult.Success;
}
}
我还有一个过滤器 class 用于在应用程序请求管道中进行全局模型验证。这是我的代码:
public class MyModelValidatorFilter: IActionFilter
{
public void OnActionExecuting(ActionExecutingContext context)
{
if (context.ModelState.IsValid)
return;
var errors = new Dictionary<string, string[]>();
foreach (var err in actionContext.ModelState)
{
var itemErrors = new List<string>();
foreach (var error in err.Value.Errors){
itemErrors.Add(error.Exception.Message);
}
errors.Add(err.Key, itemErrors.ToArray());
}
actionContext.Result = new OkObjectResult(new MyResponse
{
Errors = errors
});
}
}
经过验证的模型class如下:
public class MyModelClass
{
[ValidateIntegerValue(ErrorMessage = "{0} must be a Integer Value")]
[Required(ErrorMessage = "{0} is required")]
public int Level { get; set; }
}
谁能告诉我为什么属性整数验证 class 不起作用。
模型验证在模型从请求中反序列化后开始发挥作用。如果模型包含整数字段 Level
并且您发送的值无法反序列化为整数(例如 "abc"),那么模型甚至不会被反序列化。结果,验证属性也不会被调用——只是没有验证模型。
照此看来,实施这样的ValidateIntegerValueAttribute
意义不大。这种验证已经由反序列化器执行,在本例中为 JSON.Net。您可以通过检查控制器操作中的模型状态来验证这一点。 ModelState.IsValid
将设置为 false
并且 ModelState
错误包将包含以下错误:
Newtonsoft.Json.JsonReaderException: Could not convert string to
integer: abc. Path 'Level', ...
还要补充一件事:为了 Required
验证属性的正确工作,您应该使基础 属性 可为空。如果没有这个,属性 将在模型反序列化器之后保留其默认值 (0
)。模型验证无法区分缺失值和等于默认值的值。因此,为了 Required
属性的正确工作,使 属性 可为空:
public class MyModelClass
{
[Required(ErrorMessage = "{0} is required")]
public int? Level { get; set; }
}
我开发了一个自定义验证器属性 class 用于检查我的模型 classes 中的整数值。但问题是这个 class 不起作用。我已经调试了我的代码,但在调试代码期间没有命中断点。这是我的代码:
public class ValidateIntegerValueAttribute : ValidationAttribute
{
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
if (value != null)
{
int output;
var isInteger = int.TryParse(value.ToString(), out output);
if (!isInteger)
{
return new ValidationResult("Must be a Integer number");
}
}
return ValidationResult.Success;
}
}
我还有一个过滤器 class 用于在应用程序请求管道中进行全局模型验证。这是我的代码:
public class MyModelValidatorFilter: IActionFilter
{
public void OnActionExecuting(ActionExecutingContext context)
{
if (context.ModelState.IsValid)
return;
var errors = new Dictionary<string, string[]>();
foreach (var err in actionContext.ModelState)
{
var itemErrors = new List<string>();
foreach (var error in err.Value.Errors){
itemErrors.Add(error.Exception.Message);
}
errors.Add(err.Key, itemErrors.ToArray());
}
actionContext.Result = new OkObjectResult(new MyResponse
{
Errors = errors
});
}
}
经过验证的模型class如下:
public class MyModelClass
{
[ValidateIntegerValue(ErrorMessage = "{0} must be a Integer Value")]
[Required(ErrorMessage = "{0} is required")]
public int Level { get; set; }
}
谁能告诉我为什么属性整数验证 class 不起作用。
模型验证在模型从请求中反序列化后开始发挥作用。如果模型包含整数字段 Level
并且您发送的值无法反序列化为整数(例如 "abc"),那么模型甚至不会被反序列化。结果,验证属性也不会被调用——只是没有验证模型。
照此看来,实施这样的ValidateIntegerValueAttribute
意义不大。这种验证已经由反序列化器执行,在本例中为 JSON.Net。您可以通过检查控制器操作中的模型状态来验证这一点。 ModelState.IsValid
将设置为 false
并且 ModelState
错误包将包含以下错误:
Newtonsoft.Json.JsonReaderException: Could not convert string to integer: abc. Path 'Level', ...
还要补充一件事:为了 Required
验证属性的正确工作,您应该使基础 属性 可为空。如果没有这个,属性 将在模型反序列化器之后保留其默认值 (0
)。模型验证无法区分缺失值和等于默认值的值。因此,为了 Required
属性的正确工作,使 属性 可为空:
public class MyModelClass
{
[Required(ErrorMessage = "{0} is required")]
public int? Level { get; set; }
}