ASP.NET Core MVC의 모델 유효성 검사Model validation in ASP.NET Core MVC

작성자: Rachel AppelBy Rachel Appel

모델 유효성 검사 소개Introduction to model validation

앱은 데이터베이스에 데이터를 저장하기 전에 데이터를 확인해야 합니다.Before an app stores data in a database, the app must validate the data. 데이터는 잠재적 보안 위협을 확인하고, 형식 및 크기별로 적절하게 서식이 지정되었는지 확인하고, 규칙을 준수해야 합니다.Data must be checked for potential security threats, verified that it's appropriately formatted by type and size, and it must conform to your rules. 유효성 검사는 중복되고 구현되기 번거로울 수 있지만 필요합니다.Validation is necessary although it can be redundant and tedious to implement. MVC에서 유효성 검사는 클라이언트와 서버 모두에서 발생합니다.In MVC, validation happens on both the client and server.

다행히 .NET는 유효성 검사를 유효성 검사 특성으로 추상화했습니다.Fortunately, .NET has abstracted validation into validation attributes. 이러한 특성에는 유효성 검사 코드가 포함되어 작성해야 하는 코드의 양을 감소시킵니다.These attributes contain validation code, thereby reducing the amount of code you must write.

GitHub에서 샘플 보기 또는 다운로드View or download sample from GitHub.

유효성 검사 특성Validation Attributes

유효성 검사 특성은 모델 유효성 검사를 구성하는 방법이므로 데이터베이스 테이블의 필드에 대한 유효성 검사와 개념적으로 유사합니다.Validation attributes are a way to configure model validation so it's similar conceptually to validation on fields in database tables. 데이터 형식이나 필수 필드를 할당하는 등 제약 조건이 포함됩니다.This includes constraints such as assigning data types or required fields. 다른 종류의 유효성 검사에는 신용 카드, 전화 번호 또는 이메일 주소와 같은 비즈니스 규칙을 적용하기 위해 데이터에 대한 패턴을 적용하는 것이 포함됩니다.Other types of validation include applying patterns to data to enforce business rules, such as a credit card, phone number, or email address. 유효성 검사 특성을 통해 훨씬 간단하고 사용하기 쉽게 이러한 요구 사항을 적용할 수 있습니다.Validation attributes make enforcing these requirements much simpler and easier to use.

영화 및 TV 프로그램에 대 한 정보를 저장하는 앱에서 주석이 추가된 Movie 모델은 다음과 같습니다.Below is an annotated Movie model from an app that stores information about movies and TV shows. 대부분의 속성은 필수이며 여러 문자열 속성에는 길이 요구 사항이 적용됩니다.Most of the properties are required and several string properties have length requirements. 또한 사용자 지정 유효성 검사 특성과 함께 Price 속성 대신에 0~$999.99 사이라는 숫자 범위 제한이 있습니다.Additionally, there's a numeric range restriction in place for the Price property from 0 to $999.99, along with a custom validation attribute.

public class Movie
{
    public int Id { get; set; }

    [Required]
    [StringLength(100)]
    public string Title { get; set; }

    [ClassicMovie(1960)]
    [DataType(DataType.Date)]
    public DateTime ReleaseDate { get; set; }

    [Required]
    [StringLength(1000)]
    public string Description { get; set; }

    [Range(0, 999.99)]
    public decimal Price { get; set; }

    [Required]
    public Genre Genre { get; set; }

    public bool Preorder { get; set; }
}

단순히 모델을 통해 읽으면 이 앱에서 데이터에 대한 규칙을 표시하여 코드를 쉽게 유지할 수 있습니다.Simply reading through the model reveals the rules about data for this app, making it easier to maintain the code. 널리 사용되는 여러 기본 제공 유효성 검사 특성은 다음과 같습니다.Below are several popular built-in validation attributes:

  • [CreditCard]: 속성에 신용 카드 형식이 있는지 유효성을 검사합니다.[CreditCard]: Validates the property has a credit card format.

  • [Compare]: 모델의 두 속성이 일치하는지 유효성을 검사합니다.[Compare]: Validates two properties in a model match.

  • [EmailAddress]: 속성에 이메일 형식이 있는지 유효성을 검사합니다.[EmailAddress]: Validates the property has an email format.

  • [Phone]: 속성에 전화 번호 형식이 있는지 유효성을 검사합니다.[Phone]: Validates the property has a telephone format.

  • [Range]: 지정된 범위 내에서 속성 값이 포함되는지 유효성을 검사합니다.[Range]: Validates the property value falls within the given range.

  • [RegularExpression]: 데이터가 지정된 정규식과 일치하는지 유효성을 검사합니다.[RegularExpression]: Validates that the data matches the specified regular expression.

  • [Required]: 필수 속성으로 설정합니다.[Required]: Makes a property required.

  • [StringLength]: 문자열 속성에 지정된 최대 길이가 있는지 유효성을 검사합니다.[StringLength]: Validates that a string property has at most the given maximum length.

  • [Url]: 속성에 URL 형식이 있는지 유효성을 검사합니다.[Url]: Validates the property has a URL format.

MVC는 유효성 검사를 위해 ValidationAttribute에서 파생된 모든 특성을 지원합니다.MVC supports any attribute that derives from ValidationAttribute for validation purposes. 많은 유용한 유효성 검사 특성을 System.ComponentModel.DataAnnotations 네임스페이스에서 확인할 수 있습니다.Many useful validation attributes can be found in the System.ComponentModel.DataAnnotations namespace.

제공되는 기본 제공 특성보다 더 많은 기능이 필요한 인스턴스가 있을 수 있습니다.There may be instances where you need more features than built-in attributes provide. 이 경우에 ValidationAttribute에서 파생하거나 IValidatableObject를 구현하도록 모델을 변경하여 사용자 지정 유효성 검사 특성을 만들 수 있습니다.For those times, you can create custom validation attributes by deriving from ValidationAttribute or changing your model to implement IValidatableObject.

필수 특성 사용에 대한 참고Notes on the use of the Required attribute

nullable 형식이 아닌 값 형식(decimal, int, float,DateTime)은 기본적으로 필요하며 Required 특성은 필요하지 않습니다.Non-nullable value types (such as decimal, int, float, and DateTime) are inherently required and don't need the Required attribute. 앱은 Required으로 표시된 null이 아닌 형식에 서버 쪽 유효성 검사를 수행하지 않습니다.The app performs no server-side validation checks for non-nullable types that are marked Required.

유효성 검사 및 유효성 검사 특성과 관련되지 않는 MVC 모델 바인딩은 null이 아닌 형식에 누락 값 또는 공백을 포함하는 형식 필드 전송을 거부합니다.MVC model binding, which isn't concerned with validation and validation attributes, rejects a form field submission containing a missing value or whitespace for a non-nullable type. 대상 속성에 BindRequired 특성이 없는 경우에 모델 바인딩은 null이 아닌 형식에 대한 누락 데이터를 무시합니다. 여기서 들어오는 형식 데이터에서 형식 필드는 비어 있습니다.In the absence of a BindRequired attribute on the target property, model binding ignores missing data for non-nullable types, where the form field is absent from the incoming form data.

BindRequired 특성(특성을 포함한 모델 바인딩 동작 사용자 지정 참조)은 형식 데이터를 완료하는 데 유용합니다.The BindRequired attribute (also see Customize model binding behavior with attributes) is useful to ensure form data is complete. 속성에 적용하는 경우 모델 바인딩 시스템에는 해당 속성에 대한 값이 필요합니다.When applied to a property, the model binding system requires a value for that property. 형식에 적용하는 경우 모델 바인딩 시스템에는 해당 형식의 모든 속성에 대한 값이 필요합니다.When applied to a type, the model binding system requires values for all of the properties of that type.

Nullable<T > 형식(예: decimal? 또는 System.Nullable<decimal>)을 사용하고 Required으로 표시하는 경우 속성이 표준 null 형식인 것처럼 서버 쪽 유효성 검사가 수행됩니다(예: string).When you use a Nullable<T> type (for example, decimal? or System.Nullable<decimal>) and mark it Required, a server-side validation check is performed as if the property were a standard nullable type (for example, a string).

클라이언트 쪽 유효성 검사에는 Required로 표시한 모델 속성에 해당하는 형식 필드에 대한 값 및 Required로 표시하지 않은 null이 아닌 형식 속성에 대한 값이 필요합니다.Client-side validation requires a value for a form field that corresponds to a model property that you've marked Required and for a non-nullable type property that you haven't marked Required. Required는 클라이언트 쪽 유효성 검사 오류 메시지를 제어하는 데 사용할 수 있습니다.Required can be used to control the client-side validation error message.

모델 상태Model State

모델 상태는 제출된 HTML 형식 값으로 유효성 검사 오류를 나타냅니다.Model state represents validation errors in submitted HTML form values.

MVC는오류의 최대 수(기본적으로 200개)에 도달할 때까지 필드를 계속 유효성 검사합니다.MVC will continue validating fields until reaches the maximum number of errors (200 by default). Startup.cs 파일의 ConfigureServices 메서드에 다음 코드를 삽입하여 이 번호를 구성할 수 있습니다.You can configure this number by inserting the following code into the ConfigureServices method in the Startup.cs file:

services.AddMvc(options => options.MaxModelValidationErrors = 50);

모델 상태 오류 처리Handling Model State Errors

모델 유효성 검사는 각 컨트롤러 작업을 호출하기 전에 발생하며, ModelState.IsValid를 검사하고 적절하게 반응하는 것은 작업 메서드의 책임입니다.Model validation occurs prior to each controller action being invoked, and it's the action method's responsibility to inspect ModelState.IsValid and react appropriately. 대부분의 경우 적합한 반응은 이상적으로 모델 유효성 검사에 실패한 이유를 자세히 보여주는 오류 응답을 반환하는 것입니다.In many cases, the appropriate reaction is to return an error response, ideally detailing the reason why model validation failed.

필터가 이러한 정책을 구현하기에 적절한 경우에 일부 앱은 모델 유효성 검사 오류를 처리하는 표준 규칙을 따르도록 선택합니다.Some apps will choose to follow a standard convention for dealing with model validation errors, in which case a filter may be an appropriate place to implement such a policy. 유효한 모델 및 잘못된 모델 상태일 때 작업 동작 방식을 테스트해야 합니다.You should test how your actions behave with valid and invalid model states.

수동 유효성 검사Manual validation

모델 바인딩 및 유효성 검사가 완료되면 일부를 반복하는 것이 좋습니다.After model binding and validation are complete, you may want to repeat parts of it. 예를 들어 사용자는 정수가 필요한 필드에 텍스트를 입력하거나 모델의 속성에 대한 값을 계산해야 할 수 있습니다.For example, a user may have entered text in a field expecting an integer, or you may need to compute a value for a model's property.

유효성 검사를 수동으로 실행해야 합니다.You may need to run validation manually. 이렇게 하려면 다음과 같이 TryValidateModel 메서드를 호출합니다.To do so, call the TryValidateModel method, as shown here:

TryValidateModel(movie);

사용자 지정 유효성 검사Custom validation

유효성 검사 특성은 대부분의 유효성 검사 요구 사항에 적용됩니다.Validation attributes work for most validation needs. 그러나 일부 유효성 검사 규칙은 비즈니스에 따라 다릅니다.However, some validation rules are specific to your business. 규칙은 필드가 필요하거나 값의 범위를 준수하는지 확인하는 등 일반적인 데이터 유효성 검사 기술이 아닐 수 있습니다.Your rules might not be common data validation techniques such as ensuring a field is required or that it conforms to a range of values. 이러한 시나리오에서 사용자 지정 유효성 검사 특성을 사용하는 것이 좋습니다.For these scenarios, custom validation attributes are a great solution. MVC에서 고유한 사용자 지정 유효성 검사 특성을 쉽게 만들 수 있습니다.Creating your own custom validation attributes in MVC is easy. ValidationAttribute에서 상속하고, IsValid 메서드를 재정의합니다.Just inherit from the ValidationAttribute, and override the IsValid method. IsValid 메서드는 value라는 개체 및 validationContext라는 ValidationContext 개체 등 두 개의 매개 변수를 허용합니다.The IsValid method accepts two parameters, the first is an object named value and the second is a ValidationContext object named validationContext. 은 사용자 지정 유효성 검사기의 유효성을 검사하는 필드의 실제 값을 나타냅니다.Value refers to the actual value from the field that your custom validator is validating.

다음 샘플에서 비즈니스 규칙에 따르면 사용자가 1960년 이후에 출시된 영화에 대해 장르를 클래식으로 설정하지 않을 수 있습니다.In the following sample, a business rule states that users may not set the genre to Classic for a movie released after 1960. [ClassicMovie] 특성은 장르를 먼저 확인하고, 클래식인 경우 출시 날짜를 확인하여 1960년보다 이후인지를 확인합니다.The [ClassicMovie] attribute checks the genre first, and if it's a classic, then it checks the release date to see that it's later than 1960. 1960년 이후에 출시되었다면 유효성 검사에 실패합니다.If it's released after 1960, validation fails. 특성은 데이터 유효성을 검사하는 데 사용할 수 있는 연도를 나타내는 정수 매개 변수를 허용합니다.The attribute accepts an integer parameter representing the year that you can use to validate data. 다음과 같이 특성의 생성자에서 매개 변수의 값을 캡처할 수 있습니다.You can capture the value of the parameter in the attribute's constructor, as shown here:

public class ClassicMovieAttribute : ValidationAttribute, IClientModelValidator
{
    private int _year;

    public ClassicMovieAttribute(int Year)
    {
        _year = Year;
    }

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        Movie movie = (Movie)validationContext.ObjectInstance;

        if (movie.Genre == Genre.Classic && movie.ReleaseDate.Year > _year)
        {
            return new ValidationResult(GetErrorMessage());
        }

        return ValidationResult.Success;
    }

위의 movie 변수는 유효성을 검사할 형식 전송의 데이터를 포함하는 Movie 개체를 나타냅니다.The movie variable above represents a Movie object that contains the data from the form submission to validate. 이 경우에 유효성 검사 코드는 규칙에 따라 ClassicMovieAttribute 클래스의 IsValid 메서드에서 날짜 및 장르를 확인합니다.In this case, the validation code checks the date and genre in the IsValid method of the ClassicMovieAttribute class as per the rules. 유효성 검사에 성공하면 IsValidValidationResult.Success 코드를 반환하고, 유효성 검사에 실패하면 오류 메시지와 함께 ValidationResult 코드를 반환합니다.Upon successful validation IsValid returns a ValidationResult.Success code, and when validation fails, a ValidationResult with an error message. 사용자가 Genre 필드를 수정하고 형식을 제출하는 경우 ClassicMovieAttributeIsValid 메서드는 영화가 클래식인지 확인합니다.When a user modifies the Genre field and submits the form, the IsValid method of the ClassicMovieAttribute will verify whether the movie is a classic. 기본 제공 특성과 마찬가지로 ClassicMovieAttributeReleaseDate와 같은 속성에 적용하여 앞의 코드 샘플에 표시된 대로 유효성 검사를 진행합니다.Like any built-in attribute, apply the ClassicMovieAttribute to a property such as ReleaseDate to ensure validation happens, as shown in the previous code sample. 이 예제가 Movie 형식에서만 작동하므로 더 나은 옵션은 다음 단락에 표시된 대로 IValidatableObject를 사용하는 것입니다.Since the example works only with Movie types, a better option is to use IValidatableObject as shown in the following paragraph.

또는 IValidatableObject 인터페이스에서 Validate 메서드를 구현하여 모델에서 이 동일한 코드를 배치할 수 있습니다.Alternatively, this same code could be placed in the model by implementing the Validate method on the IValidatableObject interface. 사용자 지정 유효성 검사 특성이 개별 속성 유효성 검사에서 잘 작동하는 반면 IValidatableObject를 구현하는 작업은 다음과 같이 클래스 수준 유효성 검사를 구현하는 데 사용될 수 있습니다.While custom validation attributes work well for validating individual properties, implementing IValidatableObject can be used to implement class-level validation as seen here.

public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
    if (Genre == Genre.Classic && ReleaseDate.Year > _classicYear)
    {
        yield return new ValidationResult(
            $"Classic movies must have a release year earlier than {_classicYear}.",
            new[] { "ReleaseDate" });
    }
}

클라이언트 쪽 유효성 검사Client side validation

클라이언트 쪽 유효성 검사는 사용자에게 매우 편리합니다.Client side validation is a great convenience for users. 그렇지 않은 경우 서버에 대한 왕복을 기다리는 데 드는 시간을 절약할 수 있습니다.It saves time they would otherwise spend waiting for a round trip to the server. 비즈니스 용어로 몇 초를 매일 수백 번 반복하게 되면 많은 시간과 비용, 노력이 추가됩니다.In business terms, even a few fractions of seconds multiplied hundreds of times each day adds up to be a lot of time, expense, and frustration. 간단하고 즉각적인 유효성 검사를 사용하면 사용자는 보다 효율적으로 작업하고 더 좋은 품질의 입력 및 출력을 생성할 수 있습니다.Straightforward and immediate validation enables users to work more efficiently and produce better quality input and output.

다음에 표시된 대로 사용할 클라이언트 쪽 유효성 검사 대신 적절한 JavaScript 스크립트 참조를 사용하는 보기가 있어야 합니다.You must have a view with the proper JavaScript script references in place for client side validation to work as you see here.

<script src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-2.2.0.min.js"></script>
<script src="https://ajax.aspnetcdn.com/ajax/jquery.validate/1.16.0/jquery.validate.min.js"></script>
<script src="https://ajax.aspnetcdn.com/ajax/jquery.validation.unobtrusive/3.2.6/jquery.validate.unobtrusive.min.js"></script>

jQuery 비간섭 유효성 검사 스크립트는 널리 사용되는 jQuery 유효성 검사 플러그 인에 기반한 사용자 지정 Microsoft 프런트 엔드 라이브러리입니다.The jQuery Unobtrusive Validation script is a custom Microsoft front-end library that builds on the popular jQuery Validate plugin. jQuery 비간섭 유효성 검사를 사용하지 않고 두 위치(모델 속성에 대한 서버 쪽 유효성 검사 특성에서 한 번 및 클라이언트 쪽 스크립트에서 다시 한 번)에서 동일한 유효성 검사 논리를 코딩해야 합니다. (jQuery 유효성 검사의 validate() 메서드에 대한 예제는 복잡함을 보여줍니다.)Without jQuery Unobtrusive Validation, you would have to code the same validation logic in two places: once in the server side validation attributes on model properties, and then again in client side scripts (the examples for jQuery Validate's validate() method shows how complex this could become). 대신 MVC의 태그 도우미HTML 도우미는 모델 속성의 유효성 검사 특성 및 형식 메타데이터를 사용하여 유효성 검사가 필요한 형식 요소에서 HTML 5 데이터 특성을 렌더링할 수 있습니다.Instead, MVC's Tag Helpers and HTML helpers are able to use the validation attributes and type metadata from model properties to render HTML 5 data- attributes in the form elements that need validation. MVC에서는 기본 제공 및 사용자 지정 특성에 대한 data- 특성을 생성합니다.MVC generates the data- attributes for both built-in and custom attributes. jQuery 비간섭 유효성 검사는 data- 특성을 구문 분석한 다음, jQuery 유효성 검사에 대한 논리를 전달하여 효과적으로 서버 쪽 유효성 검사 논리를 클라이언트에 "복사"합니다.jQuery Unobtrusive Validation then parses thes data- attributes and passes the logic to jQuery Validate, effectively "copying" the server side validation logic to the client. 다음과 같이 관련 태그 도우미를 사용하여 클라이언트에서 유효성 검사 오류를 표시할 수 있습니다.You can display validation errors on the client using the relevant tag helpers as shown here:

<div class="form-group">
    <label asp-for="ReleaseDate" class="col-md-2 control-label"></label>
    <div class="col-md-10">
        <input asp-for="ReleaseDate" class="form-control" />
        <span asp-validation-for="ReleaseDate" class="text-danger"></span>
    </div>
</div>

위의 태그 도우미는 아래의 HTML을 렌더링합니다.The tag helpers above render the HTML below. HTML의 data- 특성 출력은 ReleaseDate 속성에 대한 유효성 검사 특성에 해당합니다.Notice that the data- attributes in the HTML output correspond to the validation attributes for the ReleaseDate property. 아래의 data-val-required 특성은 사용자가 릴리스 날짜 필드를 입력하지 않았음을 표시하는 오류 메시지를 포함합니다.The data-val-required attribute below contains an error message to display if the user doesn't fill in the release date field. jQuery 비간섭 유효성 검사는 jQuery 유효성 검사 required() 메서드에 이 값을 전달합니다. 그러면**<span>** 요소와 함께 해당 메시지를 표시합니다.jQuery Unobtrusive Validation passes this value to the jQuery Validate required() method, which then displays that message in the accompanying <span> element.

<form action="/Movies/Create" method="post">
    <div class="form-horizontal">
        <h4>Movie</h4>
        <div class="text-danger"></div>
        <div class="form-group">
            <label class="col-md-2 control-label" for="ReleaseDate">ReleaseDate</label>
            <div class="col-md-10">
                <input class="form-control" type="datetime"
                data-val="true" data-val-required="The ReleaseDate field is required."
                id="ReleaseDate" name="ReleaseDate" value="" />
                <span class="text-danger field-validation-valid"
                data-valmsg-for="ReleaseDate" data-valmsg-replace="true"></span>
            </div>
        </div>
    </div>
</form>

클라이언트 쪽 유효성 검사는 형식이 유효할 때까지 전송을 방지합니다.Client-side validation prevents submission until the form is valid. 제출 단추는 형식을 전송하거나 오류 메시지를 표시하는 JavaScript를 실행합니다.The Submit button runs JavaScript that either submits the form or displays error messages.

MVC는 속성의 .NET 데이터 형식에 따라 형식 특성 값을 결정하고 [DataType] 특성을 사용하여 재정의할 수 있습니다.MVC determines type attribute values based on the .NET data type of a property, possibly overridden using [DataType] attributes. 기본 [DataType] 특성은 실제 서버 쪽 유효성 검사를 수행하지 않습니다.The base [DataType] attribute does no real server-side validation. 브라우저는 고유한 오류 메시지를 선택하고 원하는 대로 해당 오류를 표시하지만 jQuery 유효성 검사 비간섭 패키지는 이 메시지를 재정의하고 다른 메시지와 일관되게 표시할 수 있습니다.Browsers choose their own error messages and display those errors as they wish, however the jQuery Validation Unobtrusive package can override the messages and display them consistently with others. 사용자가 [EmailAddress]와 같은 [DataType] 하위 클래스를 적용할 때 가장 분명하게 발생합니다.This happens most obviously when users apply [DataType] subclasses such as [EmailAddress].

동적 형식에 유효성 검사 추가Add Validation to Dynamic Forms

페이지가 처음 로드될 때 jQuery 비간섭 유효성 검사가 유효성 검사 논리 및 매개 변수를 jQuery 유효성 검사에 전달하기 때문에 동적으로 생성된 형식은 유효성 검사를 자동으로 표시하지 않습니다.Because jQuery Unobtrusive Validation passes validation logic and parameters to jQuery Validate when the page first loads, dynamically generated forms won't automatically exhibit validation. 대신 jQuery 비간섭 유효성 검사에서 동적 폼을 만든 후에 즉시 구문 분석하도록 지시합니다.Instead, you must tell jQuery Unobtrusive Validation to parse the dynamic form immediately after creating it. 예를 들어 아래 코드에서는 AJAX를 통해 추가된 형식에서 클라이언트 쪽 유효성 검사를 설정할 수 있는 방법을 보여줍니다.For example, the code below shows how you might set up client side validation on a form added via AJAX.

$.get({
    url: "https://url/that/returns/a/form",
    dataType: "html",
    error: function(jqXHR, textStatus, errorThrown) {
        alert(textStatus + ": Couldn't add form. " + errorThrown);
    },
    success: function(newFormHTML) {
        var container = document.getElementById("form-container");
        container.insertAdjacentHTML("beforeend", newFormHTML);
        var forms = container.getElementsByTagName("form");
        var newForm = forms[forms.length - 1];
        $.validator.unobtrusive.parse(newForm);
    }
})

$.validator.unobtrusive.parse() 메서드는 하나의 인수에 대해 jQuery 선택기를 허용합니다.The $.validator.unobtrusive.parse() method accepts a jQuery selector for its one argument. 이 메서드는 jQuery 비간섭 유효성 검사에서 해당 선택기 내에 있는 형식의 data- 특성을 구문 분석하도록 지시합니다.This method tells jQuery Unobtrusive Validation to parse the data- attributes of forms within that selector. 이러한 특성의 값은 jQuery 유효성 검사 플러그 인에 전달되므로 형식은 원하는 클라이언트 쪽 유효성 검사 규칙을 나타냅니다.The values of those attributes are then passed to the jQuery Validate plugin so that the form exhibits the desired client side validation rules.

동적 컨트롤에 유효성 검사 추가Add Validation to Dynamic Controls

<input/><select/> 등의 개별 컨트롤이 동적으로 생성될 경우 형식에 대한 유효성 검사 규칙을 업데이트할 수도 있습니다.You can also update the validation rules on a form when individual controls, such as <input/>s and <select/>s, are dynamically generated. 주변 형식이 이미 구문 분석되고 업데이트되지 않았기 때문에 이러한 요소에 대한 선택기를 parse() 메서드로 직접 전달할 수 없습니다.You cannot pass selectors for these elements to the parse() method directly because the surrounding form has already been parsed and won't update. 대신 먼저 기존 유효성 검사 데이터를 제거한 다음, 아래와 같이 전체 형식을 다시 구문 분석합니다.Instead, you first remove the existing validation data, then reparse the entire form, as shown below:

$.get({
    url: "https://url/that/returns/a/control",
    dataType: "html",
    error: function(jqXHR, textStatus, errorThrown) {
        alert(textStatus + ": Couldn't add control. " + errorThrown);
    },
    success: function(newInputHTML) {
        var form = document.getElementById("my-form");
        form.insertAdjacentHTML("beforeend", newInputHTML);
        $(form).removeData("validator")    // Added by jQuery Validate
               .removeData("unobtrusiveValidation");   // Added by jQuery Unobtrusive Validation
        $.validator.unobtrusive.parse(form);
    }
})

IClientModelValidatorIClientModelValidator

사용자는 사용자 지정 특성에 대한 클라이언트 쪽 논리를 만들 수 있으며, jquery 유효성 검사에 어댑터를 만드는 비간섭 유효성 검사는 클라이언트에서 유효성 검사 중에 자동으로 실행합니다.You may create client side logic for your custom attribute, and unobtrusive validation which creates an adapter to jquery validation will execute it on the client for you automatically as part of validation. 첫 번째 단계는 다음과 같이 IClientModelValidator 인터페이스를 구현하여 추가할 데이터 특성을 제어하는 것입니다.The first step is to control what data- attributes are added by implementing the IClientModelValidator interface as shown here:

public void AddValidation(ClientModelValidationContext context)
{
    if (context == null)
    {
        throw new ArgumentNullException(nameof(context));
    }

    MergeAttribute(context.Attributes, "data-val", "true");
    MergeAttribute(context.Attributes, "data-val-classicmovie", GetErrorMessage());

    var year = _year.ToString(CultureInfo.InvariantCulture);
    MergeAttribute(context.Attributes, "data-val-classicmovie-year", year);
}

이 인터페이스를 구현하는 특성은 생성된 필드에 HTML 특성을 추가할 수 있습니다.Attributes that implement this interface can add HTML attributes to generated fields. ReleaseDate 요소에 대한 출력을 검사하면 이전 예제와 비슷한 HTML을 표시합니다. 단지 이제는 data-val-classicmovie 특성이 IClientModelValidator라는 AddValidation 메서드에서 정의됩니다.Examining the output for the ReleaseDate element reveals HTML that's similar to the previous example, except now there's a data-val-classicmovie attribute that was defined in the AddValidation method of IClientModelValidator.

<input class="form-control" type="datetime"
    data-val="true"
    data-val-classicmovie="Classic movies must have a release year earlier than 1960."
    data-val-classicmovie-year="1960"
    data-val-required="The ReleaseDate field is required."
    id="ReleaseDate" name="ReleaseDate" value="" />

비간섭 유효성 검사는 data- 특성에서 데이터를 사용하여 오류 메시지를 표시합니다.Unobtrusive validation uses the data in the data- attributes to display error messages. 그러나 jQuery는 jQuery의 validator 개체에 추가될 때까지 규칙 또는 메시지를 인식하지 못합니다.However, jQuery doesn't know about rules or messages until you add them to jQuery's validator object. 아래 예제에서 jQuery validator 개체에 대한 사용자 지정 클라이언트 유효성 검사 코드가 포함된 classicmovie라는 메서드를 추가합니다.This is shown in the example below that adds a method named classicmovie containing custom client validation code to the jQuery validator object. unobtrusive.adapters.add 메서드에 대한 설명은 여기에서 확인할 수 있습니다.An explanations of the unobtrusive.adapters.add method can be found here

$(function () {
    $.validator.addMethod('classicmovie',
        function (value, element, params) {
            // Get element value. Classic genre has value '0'.
            var genre = $(params[0]).val(),
                year = params[1],
                date = new Date(value);
            if (genre && genre.length > 0 && genre[0] === '0') {
                // Since this is a classic movie, invalid if release date is after given year.
                return date.getFullYear() <= year;
            }

            return true;
        });

    $.validator.unobtrusive.adapters.add('classicmovie',
        ['year'],
        function (options) {
            var element = $(options.form).find('select#Genre')[0];
            options.rules['classicmovie'] = [element, parseInt(options.params['year'])];
            options.messages['classicmovie'] = options.message;
        });
});

이제 jQuery에는 유효성 검사 코드가 false를 반환하는 경우 표시할 오류 메시지뿐만 아니라 사용자 지정 JavaScript 유효성 검사를 실행하는 정보도 포함됩니다.Now jQuery has the information to execute the custom JavaScript validation as well as the error message to display if that validation code returns false.

원격 유효성 검사Remote validation

원격 유효성 검사는 서버의 데이터에 대한 클라이언트의 데이터 유효성을 검사해야 할 경우에 사용할 수 있는 유용한 기능입니다.Remote validation is a great feature to use when you need to validate data on the client against data on the server. 예를 들어 앱은 이메일 또는 사용자 이름을 이미 사용 중인지 확인해야 하고, 이를 위해 많은 양의 데이터를 쿼리해야 합니다.For example, your app may need to verify whether an email or user name is already in use, and it must query a large amount of data to do so. 하나 이상의 필드에 대한 유효성을 검사하는 대규모 데이터 집합을 다운로드하면 너무 많은 리소스를 소비하게 됩니다.Downloading large sets of data for validating one or a few fields consumes too many resources. 또한 중요한 정보를 노출할 수 있습니다.It may also expose sensitive information. 대안은 필드의 유효성을 검사하는 왕복 요청을 수행하는 것입니다.An alternative is to make a round-trip request to validate a field.

2단계 프로세스에서 원격 유효성 검사를 구현할 수 있습니다.You can implement remote validation in a two step process. 먼저 [Remote] 특성을 사용하여 모델을 주석으로 처리해야 합니다.First, you must annotate your model with the [Remote] attribute. [Remote] 특성은 클라이언트 쪽 JavaScript를 적절한 코드를 호출하는 데 사용할 수 있는 여러 오버로드를 허용합니다.The [Remote] attribute accepts multiple overloads you can use to direct client side JavaScript to the appropriate code to call. 다음 예제에서는 Users 컨트롤러의 VerifyEmail 작업 메서드를 가리킵니다.The example below points to the VerifyEmail action method of the Users controller.

[Remote(action: "VerifyEmail", controller: "Users")]
public string Email { get; set; }

두 번째 단계는 [Remote] 특성에 정의된 대로 해당 작업 메서드에서 유효성 검사 코드를 지정하는 것입니다.The second step is putting the validation code in the corresponding action method as defined in the [Remote] attribute. jQuery 유효성 검사 remote() 메서드 설명서에 따라:According to the jQuery Validate remote() method documentation:

서버 쪽 응답은 기본 오류 메시지를 사용하며 유효한 요소에 대해 "true"인 JSON 문자열이며 잘못된 요소에 대해 "false", undefined 또는 null일 수 있습니다.The serverside response must be a JSON string that must be "true" for valid elements, and can be "false", undefined, or null for invalid elements, using the default error message. 서버 쪽 응답이 문자열인 경우(예:If the serverside response is a string, eg. "That name is already taken, try peter123 instead") 이 문자열은 기본값 대신 사용자 지정 오류 메시지로 표시됩니다."That name is already taken, try peter123 instead", this string will be displayed as a custom error message in place of the default.

VerifyEmail() 메서드의 정의는 아래 표시된 대로 이러한 규칙을 따릅니다.The definition of the VerifyEmail() method follows these rules, as shown below. 이메일을 사용한 경우 유효성 검사 오류 메시지가 반환됩니다. 또는 이메일이 무료인 경우 true이며 JsonResult 개체에서 결과를 래핑합니다.It returns a validation error message if the email is taken, or true if the email is free, and wraps the result in a JsonResult object. 클라이언트 쪽은 반환 값을 계속 사용하거나 필요한 경우 오류를 표시할 수 있습니다.The client side can then use the returned value to proceed or display the error if needed.

[AcceptVerbs("Get", "Post")]
public IActionResult VerifyEmail(string email)
{
    if (!_userRepository.VerifyEmail(email))
    {
        return Json($"Email {email} is already in use.");
    }

    return Json(true);
}

이제 사용자가 이메일을 입력하면 보기의 JavaScript에서는 해당 이메일을 사용하는지 확인하기 위해 원격 호출을 수행하고, 해당하는 경우 오류 메시지를 표시합니다.Now when users enter an email, JavaScript in the view makes a remote call to see if that email has been taken and, if so, displays the error message. 그렇지 않으면 사용자는 일반적으로 형식을 제출할 수 있습니다.Otherwise, the user can submit the form as usual.

[Remote] 특성의 AdditionalFields 속성은 서버에서 데이터에 대한 필드 조합의 유효성을 검사하는 데 유용합니다.The AdditionalFields property of the [Remote] attribute is useful for validating combinations of fields against data on the server. 예를 들어 위의 User 모델에 FirstNameLastName라는 두 개의 추가 속성이 있는 경우 기존 사용자가 해당 쌍의 이름을 사용하지 않는지 확인하는 것이 좋습니다.For example, if the User model from above had two additional properties called FirstName and LastName, you might want to verify that no existing users already have that pair of names. 다음 코드와 같이 새로운 속성을 정의합니다.You define the new properties as shown in the following code:

[Remote(action: "VerifyName", controller: "Users", AdditionalFields = nameof(LastName))]
public string FirstName { get; set; }
[Remote(action: "VerifyName", controller: "Users", AdditionalFields = nameof(FirstName))]
public string LastName { get; set; }

AdditionalFields는 명시적으로 "FirstName""LastName" 문자열로 설정될 수 있지만 다음과 같은 nameof 연산자를 사용하면 나중에 리팩터링을 간소화할 수 있습니다.AdditionalFields could've been set explicitly to the strings "FirstName" and "LastName", but using the nameof operator like this simplifies later refactoring. 유효성 검사를 수행하는 작업 메서드는 FirstName 값 및 LastName 값에 대해 하나씩 두 개의 인수를 허용해야 합니다.The action method to perform the validation must then accept two arguments, one for the value of FirstName and one for the value of LastName.

[AcceptVerbs("Get", "Post")]
public IActionResult VerifyName(string firstName, string lastName)
{
    if (!_userRepository.VerifyName(firstName, lastName))
    {
        return Json(data: $"A user named {firstName} {lastName} already exists.");
    }

    return Json(data: true);
}

이제 사용자가 이름과 성을 입력할 때 JavaScript:Now when users enter a first and last name, JavaScript:

  • 해당 쌍의 이름을 사용 중인지 확인하기 위해 원격 호출을 수행합니다.Makes a remote call to see if that pair of names has been taken.
  • 쌍이 사용 중인 경우 오류 메시지가 표시됩니다.If the pair has been taken, an error message is displayed.
  • 그렇지 않은 경우 사용자는 형식을 전송할 수 있습니다.If not taken, the user can submit the form.

[Remote] 특성을 포함하는 두 개 이상의 추가 필드 유효성을 검사해야 하는 경우 쉼표로 구분된 목록으로 제공합니다.If you need to validate two or more additional fields with the [Remote] attribute, you provide them as a comma-delimited list. 예를 들어 MiddleName 특성을 메서드에 추가하고, 다음 코드에 표시된 대로 [Remote] 특성을 설정합니다.For example, to add a MiddleName property to the model, set the [Remote] attribute as shown in the following code:

[Remote(action: "VerifyName", controller: "Users", AdditionalFields = nameof(FirstName) + "," + nameof(LastName))]
public string MiddleName { get; set; }

모든 특성 인수와 같은 AdditionalFields은 상수 식이어야 합니다.AdditionalFields, like all attribute arguments, must be a constant expression. 따라서 보간된 문자열을 사용하거나 string.Join()를 호출하여 AdditionalFields을 초기화하지 않아야 합니다.Therefore, you must not use an interpolated string or call string.Join() to initialize AdditionalFields. [Remote] 특성에 추가한 모든 추가 필드의 경우 해당하는 컨트롤러 작업 메서드에 다른 인수를 추가해야 합니다.For every additional field that you add to the [Remote] attribute, you must add another argument to the corresponding controller action method.