ASP.NET MVC localization DisplayNameAttribute alternatives: a better way

Posted by Brian Schroer on Geeks with Blogs See other posts from Geeks with Blogs or by Brian Schroer
Published on Mon, 14 Jun 2010 16:04:42 GMT Indexed on 2010/06/14 23:12 UTC
Read the original article Hit count: 644

Filed under:

In my last post, I talked bout creating a custom class inheriting from System.ComponentModel.DisplayNameAttribute to retrieve display names from resource files:

        [LocalizedDisplayName("RememberMe")]
        public bool RememberMe { get; set; }

That’s a lot of work to put an attribute on all of my model properties though. It would be nice if I could intercept the ASP.NET MVC code that analyzes the model metadata to retrieve display names to make it automatically get localized text from my resource files. That way, I could just set up resource file entries where the keys are the property names, and not have to put attributes on all of my properties.

That’s done by creating a custom class inheriting from System.Web.Mvc.DataAnnotationsModelMetadataProvider:

   1:      public class LocalizedDataAnnotationsModelMetadataProvider :
   2:          DataAnnotationsModelMetadataProvider
   3:      {
   4:          protected override ModelMetadata CreateMetadata(
   5:              IEnumerable<Attribute> attributes, 
   6:              Type containerType, 
   7:              Func<object> modelAccessor, 
   8:              Type modelType, 
   9:              string propertyName)
  10:          {
  11:              var meta = base.CreateMetadata
  12:                  (attributes, containerType, modelAccessor, modelType, propertyName);
  13:   
  14:              if (string.IsNullOrEmpty(propertyName)) 
  15:                  return meta;
  16:   
  17:              if (meta.DisplayName == null)
  18:                  GetLocalizedDisplayName(meta, propertyName);
  19:   
  20:              if (string.IsNullOrEmpty(meta.DisplayName))
  21:                  meta.DisplayName = string.Format("[[{0}]]", propertyName);
  22:   
  23:              return meta;
  24:          }
  25:   
  26:          private static void GetLocalizedDisplayName(ModelMetadata meta, string propertyName)
  27:          {
  28:              ResourceManager resourceManager = MyResource.ResourceManager;
  29:              CultureInfo culture = Thread.CurrentThread.CurrentUICulture;
  30:   
  31:              meta.DisplayName = resourceManager.GetString(propertyName, culture);
  32:          }
  33:      }

Line 11 calls the base CreateMetadata method.

Line 17 checks whether the metadata DisplayName property has already been populated by a DisplayNameAttribute (or my LocalizedDisplayNameAttribute). If so, it respects that and doesn’t use my custom localized text lookup.

The GetLocalizedDisplayName method checks for the property name as a resource file key. If found, it uses the localized text from the resource files.

If the key is not found in the resource file, as with my LocalizedDisplayNameAttribute, I return a formatted string containing the property name (e.g. “[[RememberMe]]”) so I can tell by looking at my web pages which resource keys I haven’t defined yet.

It’s hooked up with this code in the Application_Start method of Global.asax:

    ModelMetadataProviders.Current = new LocalizedDataAnnotationsModelMetadataProvider();

© Geeks with Blogs or respective owner