각 ASPNET 핵심 웹 API 프로젝트 요구사항 - 섹션 4 - 오류 메시지 재사용 및 현지화

본문에서, 나는 전역 이상 처리 중간부품을 통해 오류를 어떻게 처리하는지 토론했다.이 문서에서는 다음 두 가지 주제를 다룹니다.
  • 우선, 자원 파일을 통해 오류 메시지를 어떻게 다시 사용합니까
  • 오류 메시지를 지역화하는 방법
  • 나 같은 모국어가 영어가 아닌 사람에게는 기본 오류 메시지System.ComponentModel.DataAnnotations가 도움이 되지 않는다. 왜냐하면 우리는 우리의 언어로 메시지를 표시해야 하기 때문이다.
    만약 네가 영어 모국어라면, 이 글을 건너뛸 수 있지만, 코드 라이브러리의 하드코드 오류 메시지를 피하고 싶다면, 이 글은 매우 유용하다.
    .NET 개발자는 일반적으로 DataAnnotationsFluentValidation 속성을 사용하여 사용자의 입력을 검증한다.다음 코드를 고려하십시오.
    public class UserRegistrationViewModel
    {
        [Required(ErrorMessage = "فیلد نام اجباری میباشد")]
        [MaxLength(32, ErrorMessage = "طول فیلد نام حداکثر 32 باید باشد")]
        [MinLength(2, ErrorMessage = "حداقل طول وارد شده برای فیلد نام بایستی 2 کاراکتر باشد")]
        public string FirstName { get; set; }
    
        [Required(ErrorMessage = "فیلد نام خانوادگی اجباری میباشد")]
        [MaxLength(32, ErrorMessage = "طول فیلد نام خانوادگی حداکثر 32 باید باشد")]
        [MinLength(2, ErrorMessage = "حداقل طول وارد شده برای فیلد نام خانوادگی بایستی 2 کاراکتر باشد")]
        public string LastName { get; set; }
    
        [DataType(DataType.EmailAddress, ErrorMessage = "ایمیل وارد شده معتبر نمیباشد")]
        [Required(ErrorMessage = "فیلد ایمیل اجباری میباشد")]
        [MaxLength(128, ErrorMessage = "طول فیلد ایمیل حداکثر 32 باید باشد")]
        [CustomEmailAddress(ErrorMessage = "فرمت ایمیل وارد شده معبتر نیست")]
        public string Email { get; set; }
    }
    
    위 코드의 문제는 속성 이름만 다르지만 필수 메시지는 같다는 메시지를 모든 필수 속성에 복사/붙여넣어야 한다는 점입니다.
    فیلد نام اجباری میباشد
    فیلد نام خانوادگی اجباری میباشد
    فیلد ایمیل اجباری میباشد
    
    فیلد ... اجباری می‌باشد 손가락... field is required . 너는 페르시아어만 조금 배웠다😄
    우리는 자원 문서의 도움 아래 상술한 문제를 해결할 것이다.
    들어와.NET Core 3.0 이상에서는 리소스 파일을 사용하는 데 로컬화를 적용하는 새로운 방법이 사용됩니다.나는 IStringLocalizer<Resource>나 새로운 해결 방안을 현지화할 생각은 없다.NetCore3.0이 발표된 이유는 그것들이 너무 복잡해 보이기 때문이다. (적어도 나에게는)

    단계 1 - 로컬화에 필요한 의존항 추가

  • 개방식Startup.cs 등급 및 아래 코드:
  • services.AddControllers().AddDataAnnotationsLocalization();
    services.AddLocalization(options => options.ResourcesPath = "Resources");
    
    ResourcesPath는 자원 파일이 있는 응용 프로그램 루트 디렉터리의 상대적인 경로입니다.
  • 열기CoolWebApi.csproj 파일:
  • <PropertyGroup>
      <EmbeddedResourceUseDependentUponConvention>false</EmbeddedResourceUseDependentUponConvention>
    </PropertyGroup>
    

    The EmbeddedResourceUseDependentUponConvention property defines whether resource manifest file names are generated from type information in source files that are colocated with resource files. For example, if Form1.resx is in the same folder as Form1.cs, and EmbeddedResourceUseDependentUponConvention is set to true, the generated .resources file takes its name from the first type that's defined in Form1.cs. For example, if MyNamespace.Form1 is the first type defined in Form1.cs, the generated file name is MyNamespace.Form1.resources.


    2단계 - 리소스 파일 추가

  • 프로젝트의 루트에 새 폴더Resources를 추가합니다.
  • 두 개의 리소스 파일을 Resources 폴더DisplayNameResource.resxErrorMessageResource.resx에 추가
  • 리소스 파일을 열고 Access ModifierPublic로 변경합니다.

  • 단계 3 - 이름 및 오류 메시지 추가


    두 번째 섹션에서 DummyModel:
    public class DummyModel
    {
        public string FirstName { get; set; }
    
        public string LastName { get; set; }
    
        [JsonIgnore]
        public string FullName { get; set; }
    }
    
  • FirstNameLastName에 추가합니다.

  • 파일을 열고 다음 값을 추가합니다(예: 사이트 언어가 페르시아어인 경우 기본 언어로 오류 메시지를 추가할 수 있습니다).

  • 데이터 주석 속성을 에 추가DisplayNameResource.resx:
  • public class DummyModel
    {
        [Display(ResourceType = typeof(DisplayNameResource), Name = "FirstName")]
        [Required(ErrorMessageResourceType = typeof(ErrorMessageResource), ErrorMessageResourceName = "RequiredError")]
        [MaxLength(32, ErrorMessageResourceType = typeof(ErrorMessageResource), ErrorMessageResourceName = "MaxLengthError")]
        public string FirstName { get; set; }
    
        [Display(ResourceType = typeof(DisplayNameResource), Name = "FirstName")]
        [Required(ErrorMessageResourceType = typeof(ErrorMessageResource), ErrorMessageResourceName = "RequiredError")]
        [StringLength(32, MinimumLength = 3, ErrorMessageResourceType = typeof(ErrorMessageResource), ErrorMessageResourceName = "MaxLengthError")]
        public string LastName { get; set; }
    
        [JsonIgnore]
        public string FullName { get; set; }
    }
    
    어떻게 데이터 주석 속성 이외에 오류 메시지를 사용합니까?
    e-메일 등록 정보를 ErrorMessageResource.rex에 추가하고 단어가 포함된 e-메일을 금지합니다.
  • 다음 이름/값을 DummyModel에 추가합니다.
    이름: DummyModel값: dummy
  • e-메일 속성 확인ErrorMessageResource.rex:
  • public class DummyModel : IValidatableObject
    {
        [Display(ResourceType = typeof(DisplayNameResource), Name = "FirstName")]
        [Required(ErrorMessageResourceType = typeof(ErrorMessageResource), ErrorMessageResourceName = "RequiredError")]
        [MaxLength(32, ErrorMessageResourceType = typeof(ErrorMessageResource), ErrorMessageResourceName = "MaxLengthError")]
        public string FirstName { get; set; }
    
        [Display(ResourceType = typeof(DisplayNameResource), Name = "FirstName")]
        [Required(ErrorMessageResourceType = typeof(ErrorMessageResource), ErrorMessageResourceName = "RequiredError")]
        [MaxLength(32, MinimumLength = 3, ErrorMessageResourceType = typeof(ErrorMessageResource), ErrorMessageResourceName = "MaxLengthError")]
        public string LastName { get; set; }
    
        [Display(ResourceType = typeof(DisplayNameResource), Name = "Email")]
        [Required(ErrorMessageResourceType = typeof(ErrorMessageResource), ErrorMessageResourceName = "RequiredError")]
        [MaxLength(128, MinimumLength = 3, ErrorMessageResourceType = typeof(ErrorMessageResource), ErrorMessageResourceName = "MaxLengthError")]
        public string Email { get; set; }
    
        [JsonIgnore]
        public string FullName { get; set; }
    
        public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
        {
            if (Email.Contains("dummy"))
                yield return new ValidationResult(string.Format(
                    ErrorMessageResource.DummyIsForbidenError, 
                    DisplayNameResource.Email));
        }
    }
    
    또는 던지기DomainException:
    if (Email.Contains("dummy"))
        throw new DomainException(string.Format(
            ErrorMessageResource.DummyIsForbidenError, DisplayNameResource.Email));
    

    4단계 현지화


    이름과 오류 메시지를 로컬화하기 위해 다른 언어를 추가합니다.
  • 개방식DummyIsForbidenError 과정과 {0} cannot contains dummy word. 방법 중의 다음과 같은 문화:
  • var supportedCultures = new List<CultureInfo> { new CultureInfo("en"), new CultureInfo("fa") };
    services.Configure<RequestLocalizationOptions>(options =>
    {
        options.DefaultRequestCulture = new RequestCulture("fa");
        options.SupportedCultures = supportedCultures;
        options.SupportedUICultures = supportedCultures;
    });
    
  • 두 개의 리소스 파일IValidatableObjectStartup을 추가하고 같은 번역 이름/값을 추가합니다.


  • 클래스를 열고 ConfigureServices 방법에 DisplayNameResource.fa.resx 중간부품을 추가합니다.
  • app.UseRequestLocalization();
    
    DataAnnotations의 로컬화를 테스트할 때입니다. 그러나 테스트를 하기 전에 프로그램의 문화를 변경할 필요가 있습니다.다음과 같은 방법으로 애플리케이션 문화를 변화시킬 수 있습니다.
  • QueryStringRequestCultureProvider
  • CookiierRequestCultureProvider
  • AcceptLanguageHeaderRequestCultureProvider
    swagger를 사용하여 API를 테스트할 때 ErrorMessageResource.fa.resx 응용 프로그램 문화를 변경하는 방법을 보여 드리겠습니다.
  • 새 클래스StartupLocalization 폴더에 추가하고 다음 코드를 추가합니다.
  • public class SwaggerLanguageHeader : IOperationFilter
    {
        private readonly IServiceProvider _serviceProvider;
    
        public SwaggerLanguageHeader(IServiceProvider serviceProvider)
        {
            _serviceProvider = serviceProvider;
        }
    
        public void Apply(OpenApiOperation operation, OperationFilterContext context)
        {
            operation.Parameters ??= new List<OpenApiParameter>();
    
            operation.Parameters.Add(new OpenApiParameter
            {
                Name = "Accept-Language",
                Description = "Supported languages",
                In = ParameterLocation.Header,
                Required = false,
                Schema = new OpenApiSchema
                {
                    Type = "string",
                    Enum = (_serviceProvider
                            .GetService(typeof(IOptions<RequestLocalizationOptions>)) as IOptions<RequestLocalizationOptions>)?
                        .Value?
                        .SupportedCultures?.Select(c => new OpenApiString(c.TwoLetterISOLanguageName)).ToList<IOpenApiAny>(),
                }
            });
        }
    }
    
  • Configure 방법에서 필터를 거들먹거리며 등록하기:
  • services.AddSwaggerGen(options =>
    {
        **options.OperationFilter<SwaggerLanguageHeader>();**
        ...
    
    이제 애플리케이션을 실행하면 새로 추가된 드롭다운 입력이 표시됩니다. 두 값은 각각 AcceptLanguageHeaderRequestCultureProviderSwaggerLanguageHeader.cs입니다.

    잘못된 입력으로 post API를 테스트하고 언어 드롭다운 목록에서 Infrastructure\Swagger:

    이렇게😁.
  • 마지막이지만 가장 중요하지 않은 것은 어떻게 파라미터를 오류 메시지에 전달합니까?예를 들어 ConfigureService 속성에 대한 메시지를 작성하고 싶습니다.
  • [StringLength(32, MinimumLength = 3, ErrorMessageResourceType = typeof(ErrorMessageResource), ErrorMessageResourceName = "MaxLengthError")]
    public string FirstName { get; set; }
    
    en
  • 첫 번째 매개 변수 {0}는 속성명에 속합니다
  • {1}, {2}에서...왼쪽에서 오른쪽까지의 속성 매개 변수 창과 관련이 있습니다.fa, 매개 변수faStringLength, 매개 변수The minimum length of {0} is {2} characters and maximum length is {1} characters.StringLength
  • Github 에서 이 연습의 원본 코드를 찾을 수 있습니다.

    좋은 웹페이지 즐겨찾기