4

asp.net Web API のモデル バインディングと検証 (データ注釈による) で少し問題が発生しています。

次のようなプロパティを持つモデルがあるようです

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

childObject の検証がトリガーされないようです。データは、Json.Net シリアライザーを使用して json からバインドされます。

これに対する回避策または修正はありますか?それとも、これに関連する何かを誤解していますか?


なぜこれがエラーにならないのか疑問に思わずにはいられません:

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.

なんてこった。フィールドの代わりにプロパティを宣言するのを忘れていました。

4

2 に答える 2

7

ディクショナリ値の検証を設定するには、2 つの方法があります。すべてのエラーを取得する必要はなく、最初に発生したエラーだけを取得する場合は、カスタム検証属性を使用できます。

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

もう 1 つの方法は、独自の 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;
    }
}
于 2013-10-21T08:33:19.387 に答える
1

属性はプロパティにのみ適用できるため、検証は常にフィールドに渡されます。自動実装されたゲッターとセッターを使用して、フィールド名と説明をプロパティに変更する必要があります。

これらは次のようになります

public string name { get; set; }
于 2013-10-21T12:56:30.073 に答える