Localizing ASP.NET MVC Validation

aspnetmvc localization validation 0 comments suggest edit

This is the fourth post in my series on ASP.NET MVC 2 and its new features.

  1. ASP.NET MVC 2 Beta Released (Release Announcement)
  2. Html.RenderAction and Html.Action
  3. ASP.NET MVC 2 Custom Validation
  4. Localizing ASP.NET MVC Validation

In my recent post on custom validation with ASP.NET MVC 2, several people asked about how to localize validation messages. They didn’t want their error messages hard-coded as an attribute value.

world-in-handsIt turns out that it’s pretty easy to do this. Localizing error messages is not specific to ASP.NET MVC, but is a feature of Data Annotations and ASP.NET. And everything I cover here works for ASP.NET MVC 1.0 (except for the part about client validation which is new to ASP.NET MVC 2).

I covered this feature a back in March at Mix 09 in my ASP.NET MVC Ninjas on Fire Black Belt Tips talk. If you want to see me walk through it step by step, check out the video. If you prefer to read about it, continue on!

Let’s start with the ProductViewModel I used in the last post

public class ProductViewModel {
  [Price(MinPrice = 1.99)]
  public double Price { get; set; }

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

If we’re going to localize the error messages for the two properties, we need to add resources to our project. To do this, right click on your ASP.NET MVC project and select Properties. This should bring up the properties window. Click on the Resources tab. You’ll see a message that says,

This project does not contain a default resources file. Click here to create one.

Obey the message. After you click on the link, you’ll see the resource editor.

resources-tab Make sure to change the Access Modifier to Public(it defaults to Internal).

resources-tab-access-modifier

Now enter your resource strings in the resource file.

resource-file

Hopefully my Spanish is not too bad. An ASP.NET build provider will create a new class named Resources behind the scenes with a property per resource string. In this case there’s a property named PriceIsNotRight and Required. You can see the new file in the Properties folder of your project.

solution-with-resources

The next step is to annotate the model so that it pulls the error messages from the resources.

public class ProductViewModel {
  [Required(ErrorMessageResourceType = typeof(Resources),
    ErrorMessageResourceName = "Required")]
  public string Title { get; set; }
  [Price(MinPrice = 3.99, ErrorMessageResourceType = typeof(Resources),
    ErrorMessageResourceName = "PriceIsNotRight")]
  public double Price { get; set; }
}

For the ErrorMessageResourceType, I just specify the type created by the build provider. In my case, the full type name is CustomValidationAttributeWeb.Properties.Resources.

For the ErrorMessageResourceName, I just use the name that I specified in the resource file. The name identifies which resource string to use.

Now when I submit invalid values, the error messages are pulled from the resource file and you can see they are in Spanish.

Client Validation - Windows Internet
Explorer

Localized Error Messages Custom Client Validation

Note that these localized error messages continue to work even if you enable client validation. However, if you were to try it with the original code I posted in my last validation example, the error message would not work for the custom price validation attribute.

Turns out I had a bug in the code, which is now corrected in the blog post with a note describing the fix. Just scroll down to the PriceValidator class.

As always, I have a code sample you can look at. It’s the same example as before, just updated. Download the sample!

Tags: aspnetmvc, asp.net, validation, localization, data annotations

Found a typo or error? Suggest an edit! If accepted, your contribution is listed automatically here.

Comments

avatar

30 responses

  1. Avatar for Dave R.
    Dave R. December 13th, 2009

    I'm unsure how your example is localized. All you've done is hard-code Spanish strings in the resource file instead of hard-coding English ones in the main source. To be localized, you'll have to be able to switch to culture-specific strings at runtime. In the past, you could do this with multiple .resx files and by using the ResourceManager - is this no longer possible in MVC?
    Why not follow the instructions here, which describe multiple approaches, including using the culture info exposed by the browser visiting your page:
    msdn.microsoft.com/en-us/library/aa905797.aspx
    quickstarts.asp.net/.../localization.aspx
    MS should produce some best practices for localizing MVC based apps if the existing ASP.NET methods no longer work.

  2. Avatar for Raj
    Raj December 14th, 2009

    Hi
    I was unable to download the sample. Even when I do "Save Link As".

  3. Avatar for Aaron King
    Aaron King December 17th, 2009

    I too was unable to download the sample.

  4. Avatar for marus
    marus December 27th, 2009

    c'mmon! download?!...

  5. Avatar for msi
    msi January 11th, 2010

    On my Visual Studio 2008 vi instaled ASP.NET MVC 2, I have disabled field "Access Modifier", how can I enable it?

  6. Avatar for Mustafa Gülmez
    Mustafa Gülmez January 19th, 2010

    If your .res file is under App_GlobalResources or App_LocalResources, Access Modifier shown as disabled. move under Properties, Access Modifier turn enabled.

  7. Avatar for msi
    msi January 19th, 2010

    I've found another solution

  8. Avatar for Adam
    Adam January 22nd, 2010

    I also can't download sample, this zip file probably don't exist. Error - "The system cannot find the file specified"

  9. Avatar for Sharbel
    Sharbel January 26th, 2010

    I think you should change the title of this post from 'Localizing' because honestly this is not localizing at all. It's a great article to show how not to hard-code validation error messages in the model, but it doesn't at all touch on localizing the messages based on the client locale.

  10. Avatar for Mahdi Taghizadeh
    Mahdi Taghizadeh February 5th, 2010

    Renaming 'Resources.resx' to something like 'Resources.fr-FR.resx' causes a problem. I described here: stackoverflow.com/...

  11. Avatar for msi
    msi February 14th, 2010

    It does not work on my situation :(
    I've found the solution and describe it on my blog. But it is only on russian language.

  12. Avatar for trinity
    trinity February 15th, 2010

    even though this isn't really true localization, it does give you a good example of how to implement the localization strings in the models, with the
    ErrorMessageResourceType = typeof(Resources), ErrorMessageResourceName = "PriceIsNotRight")
    line.
    this is a great example of localization: http://code.google.com/p/aspmvclocalization/ - but it leaves out what I said above. enjoy...

  13. Avatar for Gregor Suttie
    Gregor Suttie May 30th, 2010

    How do I go about this problem - I have 2 date time values in my model and when I go to insert a new project the start date and end date validation error messages say that the format is incorrect. Im in the UK and add them as 30/05/2010 but the error message says its invalid and the format 05/30/2010 is invalid.

  14. Avatar for Shash J
    Shash J August 2nd, 2010

    I want to replace certain words that are in the resource file. Is there a way to derive a class from a base class that will replace words.
    <asp:Localize ...
    <custom:Localize ...

  15. Avatar for Lee
    Lee August 10th, 2010

    If we use Database as our Resource Content then How can we use this approach.

  16. Avatar for Rob
    Rob August 15th, 2010

    Link for the sample code is broken. thx for the post btw, everything works very nice.

  17. Avatar for RR
    RR August 24th, 2010

    The download is available through:
    code.haacked.com/...

  18. Avatar for denappel
    denappel October 19th, 2010

    Thanks for the example.
    We aren't using static resources, but we get the resources from the database.
    If I fill in the following for the dataannotations:

    [MetadataType(typeof(IncidentsMetaData))]
    public partial class INCIDENTS
    {
    private class IncidentsMetaData
    {
    [Required(ErrorMessageResourceType = typeof(CustomResourceProviders.DBResourceProviderFactory),
    ErrorMessageResourceName="1277")]
    public string SUBJECT { get; set; }
    }
    }

    Then I get the following error:
    The resource type 'CustomResourceProviders.DBResourceProviderFactory' does not have an accessible static property named '1277'.
    Of course there is no such property, it should be accessed by a function.
    Any idea what I could do about this?
    tnx

  19. Avatar for Ryan
    Ryan November 24th, 2010

    I've got a stupid question: is it possible to replace all of the english text around the validation errors with errors in a different language. WITHOUT using data annotations?
    We've built a web application which currently only supports one language (dutch). It will eventually be globalized, but the immediate problem is that the error messages are all (US) English.
    It's not really efficient use of time to add several thousand attributes to view models just to change a dozen string constants..

  20. Avatar for Ryan
    Ryan November 29th, 2010


    Still can't download the sample: "An error occurred while processing your request."
    Thanks

  21. Avatar for JohnF
    JohnF January 16th, 2011

    By the way, here is a nice and detailed ASP.NET MVC 3 Internationalization/Localization post http://bit.ly/gUBkX3

  22. Avatar for Esmaltes
    Esmaltes March 10th, 2011

    How should I localize DisplayName Attribute ?

  23. Avatar for haacked
    haacked March 10th, 2011

    @Esmaltes you can't. If you're running on .NET 4, use the DisplayAttribute instead.

  24. Avatar for Tom
    Tom April 18th, 2012

    adamyan.blogspot.com.au/... for the full store. Thanks Phil

  25. Avatar for Diablofan
    Diablofan April 28th, 2012

    I was having trouble localizing Enumeration values, and your article helped me figure out how to get it done. Thanks.

  26. Avatar for Oliver
    Oliver August 23rd, 2012

    Hi.
    How would get the display name of the property? Like
    "Field "Name" is requried",
    How would you get the "Name"-value?

  27. Avatar for ssssss
    ssssss May 6th, 2013

    sssssssssss

  28. Avatar for Asmaa Gad
    Asmaa Gad June 29th, 2015

    by [DisplayName("your Name")]
    property in model

  29. Avatar for Anjan Kant
    Anjan Kant December 7th, 2015

    Good example on Data Annotation!

  30. Avatar for Bhilendra Yede
    Bhilendra Yede July 26th, 2016

    HI

    How i do validation for ^([a-zA-Z]*[a-zA-Z '-]*)$ regexp in Thai

    any idea??