14

I use a custom resource provider to get resource strings from a database. This works fine with ASP.NET where I can define the resource type as a string. The metadata attributes for model properties in MVC 3 (like [Range], [Display], [Required] require the type of a Resource as a parameter, where the ResourceType is the type of the generated code-behind class of a .resx file.

    [Display(Name = "Phone", ResourceType = typeof(MyResources))]
    public string Phone { get; set; }

Because I don't have .resx files, such a class does not exist. How can I use the model attributes with a custom resource provider?

I would like to have something like this:

    [Display(Name = "Telefon", ResourceTypeName = "MyResources")]
    public string Phone { get; set; }

The DisplayNameAttribute from System.ComponentModel had a overridable DisplayName Property for this purpose, but the DisplayAttribute class is sealed. For the validation attributes no corresponding classes exist.

3 Answers 3

7

The most cleanest way I came up with is to override DataAnnotationsModelMetadataProvider. Here's a very neat article on how to do this.

http://buildstarted.com/2010/09/14/creating-your-own-modelmetadataprovider-to-handle-custom-attributes/

Sign up to request clarification or add additional context in comments.

1 Comment

would you show us how you managed to write that. The article shows how to add a new data notation, but doesn't show anything about localization
4

You can extend the DisplayNameAttribute and override the DisplayName string property. I have something like this

    public class LocalizedDisplayName : DisplayNameAttribute
    {
        private string DisplayNameKey { get; set; }   
        private string ResourceSetName { get; set; }   

        public LocalizedDisplayName(string displayNameKey)
            : base(displayNameKey)
        {
            this.DisplayNameKey = displayNameKey;
        }


        public LocalizedDisplayName(string displayNameKey, string resourceSetName)
            : base(displayNameKey)
        {
            this.DisplayNameKey = displayNameKey;
            this.ResourceSetName = resourceSetName;
        }

        public override string DisplayName
        {
            get
            {
                if (string.IsNullOrEmpty(this.GlobalResourceSetName))
                {
                    return MyHelper.GetLocalLocalizedString(this.DisplayNameKey);
                }
                else
                {
                    return MyHelper.GetGlobalLocalizedString(this.DisplayNameKey, this.ResourceSetName);
                }
            }
        }
    }
}

For MyHelper, the methods can be something like this:

public string GetLocalLocalizedString(string key){
    return _resourceSet.GetString(key);
}

Obviously you will need to add error handling and have the resourceReader set up. More info here

With this, you then decorate your model with the new attribute, passing the key of the resource you want to get the value from, like this

[LocalizedDisplayName("Title")]

Then the Html.LabelFor will display the localized text automatically.

2 Comments

i think you forgot to put the code for "MyHelper.GetLocalLocalizedString"
I know this is going zombie but you deserve more internets for this.
2

I think you would have to override the DataAnnotations properties to localize them with a DB resource provider. You could inherit from the current ones, and then specify further properties such as DB connection string to use when getting the resources from your custom provider.

2 Comments

Unfortunately this does not work as the DisplayAttribute is a sealed class. Even if I do my own implementation for the attribute I would have to overwrite the Html Extension methods (e.g. Html.LabelFor) as well.
I made further investigations: I could derive from DisplayNameAttribute which has an overrideble property DisplayName. In the end I used a T4 template to generate the Resources class because I don't have to implement all data annotation attributes.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.