8

Using MVC 5 I need to localize an ErrorMessage for a DataAnnotation attributes. I receive the following error

ERROR

An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type

In model

[Compare("Password", ErrorMessage = Resources.Account_Register_ConfirmPasswordErrorMessage)]
public string ConfirmPassword { get; set; }

Any idea how to fix it?

Erik Philips
  • 53,428
  • 11
  • 128
  • 150
GibboK
  • 71,848
  • 143
  • 435
  • 658

3 Answers3

13

You need to use ErrorMessageResourceName and ErrorMessageResourceType properties.

For example like this:

[Compare("Password", ErrorMessageResourceName = "ConfirmPasswordErrorMessage",
  ErrorMessageResourceType=typeof(<<type_of_your_resoruce_class>>)]
public string ConfirmPassword { get; set; }

Hope this helps!

Regards, Uros

Shimmy Weitzhandler
  • 101,809
  • 122
  • 424
  • 632
Uroš Goljat
  • 1,806
  • 14
  • 15
  • 1
    This may work, but according to the ASP.NET CORE documentation here: https://docs.asp.net/en/latest/fundamentals/localization.html#dataannotations-localization, we should be able to localize these DataAnnotation error messages without specifying resource name and type. Whatever I try, however, I do not mange to get this working. Can someone share some experience on that? – Vladislav Sep 01 '16 at 12:47
1

You don't need anything, just create your resource file in right place.

For example Resources > ViewModels > LoginVm.ka-GE.resx (Georgian culture-info)

in LoginVm:
[Required(ErrorMessage = "UserName is Required")]

and in LoginVm.ka-GE.resx just add

UserName is Required > სახელი არის აუცილებელი < (it's Georgian Language)

and all done.

Shimmy Weitzhandler
  • 101,809
  • 122
  • 424
  • 632
Jorjini
  • 25
  • 4
0

Here's a detailed explanation on how to do this:

You add appropriate culture resx files to conventional folders, and tell the DA engine to look through them:

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc()
        .AddDataAnnotationsLocalization(options => {
            options.DataAnnotationLocalizerProvider = (type, factory) =>
                factory.Create(typeof(SharedResource));
        });
}

So for this model:

public class RegisterViewModel
{
    [Required(ErrorMessage = "The Email field is required.")]
    [EmailAddress(ErrorMessage = "The Email field is not a valid email address.")]
    [Display(Name = "Email")]
    public string Email { get; set; }
}

You'd add a resx file in one of the following locations:

  • Resources/ViewModels.Account.RegisterViewModel.fr.resx
  • Resources/ViewModels/Account/RegisterViewModel.fr.resx

For non-ASP.NET environments such as WPF, WinForms or others, see this answer.

Shimmy Weitzhandler
  • 101,809
  • 122
  • 424
  • 632
  • 1
    You've mixed two things together. SharedResource registered in ConfigureServices works if you want to use one file across classe. Resources/ViewModels.Account.RegisterViewModel.fr.resx will work in case you want to have a separated translation for each class (ie. you can translate the same string differently in different models). – Vočko Aug 19 '20 at 05:45