Back End/🌈 ASP.NET

ValidationAttribute

James Wetzel 2025. 6. 15. 16:27

내장된 유효성 검사 특성 외에 사용자 정의 유효성 검사 규칙을 추가하는 방법은 크게 두 가지가 있습니다.

  1. 사용자 정의 유효성 검사 특성(Custom Validation Attribute):
    • 가장 일반적인 방법이며, 단일 속성에 대한 유효성 검사를 정의할 때 [Required], [StringLength]처럼 속성 위에 어노테이션 형태로 붙여 사용할 수 있습니다. 재사용성이 높습니다.
    • ValidationAttribute 클래스를 상속받아 구현합니다.
  2. IValidatableObject 인터페이스 구현:
    • 모델(클래스) 수준의 유효성 검사를 정의할 때 사용합니다. 여러 속성의 값 조합에 따라 유효성 검사 결과가 달라지는 경우에 적합합니다. (예: 시작 날짜가 종료 날짜보다 빠르지 않아야 한다.)

NoReservedUsernameAttribute.cs

using System.ComponentModel.DataAnnotations; // ValidationAttribute를 상속받기 위해 필요

namespace MyWebApiWithAuth.ValidationAttributes // 적절한 네임스페이스로 변경
{
    // ValidationAttribute를 상속받아 사용자 정의 유효성 검사 특성을 만듭니다.
    public class NoReservedUsernameAttribute : ValidationAttribute
    {
        private readonly string[] _reservedWords; // 예약어 목록

        // 생성자: 특성 사용 시 예약어를 인자로 받을 수 있도록 합니다.
        // 예: [NoReservedUsername("admin", "root")]
        public NoReservedUsernameAttribute(params string[] reservedWords)
        {
            _reservedWords = reservedWords;
            // 기본 오류 메시지 설정 (ErrorMessage 속성으로 재정의 가능)
            ErrorMessage = "사용자 이름에 예약된 단어 ({0})가 포함될 수 없습니다.";
        }

        // 유효성 검사 로직을 구현하는 메서드
        // value: 유효성 검사를 수행할 속성의 값
        // validationContext: 유효성 검사에 대한 추가 정보 (예: 다른 속성 값 접근)
        protected override ValidationResult? IsValid(object? value, ValidationContext validationContext)
        {
            // 값이 null이거나 빈 문자열인 경우, [Required] 특성이 처리하므로 여기서는 유효한 것으로 간주
            if (value == null || string.IsNullOrWhiteSpace(value.ToString()))
            {
                return ValidationResult.Success; // 유효성 검사 성공
            }

            var username = value.ToString()!.ToLowerInvariant(); // 사용자 이름을 소문자로 변환

            // 예약어 목록을 순회하며 사용자 이름에 예약어가 포함되어 있는지 확인
            foreach (var reservedWord in _reservedWords)
            {
                if (username.Contains(reservedWord.ToLowerInvariant()))
                {
                    // 예약어가 발견되면 유효성 검사 실패
                    // FormatErrorMessage를 사용하여 {0} 플레이스홀더를 예약어로 대체
                    return new ValidationResult(string.Format(ErrorMessage!, reservedWord));
                }
            }

            // 모든 검사를 통과하면 유효성 검사 성공
            return ValidationResult.Success;
        }
    }
}

 

model

using System.ComponentModel.DataAnnotations;
using MyWebApiWithAuth.ValidationAttributes; // 사용자 정의 특성 네임스페이스 참조

namespace MyWebApiWithAuth.Models
{
    public class RegisterRequest
    {
        // --- 여기에 사용자 정의 유효성 검사 특성 적용 ---
        [NoReservedUsername("admin", "root", "system")] // "admin", "root", "system"이 포함된 사용자 이름 금지
        public string? Username { get; set; }
    }
}

 

controller

using Microsoft.AspNetCore.Mvc;
using MyWebApiWithAuth.Models;
using MyWebApiWithAuth.Services;
using MyWebApiWithAuth.ValidationAttributes; // (필요하다면 네임스페이스 추가, 직접 사용은 안 함)

namespace MyWebApiWithAuth.Controllers
{
    [ApiController]
    [Route("api/[controller]")]
    public class UsersController : ControllerBase
    {
        private readonly IUserService _userService;

        public UsersController(IUserService userService)
        {
            _userService = userService;
        }

        [HttpPost("register")]
        public async Task<IActionResult> Register([FromBody] RegisterRequest request)
        {
            // ModelState.IsValid는 사용자 정의 NoReservedUsername 특성도 함께 검사합니다.
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState); // 400 Bad Request
            }

            var registeredUser = await _userService.RegisterUserAsync(request);
            return CreatedAtAction(nameof(GetUserById), new { id = registeredUser.Id }, registeredUser);
        }

        // ... GetUserById 등의 다른 액션들은 생략
    }
}

 

 

내장된 유효성 검사

https://learn.microsoft.com/ko-kr/aspnet/core/mvc/models/validation?view=aspnetcore-9.0

 

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

ASP.NET Core MVC 및 Razor Pages의 모델 유효성 검사에 대해 알아봅니다.

learn.microsoft.com

 

728x90
반응형