Проверка ViewModel для списка - PullRequest
       7

Проверка ViewModel для списка

67 голосов
/ 28 февраля 2011

У меня есть следующее определение модели представления

public class AccessRequestViewModel
{
    public Request Request { get; private set; }
    public SelectList Buildings { get; private set; }
    public List<Person> Persons { get; private set; }
}

Таким образом, в моем приложении должен быть хотя бы 1 человек для запроса доступа.Какой подход вы могли бы использовать для проверки?Я не хочу, чтобы эта проверка происходила в моем контроллере, что было бы просто сделать.Является ли единственный выбор настраиваемым атрибутом проверки?

Редактировать: В настоящее время эта проверка выполняется с помощью FluentValidation (хорошая библиотека!)

RuleFor(vm => vm.Persons)
                .Must((vm, person) => person.Count > 0)
                .WithMessage("At least one person is required");

Ответы [ 7 ]

151 голосов
/ 28 февраля 2011

Если вы используете аннотации данных для выполнения проверки, вам может потребоваться настраиваемый атрибут:

public class EnsureOneElementAttribute : ValidationAttribute
{
    public override bool IsValid(object value)
    {
        var list = value as IList;
        if (list != null)
        {
            return list.Count > 0;
        }
        return false;
    }
}

, а затем:

[EnsureOneElement(ErrorMessage = "At least a person is required")]
public List<Person> Persons { get; private set; }

или чтобы сделать его более общим:

public class EnsureMinimumElementsAttribute : ValidationAttribute
{
    private readonly int _minElements;
    public EnsureMinimumElementsAttribute(int minElements)
    {
        _minElements = minElements;
    }

    public override bool IsValid(object value)
    {
        var list = value as IList;
        if (list != null)
        {
            return list.Count >= _minElements;
        }
        return false;
    }
}

и затем:

[EnsureMinimumElements(1, ErrorMessage = "At least a person is required")]
public List<Person> Persons { get; private set; }

Лично я использую FluentValidation.NET вместо аннотаций данных для выполнения проверки, потому что я предпочитаю обязательную логику проверки вместо декларативной.Я думаю, что это более мощный.Поэтому мое правило проверки будет выглядеть так:

RuleFor(x => x.Persons)
    .Must(x => x.Count > 0)
    .WithMessage("At least a person is required");
12 голосов
/ 14 августа 2015

Другой возможный способ обработки проверок количества для членов коллекции объекта модели представления - это иметь вычисляемое свойство, возвращающее количество коллекции или списка.Затем можно применить RangeAttribute, как показано в приведенном ниже коде, для принудительной проверки количества:

[Range(minimum: 1, maximum: Int32.MaxValue, ErrorMessage = "At least one item needs to be selected")]
public int ItemCount
{
    get
    {
        return Items != null ? Items.Length : 0;
    }
}

В приведенном выше коде ItemCount является примером вычисляемого свойства для проверяемой модели представления, а Items является примером коллекции элементовсвойство, чей счет проверяется.В этом примере по крайней мере один элемент применяется к элементу коллекции, а максимальный предел - это максимальное значение, которое может принимать целое число, которое для большинства практических целей не ограничено.Сообщение об ошибке при сбое проверки также может быть установлено с помощью элемента ErrorMessage в RangeAttribute в приведенном выше примере.

5 голосов
/ 16 января 2018

Ответ Дарина хорош, но приведенная ниже версия автоматически выдаст вам полезное сообщение об ошибке.

public class MinimumElementsAttribute : ValidationAttribute
{
    private readonly int minElements;

    public MinimumElementsAttribute(int minElements)
    {
        this.minElements = minElements;
    }

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        var list = value as IList;

        var result = list?.Count >= minElements;

        return result
            ? ValidationResult.Success
            : new ValidationResult($"{validationContext.DisplayName} requires at least {minElements} element" + (minElements > 1 ? "s" : string.Empty));
    }
}

Использование:

[MinimumElements(1)]
public List<Customer> Customers {get;set}

[MinimumElements(2)]
public List<Address> Addresses {get;set}

Сообщение об ошибке:

  • Клиентам требуется как минимум 1 элемент
  • Адреса требуют как минимум 2 элемента
3 голосов
/ 31 августа 2017

Следующий код работает в ядре asp.net 1.1.

[Required, MinLength(1, ErrorMessage = "At least one item required in work order")]
public ICollection<WorkOrderItem> Items { get; set; }
1 голос
/ 28 февраля 2011

Здесь у вас есть два варианта: либо создать пользовательский атрибут проверки и украсить им свойство, либо вы можете заставить свой ViewModel реализовать интерфейс IValidatableObject (который определяет метод Validate)

Надеюсь, это поможет:)

0 голосов
/ 28 февраля 2011

Было бы очень чисто и элегантно иметь пользовательскую проверку. Примерно так:

public class AccessRequestViewModel
{
    public Request Request { get; private set; }
    public SelectList Buildings { get; private set; }
    [AtLeastOneItem]
    public List<Person> Persons { get; private set; }
}

или [MinimumItems(1)].

0 голосов
/ 28 февраля 2011

Одним из подходов может быть использование частного конструктора и статического метода для возврата экземпляра объекта.

public class AccessRequestViewModel
{
    private AccessRequesetViewModel() { };

    public static GetAccessRequestViewModel (List<Person> persons)
    {
            return new AccessRequestViewModel()
            {
                Persons = persons,
            };
    }

    public Request Request { get; private set; }
    public SelectList Buildings { get; private set; }
    public List<Person> Persons { get; private set; }
}

Всегда используя фабрику для создания экземпляра модели ViewModel, вы можете быть уверены, что человек всегда будет.

Это, вероятно, не идеально для того, что вы хотите, но, скорее всего, сработает.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...