ASP.NET MVC : DataAnnotation에 의한 사용자 지정 유효성 검사


110

문자열 유형의 4 가지 속성이있는 모델이 있습니다. StringLength 주석을 사용하여 단일 속성의 길이를 확인할 수 있다는 것을 알고 있습니다. 그러나 결합 된 4 개 속성의 길이를 확인하고 싶습니다.

데이터 주석으로이를 수행하는 MVC 방법은 무엇입니까?

나는 MVC를 처음 사용하고 내 자신의 솔루션을 만들기 전에 올바른 방법으로하고 싶기 때문에 이것을 묻습니다.


2
Fluent Validation을 보셨습니까? 데이터 주석보다 훨씬 더 복잡한 시나리오를 처리합니다
— levelnis

적극 권장되는 솔루션을 살펴보십시오 ... dotnetcurry.com/ShowArticle.aspx?ID=776
— Niks

대답 해줘서 고마워. Fluent Validation을 확인해 보겠습니다. 들어 본 적이 없습니다. 그리고 Niks, Darin은 기본적으로 귀하가 게시 한 링크의 기사에서 설명하는 내용을 작성했습니다. 그래서 고마워요 ... 멋진 것들!
— Danny van der Kraan

답변:


177

사용자 지정 유효성 검사 속성을 작성할 수 있습니다.

public class CombinedMinLengthAttribute: ValidationAttribute
{
    public CombinedMinLengthAttribute(int minLength, params string[] propertyNames)
    {
        this.PropertyNames = propertyNames;
        this.MinLength = minLength;
    }

    public string[] PropertyNames { get; private set; }
    public int MinLength { get; private set; }

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        var properties = this.PropertyNames.Select(validationContext.ObjectType.GetProperty);
        var values = properties.Select(p => p.GetValue(validationContext.ObjectInstance, null)).OfType<string>();
        var totalLength = values.Sum(x => x.Length) + Convert.ToString(value).Length;
        if (totalLength < this.MinLength)
        {
            return new ValidationResult(this.FormatErrorMessage(validationContext.DisplayName));
        }
        return null;
    }
}

그런 다음 뷰 모델을 사용하여 속성 중 하나를 장식 할 수 있습니다.

public class MyViewModel
{
    [CombinedMinLength(20, "Bar", "Baz", ErrorMessage = "The combined minimum length of the Foo, Bar and Baz properties should be longer than 20")]
    public string Foo { get; set; }
    public string Bar { get; set; }
    public string Baz { get; set; }
}

4
답변 해 주셔서 감사합니다. 답변을 수락했습니다. 사실 조금 당황 스러워요. 전체 솔루션을 작성했습니다! 헤헤. 최대 길이를 확인하기 위해 IsValid 함수 만 변경하면됩니다. 그렇다면 이것이 이러한 유형의 문제에 대해 허용되는 MVC 솔루션입니까?
— Danny van der Kraan

7
@DannyvanderKraan, 예, 이것이 허용되는 방법입니다. 물론 이것은 너무 나빠서 절대 사용하지 않고 대신 FluentValidation.NET을 사용하여 유효성 검사를 수행합니다.
— Darin Dimitrov 2013

11
여기 : fluentvalidation.codeplex.com . 다음과 같은보기 모델에 대한 간단한 유효성 검사기를 작성할 수 있습니다 (단일 코드 줄) this.RuleFor(x => x.Foo).Must((x, foo) => x.Foo.Length + x.Bar.Length + x.Baz.Length < 20).WithMessage("The combined minimum length of the Foo, Bar and Baz properties should be longer than 20");. 이제 데이터 주석으로 작성 해야하는 내 대답의 코드를보고 어떤 것을 선호하는지 알려주십시오. 선언적 유효성 검사 모델은 명령형 모델에 비해 매우 열악합니다.
— Darin Dimitrov 2013

1
조금 늦었지만 사용자 지정 데이터 주석을 허용하기 위해 "켜야"하는 다른 설정이 있는지 아는 사람이 있습니까? web.config 파일에 눈에 거슬리지 않는 js를위한 네임 스페이스를 추가하는 것에 대해 알고 있지만 다른 곳은 어디입니까?
— Jose

1
아침 내내 이걸 찾고 있었어 ! 나는 그것을 mplemented했으나 안타깝게도 때 IsValid호출되는이 validationContextnull입니다. 내가 뭘 잘못했는지 알아? :-(
— Grimm The Opiner 2013

95

자체 검증 된 모델

모델은 인터페이스를 구현해야합니다 IValidatableObject. Validate메서드에 유효성 검사 코드를 넣으십시오 .

public class MyModel : IValidatableObject
{
    public string Title { get; set; }
    public string Description { get; set; }

    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
    {
        if (Title == null)
            yield return new ValidationResult("*", new [] { nameof(Title) });

        if (Description == null)
            yield return new ValidationResult("*", new [] { nameof(Description) });
    }
}

참고 : 이것은 서버 측 유효성 검사입니다. 클라이언트 측에서는 작동하지 않습니다. 양식 제출 후에 만 ​​유효성 검사가 수행됩니다.


Andrei에게 대답 해 주셔서 감사합니다. 귀하의 솔루션도 작동하지만 재사용이 더 가능하기 때문에 Darin을 선택합니다.
— 대니 반 데르 Kraan

6
yield return new ValidationResult ( "제목은 필수입니다.", "제목"); 필요한 경우 표시 할 유효성 검사 오류를 그룹화하는 데 유용한 속성 이름을 추가합니다.
— Mike Kingscott

5
이 유효성 검사 메서드는 모든 유효성 검사 속성이 유효성 검사를 통과 한 후에 만 ​​호출됩니다.
— Pedro

3
내 유효성 검사가 매우 구체적이기 때문에 이것은 나를 위해 잘 작동했습니다. 사용자 지정 속성을 추가하는 것은 유효성 검사가 다시 사용되지 않을 것이기 때문에 나에게 과잉이었습니다.
— Steve S

이것이 제가 찾고있는 것입니다. 감사합니다!
— Amol Jadhav

27

ExpressiveAnnotations 는 다음과 같은 가능성을 제공합니다.

[Required]
[AssertThat("Length(FieldA) + Length(FieldB) + Length(FieldC) + Length(FieldD) > 50")]
public string FieldA { get; set; }

이것은 훌륭합니다!
— 내기

방금이 답변을 찾았고 시간이 많이 절약되었습니다. ExpressiveAnnotations는 훌륭합니다!
— Brad

10

Darin의 대답을 개선하기 위해 조금 더 짧을 수 있습니다.

public class UniqueFileName : ValidationAttribute
{
    private readonly NewsService _newsService = new NewsService();

    public override bool IsValid(object value)
    {
        if (value == null) { return false; }

        var file = (HttpPostedFile) value;

        return _newsService.IsFileNameUnique(file.FileName);
    }
}

모델:

[UniqueFileName(ErrorMessage = "This file name is not unique.")]

오류 메시지가 필요합니다. 그렇지 않으면 오류가 비어 있습니다.


8

배경:

수신 된 데이터가 유효하고 올바른지 확인하여이 데이터로 추가 처리를 수행 할 수 있도록 모델 유효성 검사가 필요합니다. 액션 메서드에서 모델을 검증 할 수 있습니다. 기본 제공 유효성 검사 속성은 Compare, Range, RegularExpression, Required, StringLength입니다. 그러나 기본 제공 속성 이외의 유효성 검사 속성이 필요한 시나리오가있을 수 있습니다.

사용자 지정 유효성 검사 속성

public class EmployeeModel 
{
    [Required]
    [UniqueEmailAddress]
    public string EmailAddress {get;set;}
    public string FirstName {get;set;}
    public string LastName {get;set;}
    public int OrganizationId {get;set;}
}

사용자 지정 유효성 검사 특성을 만들려면 ValidationAttribute에서이 클래스를 파생해야합니다.

public class UniqueEmailAddress : ValidationAttribute
{
    private IEmployeeRepository _employeeRepository;
    [Inject]
    public IEmployeeRepository EmployeeRepository
    {
        get { return _employeeRepository; }
        set
        {
            _employeeRepository = value;
        }
    }
    protected override ValidationResult IsValid(object value,
                        ValidationContext validationContext)
    {
        var model = (EmployeeModel)validationContext.ObjectInstance;
        if(model.Field1 == null){
            return new ValidationResult("Field1 is null");
        }
        if(model.Field2 == null){
            return new ValidationResult("Field2 is null");
        }
        if(model.Field3 == null){
            return new ValidationResult("Field3 is null");
        }
        return ValidationResult.Success;
    }
}

도움이 되었기를 바랍니다. 건배!

참고 문헌


1

대답하기 조금 늦었지만 누가 찾고 있는지. 데이터 주석과 함께 추가 속성을 사용하여 쉽게 수행 할 수 있습니다.

public string foo { get; set; }
public string bar { get; set; }

[MinLength(20, ErrorMessage = "too short")]
public string foobar 
{ 
    get
    {
        return foo + bar;
    }
}

그게 전부입니다. 특정 위치에 유효성 검사 오류도 표시하려면보기에 다음을 추가 할 수 있습니다.

@Html.ValidationMessage("foobar", "your combined text is too short")

뷰에서이 작업을 수행하면 현지화를 수행하려는 경우 유용 할 수 있습니다.

도움이 되었기를 바랍니다!

당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.