Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to Localize validation message (DataAnnotationsValidator) in blazor server side

I am using blazor 3.1 in latest version of VS 2019.

So far, I am able to localize page labels (title, table fields etc.).

On the ListEmployee.razor page, I am able to localize table heading etc. On the AddEmplyeeValidation.razor page, I am able to localize form labels but I have a problem localizing the validation messages.

For validation message for the Employee.cs file, validation message are defined in the Resources/Data folder in files Data.Employee.resx and Data.Employee.ar.resx but this doesn't seem to work.

    using System.ComponentModel.DataAnnotations;

    namespace BlazorSPA1.Data
    {
        public class Employee
        {
            [MaxLength(50)]
            public string Id { get; set; }

            [Required (ErrorMessage ="Name is RRRequired")]
            [StringLength(20, ErrorMessage = "Name is too long.")]
            public string Name { get; set; }

            [Required]
            [StringLength(20)]
            public string Department { get; set; }
            [MaxLength(100)]
            public string Designation { get; set; }
            [MaxLength(100)]
            public string Company { get; set; }
            [MaxLength(100)]
            public string City { get; set; }
        }
    }

How can I load the validation messages from the resource files based on language for my AddEmployeForm?

    @page "/addemployeeValidation"
    @inject NavigationManager NavigationManager
    @inject IEmployeeService EmployeeService
    @inject IStringLocalizer<AddEmployeeValidation> L

    <h2>Create Employee</h2>
    <hr />
    <EditForm Model="@employee" OnValidSubmit="@CreateEmployee">
        <DataAnnotationsValidator />
        <ValidationSummary />
        <div class="row">
            <div class="col-md-8">
                <div class="form-group">
                    <label for="Name" class="control-label">@L["Name"]</label>
                    <input for="Name" class="form-control" @bind="@employee.Name" />
                    <ValidationMessage For="@(()=> employee.Name)" />
                </div>
                <div class="form-group">
                    <label for="Department" class="control-label">@L["Department"]</label>
                    <input for="Department" class="form-control" @bind="@employee.Department" />
                </div>
                <div class="form-group">
                    <label for="Designation" class="control-label">@L["Designation"]</label>
                    <input for="Designation" class="form-control" @bind="@employee.Designation" />
                </div>
                <div class="form-group">
                    <label for="Company" class="control-label">@L["Company"]</label>
                    <input for="Company" class="form-control" @bind="@employee.Company" />
                </div>
                <div class="form-group">
                    <label for="City" class="control-label">@L["City"]</label>
                    <input for="City" class="form-control" @bind="@employee.City" />
                </div>
            </div>
        </div>
        <div class="row">
            <div class="col-md-4">
                <div class="form-group">
                    <input type="submit" class="btn btn-primary" value="Save" />
                    <input type="button" class="btn" @onclick="@Cancel" value="Cancel" />
                </div>
            </div>
        </div>
    </EditForm>

    @code {

        Employee employee = new Employee();

        protected async Task CreateEmployee()
        {
            await EmployeeService.CreateEmployee(employee);
            NavigationManager.NavigateTo("listemployees");
        }


        void Cancel()
        {
            NavigationManager.NavigateTo("listemployees");
        }
    }   

I have read a few articles and tried few thing but nothing seems to be working.

Here is my Startup.cs code:

        services.AddServerSideBlazor(options => options.DetailedErrors = true);
        services.AddLocalization(options => options.ResourcesPath = "Resources");
        var supportedCultures = new List<CultureInfo> { new CultureInfo("en"), new CultureInfo("ar") };
        services.Configure<RequestLocalizationOptions>(options =>
        {
            options.DefaultRequestCulture = new Microsoft.AspNetCore.Localization.RequestCulture("en");
            options.SupportedUICultures = supportedCultures;
        });

I am using the following example for localization but it doesn't show how to localize error messages: https://www.c-sharpcorner.com/article/localization-in-blazor-server/

Folder structure image for reference:

enter image description here

Resource file example for English version in same way i have Arabic file also:

enter image description here

In the screenshot below, you will see field names are being pulled correctly from the Resource file but validation messages are not working and only display in English.

enter image description here

like image 887
Learning Avatar asked Jan 09 '20 08:01

Learning


2 Answers

Here is my solution for localizing data annotation error messages. I create two resource files, one for fields and another one for error messages.

  • DisplayNameResource for localizing fields
  • ErrorMessageResource for localizing error messages

enter image description here enter image description here enter image description here enter image description here

In view model class use Display attribute for localizing field name. To specify resource file use ResourceType property on Display attribute:

[Display(Name = "Address", ResourceType = typeof(DisplayNameResource))]

And on validation attributes use ErrorMessageResourceName and ErrorMessageResourceType to specify resource file:

[Required(ErrorMessageResourceName = "RequiredError", ErrorMessageResourceType = typeof(ErrorMessageResource))]

Here is full example:

public class SomeViewModel
{
    [Display(Name = "Address", ResourceType = typeof(DisplayNameResource))]
    [Required(ErrorMessageResourceName = "RequiredError", ErrorMessageResourceType = typeof(ErrorMessageResource))]
    [StringLength(256, ErrorMessageResourceName = "MaxLengthError", ErrorMessageResourceType = typeof(ErrorMessageResource))]
    public string Address { get; set; }

    [Display(Name = "Phone", ResourceType = typeof(DisplayNameResource))]
    [Required(ErrorMessageResourceName = "RequiredError", ErrorMessageResourceType = typeof(ErrorMessageResource))]
    [RegularExpression("^09([0-9]{9})$", ErrorMessageResourceName = "PhoneLengthError", ErrorMessageResourceType = typeof(ErrorMessageResource))]
    public string Phone { get; set; }

    [Display(Name = "Password", ResourceType = typeof(DisplayNameResource))]
    [Required(ErrorMessageResourceName = "RequiredError", ErrorMessageResourceType = typeof(ErrorMessageResource))]
    [StringLength(50, MinimumLength = 6, ErrorMessageResourceType = typeof(ErrorMessageResource), ErrorMessageResourceName = "MinxMaxLengthError")]
    public string Password { get; set; }

    [Display(Name = "ConfirmPassword", ResourceType = typeof(DisplayNameResource))]
    [Required(ErrorMessageResourceName = "RequiredError", ErrorMessageResourceType = typeof(ErrorMessageResource))]
    [StringLength(50, MinimumLength = 6, ErrorMessageResourceType = typeof(ErrorMessageResource), ErrorMessageResourceName = "MinxMaxLengthError")]
    [Compare("Password", ErrorMessageResourceName = "PasswordConfirmMisMatch", ErrorMessageResourceType = typeof(ErrorMessageResource))]
    public string ConfirmPassword { get; set; }
}

Error message for MaxLengthError is {0} cannot be longer than {1} character, so {0} will be replaced with localized filed name and {1} will be replaced with the 256 you specified on attribute [StringLength(256,...

like image 197
Mohsen Esmailpour Avatar answered Oct 09 '22 13:10

Mohsen Esmailpour


This has been asked before:

How to add ViewModel localization to Blazor?

I suggested that using FluentValidation would be a better approach. Here is a link to my Github repo that demonstrates how it could work:

https://github.com/conficient/BlazorValidationLocalization

like image 39
Quango Avatar answered Oct 09 '22 12:10

Quango