Click here to Skip to main content
Click here to Skip to main content
Technical Blog

Easy model and validation localization in ASP.NET MVC3

, 13 Sep 2011 LGPL3
Rate this:
Please Sign up or sign in to vote.
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 looks 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.

License

This article, along with any associated source code and files, is licensed under The GNU Lesser General Public License (LGPLv3)

Share

About the Author

jgauffin
Founder Gauffin Interactive AB
Sweden Sweden
Founder of OneTrueError, a .NET service which captures, analyzes and provide possible solutions for exceptions.
 
blog | twitter
Follow on   Twitter   LinkedIn

Comments and Discussions

 
-- There are no messages in this forum --
| Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.141220.1 | Last Updated 13 Sep 2011
Article Copyright 2011 by jgauffin
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid