Проверка верстки 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");
Ответы
Ответ 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; }