Тот же атрибут DataAnnotation, повторенный для того же свойства - PullRequest
3 голосов
/ 05 ноября 2011

У меня есть довольно сумасшедшая пользовательская проверка, над которой я работаю. В основном, на основе выбора раскрывающегося списка, который будет определять, какие значения проверяются относительно целевого свойства.

Например, у меня есть следующее выпадающее меню:

1 = Автомобиль
2 = Грузовик

В моей пользовательской проверке, если выбрано «Автомобиль», значение не может быть больше 20. Если выбрано «Грузовик», значение не может быть больше 40.

Так что мои атрибуты должны выглядеть примерно так:

[ValueBelowIf("1", 20)]
[ValueBelowIf("2", 40)]
public int Value { get; set; }

Конечно, даже для его компиляции я должен установить это на свой пользовательский атрибут:

[AttributeUsage(AttributeTargets.Property, AllowMultiple = true)]
public class ValueBelowIfAttribute : ValidationAttribute, IClientValidatable

Однако представляется, что привязан только первый атрибут, а второй игнорируется.

Что я делаю не так?

Ответы [ 3 ]

1 голос
/ 14 февраля 2014

Вам необходимо переопределить реализацию по умолчанию TypeId . Валидатор MVC будет оценивать каждый уникальный атрибут только на основании его значения TypeId.

Измените реализацию вашего атрибута на следующую, и она будет работать:

[AttributeUsage(AttributeTargets.Property, AllowMultiple = true)]
public class ValueBelowIfAttribute : ValidationAttribute, IClientValidatable
{
  private object _typeId = new object();
  public override object TypeId
  {
    get { return this._typeId; }
  }
  // OTHER CODE
}

Из того, что я понял, AllowMultiple, по крайней мере в случае MVC, просто сообщает компилятору, что атрибут действителен, появляется несколько раз, но именно TypeId контролирует, как эти атрибуты оцениваются во время выполнения.

Это может быть полезно, поскольку вы можете статически (во время компиляции) разрешать применение одного и того же типа атрибута несколько раз, но во время выполнения игнорировать логически дублированные атрибуты. Например, в моем примере вместо возврата гарантированно уникального нового объекта () я мог бы вернуть хеш-код параметров атрибута. В этом случае, если вы сделали:

[ValueBelowIf("1", 20)]
[ValueBelowIf("2", 40)]
[ValueBelowIf("2", 40)]
public int Value { get; set; }

второй [ValueBelowIf("2", 40)] не будет оцениваться.

Подробнее об этом я узнал здесь: http://www.paraesthesia.com/archive/2010/03/02/the-importance-of-typeid-in-asp.net-mvc-dataannotations-validation-attributes.aspx

0 голосов
/ 27 ноября 2012

Поскольку C # Attrbiutes - ограниченные константы, я обнаружил, что лучший способ добиться этого - предоставить все значения через конструктор как отдельные значения.Это некрасиво, но единственный способ сделать это.

Например:

[AttributeUsage(AttributeTargets.Property, AllowMultiple = true)]
public class ValueBelowIfAttribute : ValidationAttribute, IClientValidatable
{
    public string IfValue { get; set; }
    public int BelowValue { get; set; }
    public string IfValue2 { get; set; }
    public int BelowValue2 { get; set; }
    public string IfValue3 { get; set; }
    public int BelowValue3 { get; set; }

    public ValueBelowIfAttribute(string ifValue, int belowValue)
    {
        // do stuff
    }

    public ValueBelowIfAttribute(string ifValue, int belowValue, string ifValue2, int belowValue2)
    {
        // do stuff
    }

    public ValueBelowIfAttribute(string ifValue, int belowValue, string ifValue2, int belowValue2, string ifValue3, int belowValue3)
    {
        // do stuff
    }
}
0 голосов
/ 05 ноября 2011

Вы пытаетесь внедрить обще-классовую логику проверки в технику проверки свойств. Не делай этого! Вместо этого используйте надлежащий механизм проверки класса, например, реализуйте IValidatableObject или используйте FluentValidation

...