Массив должен содержать 1 элемент
У меня есть следующий класс:
public class CreateJob
{
[Required]
public int JobTypeId { get; set; }
public string RequestedBy { get; set; }
public JobTask[] TaskDescriptions { get; set; }
}
Я хотел бы иметь аннотацию данных выше TaskDescriptions
так что массив должен содержать хотя бы один элемент? Так же, как [Required]
, Это возможно?
9 ответов
Я видел пользовательский атрибут проверки, используемый для этого раньше, например:
(Я привел пример со списком, но может быть адаптирован для массива или вы можете использовать список)
public class MustHaveOneElementAttribute : ValidationAttribute
{
public override bool IsValid(object value)
{
var list = value as IList;
if (list != null)
{
return list.Count > 0;
}
return false;
}
}
[MustHaveOneElementAttribute (ErrorMessage = "At least a task is required")]
public List<Person> TaskDescriptions { get; private set; }
Это можно сделать с помощью стандартного атрибута валидации MinLengthAttribute, но работает ТОЛЬКО для массивов:
public class CreateJob
{
[Required]
public int JobTypeId { get; set; }
public string RequestedBy { get; set; }
[MinLength(1)]
public JobTask[] TaskDescriptions { get; set; }
}
Вот немного улучшенная версия решения @dove, которое обрабатывает различные типы коллекций, такие как HashSet, List и т. Д.
public class MustHaveOneElementAttribute : ValidationAttribute
{
public override bool IsValid(object value)
{
var collection = value as IEnumerable;
if (collection != null && collection.GetEnumerator().MoveNext())
{
return true;
}
return false;
}
}
Пожалуйста, позвольте мне добавить примечание об использовании MinLengthAttribute с.NET Core.
Microsoft рекомендует использовать Razor Pages, начиная с.NET Core 2.0.
В настоящее время проверка с помощью MinLengthAttribute для свойства в PageModel не работает:
[BindProperty]
[Required]
[MinLength(1)]
public IEnumerable<int> SelectedStores { get; set; }
ModelState.IsValid возвращает true, когда SelectedStores.Count() == 0.
Протестировано с.NET Core 2.1 Preview 2.
Вы должны использовать 2 стандартных атрибута аннотации
public class CreateJob
{
[MaxLength(1), MinLength(1)]
public JobTask[] TaskDescriptions { get; set; }
}
Начиная с .net 8, вы можете использовать System.ComponentModel.DataAnnotations.LengthAttribute.
Этот атрибут теперь работает сString
ИCollection
. Затем вы указываете минимальную и максимальную длину атрибута.
Использование:
[Length(1, int.MaxValue)]
public IEnumerable<int> TaskDescriptions { get; set; }
В дополнение к ответу mynkow я добавил возможность передавать атрибуту минимальное значение счетчика и создавать значимые сообщения об ошибках:
public class MinimumElementsRequiredAttribute : ValidationAttribute
{
private readonly int _requiredElements;
public MinimumElementsRequiredAttribute(int requiredElements)
{
if (requiredElements < 1)
{
throw new ArgumentOutOfRangeException(nameof(requiredElements), "Minimum element count of 1 is required.");
}
_requiredElements = requiredElements;
}
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
if (!(value is IEnumerable enumerable))
{
return new ValidationResult($"The {validationContext.DisplayName} field is required.");
}
int elementCount = 0;
IEnumerator enumerator = enumerable.GetEnumerator();
while (enumerator.MoveNext())
{
if (enumerator.Current != null && ++elementCount >= _requiredElements)
{
return ValidationResult.Success;
}
}
return new ValidationResult($"At least {_requiredElements} elements are required for the {validationContext.DisplayName} field.");
}
}
Используйте это так:
public class Dto
{
[MinimumElementsRequired(2)]
public IEnumerable<string> Values { get; set; }
}
Просто обновляю ответ Dove (@dove) на синтаксис C# 9:
public class MustHaveOneElementAttribute : ValidationAttribute
{
public override bool IsValid(object value)
=> value is IList {Count: > 0};
}
Атрибут MinLength считает значение допустимым, если оно равно нулю. Поэтому просто инициализируйте ваше свойство в модели как пустой массив, и оно будет работать.
MinLength(1, ErrorMessageResourceName = nameof(ValidationErrors.AtLeastOneSelected), ErrorMessageResourceType = typeof(ValidationErrors))]
int[] SelectedLanguages { get; set; } = new int[0];