ASP.NET Core Web API中用于整数值的自定义模型验证器

5

我为我的模型类开发了一个自定义验证器Attribute类,用于检查整数值。但问题是这个类不起作用。我已经调试了代码,但在调试代码时断点没有被触发。以下是我的代码:

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;
        }
    }

我还有一个用于在应用程序请求管道中全局验证模型的过滤器类。以下是我的代码:

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
        });
    }
}

以下是带验证的模型类:
```html

带验证的模型类如下所示:

```
public class MyModelClass

{

[ValidateIntegerValue(ErrorMessage = "{0} must be a Integer Value")]
[Required(ErrorMessage = "{0} is required")]
public int Level { get; set; }        

请问有人能告诉我为什么整数验证类属性不起作用吗?


Response 使用哪个库? - superninja
1个回答

11

模型验证在从请求中反序列化模型后发挥作用。如果模型包含整数字段Level并且您发送的值无法反序列化为整数(例如"abc"),则模型甚至不会被反序列化。因此,验证属性也不会被调用 - 没有模型进行验证。

鉴于此,实现这样的ValidateIntegerValueAttribute没有太多意义。这种验证已经由反序列化器(在本例中为JSON.Net)执行。您可以通过检查控制器操作中的模型状态来验证这一点。ModelState.IsValid将设置为false,而ModelState错误包将包含以下错误:

Newtonsoft.Json.JsonReaderException:无法将字符串转换为整数:abc。路径“级别”,...

还有一件事需要补充:要正确使用Required验证属性,应将基础属性设为可空类型。否则,在模型反序列化后,该属性将保留其默认值(0)。模型验证无法区分缺失值和等于默认值的值。因此,为了使Required属性正常工作,请将属性设置为可空:

public class MyModelClass
{
    [Required(ErrorMessage = "{0} is required")]
    public int? Level { get; set; }
}

1
我相信这个答案也回答了你的另一个问题 - https://stackoverflow.com/questions/49300906/model-validation-is-not-working-in-asp-net-core-2-0 - CodeFuller
谢谢你的出色回答。它真的帮了我很多。请问您能否告诉我,在JSON.Net库处理请求之前是否有可能解决问题?在应用程序请求周期中是否有任何执行手动任务的方法? - mnu-nasir
JSON.Net和ASP.NET Web API都非常灵活,并为不同的场景提供了各种可扩展性点。但是,您能否更详细地描述一下您想如何处理这些情况?您是否希望JSON.Net跳过此类错误(例如,对于数字字段的“abc123”),并仍然反序列化具有有效属性的模型? - CodeFuller
请告诉我,在那种情况下我应该怎么做? - mnu-nasir
但是在这个阶段,您还没有访问模型或HttpContext。因此,当您遇到此类错误时,您没有适当的方法将其注册以进行进一步验证。我不太确定我完全理解您的用例-为什么您要在JSON.Net为您执行整数解析并提供适当的错误和模型状态时进行验证。 - CodeFuller
1
这个答案的最后一段非常棒,我已经搜索了一个小时才找到这个答案。 - Ed Graham

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接