c# - Asp.net Web Api 嵌套模型验证

标签 c# asp.net-web-api data-annotations

我在 asp.net web api 的模型绑定(bind)和验证(通过数据注释)中遇到了一些问题。

看起来如果我有一个具有属性的模型

Dictionary<string, childObject> obj { get; set; }

childObject 的验证似乎没有触发。数据是使用 Json.Net 序列化程序从 json 绑定(bind)的。

是否有一些解决方法或修复方法?还是我误解了与此相关的其他内容?


我不禁想知道为什么这不会导致错误:

public class Child
{        
    [Required]
    [StringLength(10)]
    public string name;
    [Required]
    [StringLength(10)]
    public string desc;     
}

//elsewhere
Child foo = new Child();
foo.name = "hellowrodlasdasdaosdkasodasasdasdasd";

List<ValidationResult> results = new List<ValidationResult>();
Validator.TryValidateObject(foo, new ValidationContext(foo), results, true);
// results.length == 0 here.

天哪。我忘了声明属性而不是字段。

最佳答案

有两种方法可以设置字典值的验证。如果您不关心获取所有错误而只关心遇到的第一个错误,则可以使用自定义验证属性。

public class Foo
{
    [Required]
    public string RequiredProperty { get; set; }

    [ValidateDictionary]
    public Dictionary<string, Bar> BarInstance { get; set; }
}

public class Bar
{
    [Required]
    public string BarRequiredProperty { get; set; }
}

public class ValidateDictionaryAttribute : ValidationAttribute
{
    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        if (!IsDictionary(value)) return ValidationResult.Success;

        var results = new List<ValidationResult>();
        var values = (IEnumerable)value.GetType().GetProperty("Values").GetValue(value, null);
        values.OfType<object>().ToList().ForEach(item => Validator.TryValidateObject(item, new ValidationContext(item, null, validationContext.Items), results));
        Validator.TryValidateObject(value, new ValidationContext(value, null, validationContext.Items), results);
        return results.FirstOrDefault() ?? ValidationResult.Success;
    }

    protected bool IsDictionary(object value)
    {
        if (value == null) return false;
        var valueType = value.GetType();
        return valueType.IsGenericType && valueType.GetGenericTypeDefinition() == typeof (Dictionary<,>);
    }
}

另一种方法是创建您自己的字典作为 IValidatableObject 并在其中进行验证。此解决方案使您能够返回所有错误。

public class Foo
{
    [Required]
    public string RequiredProperty { get; set; }

    public ValidatableDictionary<string, Bar> BarInstance { get; set; }
}

public class Bar
{
    [Required]
    public string BarRequiredProperty { get; set; }
}

public class ValidatableDictionary<TKey, TValue> : Dictionary<TKey, TValue>, IValidatableObject
{
    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
    {
        var results = new List<ValidationResult>();
        Values.ToList().ForEach(item => Validator.TryValidateObject(item, new ValidationContext(item, null, validationContext.Items), results));
        return results;
    }
}

关于c# - Asp.net Web Api 嵌套模型验证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19448662/

相关文章:

c# - DataAnnotations tryvalidateobject 总是返回 true

regex - 使用电子邮件地址作为用户名的正则表达式?

c# - Xamarin Forms 相对布局 - 获取内部居中的堆栈布局

c# - Linq 获取按最快日期排序的第一行,其中 B 列不是 "Expired"或 "Cancelled"

c# - 如何缓存 .NET Web API 请求(并使用 w/AngularJS $http)

c# - 使用存储库模式实现依赖注入(inject)的困惑 - c# EF Core

javascript - 如果多个复选框选中,如何发出警报 C#

c# - ScrollViewer.ChangeView 什么时候失败?

c# - 我应该如何使用不允许异步 Controller 操作的 CMS 处理异步 API 调用?

c# - 基本类型的必需属性没有意义