65.9K
CodeProject is changing. Read more.
Home

Easy Model and Validation Localization in ASP.NET MVC3

starIconstarIconstarIconstarIconstarIcon

5.00/5 (1 vote)

Sep 13, 2011

LGPL3

1 min read

viewsIcon

16520

How to get clean and flexible model + validation localization in ASP.NET MVC3

If you have Googled a bit, you’ll read that you should derive DescriptionAttribute and DisplayNameAttribute to create localized versions which will result in a View Model that looks something like this:

public class UserViewModel
{
    [Required(ErrorMessageResourceName = "Required", 
      ErrorMessageResourceType = typeof(Resources.LocalizedStrings))]
    [LocalizedDisplayName(ErrorMessageResourceName = "UserId", 
      ErrorMessageResourceType = typeof(Resources.LocalizedStrings))]
    [LocalizedDescription(ErrorMessageResourceName = "UserIdDescription", 
      ErrorMessageResourceType = typeof(Resources.LocalizedStrings))]
    public int Id { get; set; }

    [Required(ErrorMessageResourceName = "Required", 
      ErrorMessageResourceType = typeof(Resources.LocalizedStrings))]
    [LocalizedDisplayName(ErrorMessageResourceName = "UserFirstName", 
      ErrorMessageResourceType = typeof(Resources.LocalizedStrings))]
    [LocalizedDescription(ErrorMessageResourceName = "UserFirstNameDescription", 
      ErrorMessageResourceType = typeof(Resources.LocalizedStrings))]
    public string FirstName { get; set; }

    [Required(ErrorMessageResourceName = "Required", 
      ErrorMessageResourceType = typeof(Resources.LocalizedStrings))]
    [LocalizedDisplayName(ErrorMessageResourceName = "UserLastName", 
      ErrorMessageResourceType = typeof(Resources.LocalizedStrings))]
    [LocalizedDescription(ErrorMessageResourceName = "UserLastNameDescription", 
      ErrorMessageResourceType = typeof(Resources.LocalizedStrings))]
    public string LastName { get; set; }
}

Don’t do that.

The solution to get cleaner DataAnnotation localization is to derive the attributes and do some magic in the derived classes. The problem with that solution is that client-side validation stops working unless you create new adapters for your derived attributes.

Don’t do that.

The Easy Solution

I found an excellent post by Brad Wilson that goes through most of the new stuff in MVC3. It’s a must read. When reading it, I came up with the idea to use the new Meta Data providers to do the localization. The solution works quite well and your models become clean again:

public class UserViewModel
{
    [Required]
    public int Id { get; set; }

    [Required]
    public string FirstName { get; set; }

    [Required]
    public string LastName { get; set; }
}

You need to specify the new providers (created by me) in your global.asax:

protected void Application_Start()
{
    var stringProvider = 
        new ResourceStringProvider(Resources.LocalizedStrings.ResourceManager);
    ModelMetadataProviders.Current = new LocalizedModelMetadataProvider(stringProvider);
    ModelValidatorProviders.Providers.Clear();
    ModelValidatorProviders.Providers.Add(
        new LocalizedModelValidatorProvider(stringProvider));
}

That’s it. No more messy attributes.

Defining the Localization Resources

I created an interface called ILocalizedStringProvider which is used by both providers. This means that you do not have to use String Tables. Just create a new class and implement that interface to get support for your database, XML file, or whatever you choose.

In my example, I used a string table, and the strings in it look like this:

As you can see, you should name your strings “ModelName_PropertyName” and “ModelName_PropertyName_MetadataName” to include meta data like Watermark and NullDisplayText. Refer to the documentation to see which kind of meta data there is.

As for validation attributes, the string table names should simply be the attribute name without the “Attribute” suffix.

Code and Documentation

The code is available at github. Documentation is available here.

Easy Model and Validation Localization in ASP.NET MVC3 - CodeProject