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.