Подтвердить что ты не робот

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

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

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");
4b9b3361

Ответ 1

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

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

Ответ 2

Еще один возможный способ обработки проверок подсчета для элементов коллекции объектов модели просмотра - это иметь вычисленное свойство, возвращающее счет коллекции или списка. Атрибут 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 является примерным вычисленным свойством для проверяемой модели представления, а элементы - это свойство элемента-члена примера, счет которого проверяется. В этом примере по крайней мере один элемент применяется к члену коллекции, а максимальный предел - это максимальное значение, которое может принимать целое число, которое для большинства практических целей неограниченное. Сообщение об ошибке при сбое проверки также может быть установлено через член RangeAttribute ErrorMessage в приведенном выше примере.

Ответ 3

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

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

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

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

Ответ 4

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

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)].

Ответ 5

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

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

Ответ 6

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

[Required, MinLength(1, ErrorMessage = "At least one item required in work order")]
public ICollection<WorkOrderItem> Items { get; set; }