Tengo la siguiente definición de modelo de vista
public class AccessRequestViewModel
{
public Request Request { get; private set; }
public SelectList Buildings { get; private set; }
public List<Person> Persons { get; private set; }
}
Entonces, en mi solicitud debe haber al menos 1 persona para una solicitud de acceso. ¿Qué enfoque podría utilizar para validar? No quiero que esta validación ocurra en mi controlador, lo cual sería simple de hacer. ¿La única opción es un atributo de validación personalizado?
Editar: actualmente realizando esta validación con FluentValidation (¡buena biblioteca!)
RuleFor(vm => vm.Persons)
.Must((vm, person) => person.Count > 0)
.WithMessage("At least one person is required");
RuleFor(x => x.Persons).Must(x => x.Count > 0).WithMessage("At least a person is required");
se compilará y funcionará bien.Otra forma posible de manejar las validaciones de recuento para los miembros de la colección del objeto del modelo de vista es tener una propiedad calculada que devuelva la colección o el recuento de la lista. Luego, se puede aplicar un RangeAttribute como en el código siguiente para hacer cumplir la validación del recuento:
[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; } }
En el código anterior, ItemCount es una propiedad calculada de ejemplo en un modelo de vista que se está validando, y Items es una propiedad de colección de miembros de ejemplo cuyo recuento se está comprobando. En este ejemplo, al menos un elemento se aplica al miembro de la colección y el límite máximo es el valor máximo que puede tomar un número entero, que es, para la mayoría de los propósitos prácticos, ilimitado. El mensaje de error en caso de error de validación también se puede establecer a través del miembro ErrorMessage de RangeAttribute en el ejemplo anterior.
fuente
El siguiente código funciona en asp.net core 1.1.
[Required, MinLength(1, ErrorMessage = "At least one item required in work order")] public ICollection<WorkOrderItem> Items { get; set; }
fuente
La respuesta de Darin es buena, pero la versión siguiente le dará automáticamente un mensaje de error útil.
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)); } }
Uso:
[MinimumElements(1)] public List<Customer> Customers {get;set} [MinimumElements(2)] public List<Address> Addresses {get;set}
Mensaje de error:
fuente
Aquí tiene dos opciones, crear un atributo de validación personalizado y decorar la propiedad con él, o puede hacer que su ViewModel implemente la
IValidatableObject
interfaz (que define unValidate
método)Espero que esto ayude :)
fuente
Sería muy limpio y elegante tener una validación personalizada. Algo como esto:
public class AccessRequestViewModel { public Request Request { get; private set; } public SelectList Buildings { get; private set; } [AtLeastOneItem] public List<Person> Persons { get; private set; } }
O
[MinimumItems(1)]
.fuente
Un enfoque podría ser utilizar un constructor privado y un método estático para devolver una instancia del objeto.
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; } }
Al usar siempre la fábrica para crear una instancia de su ViewModel, puede asegurarse de que siempre habrá una persona.
Probablemente esto no sea ideal para lo que desea, pero probablemente funcionaría.
fuente