views:

1290

answers:

3

I am trying to figure out how to get the DisplayAttribute in my MVC 2 ViewModel to work with the Html.LabelFor() helper.

Neither

public class TestModel
{
    [Display(ResourceType = typeof(Localization.Labels))]
    public string Text { get; set; }
}

nor

public class TestModel
{
    [Display(Name = "test")]
    public string Text { get; set; }
}

seem to work. Localizing the Required Attribute works as expected:

[Required(ErrorMessageResourceName = "Test", ErrorMessageResourceType = typeof(Localization.Labels))]

I am using VS2010 RC. Has anybody got that running?

+7  A: 

The [Display] attribute is a .NET 4-specific attribute. Since MVC 2 is compiled against .NET 3.5, the runtime does not recognize this attribute.

See http://aspnet.codeplex.com/WorkItem/View.aspx?WorkItemId=5515 for more information plus workarounds.

Edit:

Eh, the work item's not that big. May as well include it inline. :)

The [Display] attribute is new in DataAnnotations v4, so MVC 2 can't use it because we're compiled against DataAnnotations v3.5. Use [DisplayName] instead until MVC 3, where we will be compiled against DataAnnotations v4.

You have a few workarounds. When .NET 4 RTMs, we will provide a .NET 4-specific Futures binary, and that Futures binary will have a metadata provider that understands [Display] and other DataAnnotations v4-specific attributes. Alternatively, if you need a solution right away, subclass the [DisplayName] attribute, make a private DisplayNameAttribute field that's instantiated appropriately, and override the virtual DisplayNameAttribute.DisplayName property so that it delegates to _theWrappedDisplayNameAttribute.GetName().

public class MultiCulturalDisplayName : DisplayNameAttribute {
  private DisplayAttribute display;

  public MultiCulturalDisplayName(Type resourceType, string resourceName) {
    this.display = new DisplayAttribute { ResourceType = resourceType, Name = resourceName };
  }

  public override string DisplayName {
    get { return display.GetName(); }
  }
}
Levi
Yep, I used a very similar solution now. Thanks.
asp_net
A: 

Levi pretty much answered your question, and for the record here is a working version for 3.5

[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)]
public class DisplayNameLocalizedAttribute : DisplayNameAttribute
{
    public DisplayNameLocalizedAttribute(Type resourceType, string resourceKey)
        : base(LookupResource(resourceType, resourceKey)) {  }

    internal static string LookupResource(Type resourceType, string resourceKey)
    {
        PropertyInfo property = resourceType.GetProperties().FirstOrDefault(p => p.PropertyType == typeof(System.Resources.ResourceManager));
        if (property != null)
        {
            return ((ResourceManager)property.GetValue(null, null)).GetString(resourceKey);
        }
        return resourceKey;
    }
}
moi_meme
+3  A: 

If you download ASP.NET MVC 2 Futures assembly, then you can use the DisplayAttribute. You just need to add DataAnnotations4ModelMetadataProvider.RegisterProvider(); to your Global.asax.cs

Matt Dotson