목록에 대한 ViewModel 유효성 검사
다음과 같은 viewmodel 정의가 있습니다.
public class AccessRequestViewModel
{
public Request Request { get; private set; }
public SelectList Buildings { get; private set; }
public List<Person> Persons { get; private set; }
}
따라서 내 응용 프로그램에는 액세스 요청에 대해 최소한 한 사람이 있어야합니다. 검증을 위해 어떤 접근 방식을 사용할 수 있습니까? 이 유효성 검사가 내 컨트롤러에서 발생하는 것을 원하지 않습니다. 유일한 선택은 사용자 지정 유효성 검사 속성입니까?
편집 : 현재 FluentValidation (멋진 라이브러리!)으로이 유효성 검사를 수행하고 있습니다.
RuleFor(vm => vm.Persons)
.Must((vm, person) => person.Count > 0)
.WithMessage("At least one person is required");
데이터 주석을 사용하여 유효성 검사를 수행하는 경우 사용자 정의 속성이 필요할 수 있습니다.
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");
뷰 모델 개체의 컬렉션 멤버에 대한 개수 유효성 검사를 처리하는 또 다른 방법은 컬렉션 또는 목록 개수를 반환하는 계산 된 속성을 갖는 것입니다. 그런 다음 아래 코드와 같이 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는 개수를 확인하는 예제 멤버 컬렉션 속성입니다. 이 예에서는 컬렉션 멤버에 대해 하나 이상의 항목이 적용되고 최대 제한은 정수가 취할 수있는 최대 값이며, 이는 대부분의 실제 목적에서 제한되지 않습니다. 유효성 검사 실패시 오류 메시지는 위의 예에서 RangeAttribute의 ErrorMessage 멤버를 통해 설정할 수도 있습니다.
다음 코드는 asp.net core 1.1에서 작동합니다.
[Required, MinLength(1, ErrorMessage = "At least one item required in work order")]
public ICollection<WorkOrderItem> Items { get; set; }
Darin's answer is good but the version below will automatically give you a useful error message.
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));
}
}
Usage:
[MinimumElements(1)]
public List<Customer> Customers {get;set}
[MinimumElements(2)]
public List<Address> Addresses {get;set}
Error message:
- Customers requires at least 1 element
- Addresses requires at least 2 elements
You have two choices here, either create a Custom Validation Attribute and decorate the property with it, or you can make your ViewModel implement the IValidatableObject
interface (which defines a Validate
method)
Hope this helps :)
It would be very clean and elegant to have a custom validation. Something like this:
public class AccessRequestViewModel
{
public Request Request { get; private set; }
public SelectList Buildings { get; private set; }
[AtLeastOneItem]
public List<Person> Persons { get; private set; }
}
Or [MinimumItems(1)]
.
One approach could be to use a private constructor and a static method to return an instance of the object.
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; }
}
By always using the factory to instantiate your ViewModel, you can ensure that there will always be a person.
This probably isn't ideal for what you want, but it would likely work.
참고URL : https://stackoverflow.com/questions/5146732/viewmodel-validation-for-a-list
'Program Tip' 카테고리의 다른 글
MySQL에서 공백 앞에있는 모든 문자 가져 오기 (0) | 2020.10.28 |
---|---|
Windows 배치 파일에 여러 색상을 사용하는 방법은 무엇입니까? (0) | 2020.10.28 |
없음 값으로 Pyspark 데이터 프레임 열 필터링 (0) | 2020.10.28 |
CSS 사이드 바 높이 100 % (0) | 2020.10.28 |
iTunes Connect API (0) | 2020.10.28 |