简体   繁体   中英

Updating DisplayName without attributing property

I need to use an existing object as a property in my model, which I can't apply DisplayNameAttribute to it as the file is compiled.

This is a complex and deep object and this pattern needs to be repeated - I don't want to create a wrapper over it unless I absolutely have to.

I believe the most appropriate way to do this is to manually set the DisplayName attribute on the ModelMetadata class.

I've managed to find properties and set the display attribute using code below:

var metadata = ModelMetadataProviders.Current.GetMetadataForType(null, model.GetType());
metadata.Properties.Where(x => x.PropertyName == "FirstName").Single().DisplayName = "First name";

The changes made on the second line do not effect the "source of truth" - that is, everytime the first line is executed the DisplayName property on FirstName is set to null.

How can I work around this? This is in a normal MVC method.

You can override DataAnnotationsModelMetadataProvider to set the DisplayName (and do all kinds of other fancy stuff).

using System.Web.Mvc;
public class CustomModelMetaDataProvider : DataAnnotationsModelMetadataProvider {

    // called once for each property of the ViewModel
    protected override ModelMetadata CreateMetadata(IEnumerable<Attribute> attributes, Type containerType, Func<object> modelAccessor, Type modelType, string propertyName) {

        Func<IEnumerable<Attribute>, ModelMetadata> metadataFactory = attr => base.CreateMetadata(attr, containerType, modelAccessor, modelType, propertyName);
        var metadata = metadataFactory(attributes);

        // set DisplayName depending on ViewModel type and property name
        if (modelType == typeof(CustomModelToOverride)) {
            if (propertyName == "FirstName") {
                metadata.DisplayName = "First name";
            }
            else if (propertyName == "LastName") {
                // ...
            }
        }

        return metadata;
    }
}

Register this custom MetaDataProvider in the Global.asax.cs

protected void Application_Start() {

    // ...
    var metaDataProvider = new CustomModelMetaDataProvider();
    ModelMetadataProviders.Current = metaDataProvider;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM