There are several options to customize model metadata:
- Customize the way that framework provides metadata. (Create
ModelMedatadaProvider
)
- Create new Metadata attributes. (Implement
IMetadataAware
)
- Modify existing attributes. (Derive existing attributes.)
The 3rd option has been discussed in the other answer. Here in this post, I'll share first and second options.
Option 1 - Customize the way that framework provides metadata
You can change the logic of getting display text without changing the attribute.
In fact it's responsibility of ModelMetaDataProvider
to get mete data for model, including display text for properties. So as an option, you can keep the Display
attribute intact and instead, create a new model metadata provider and return property metadata from a different source.
To do so, you can create a new metadata provider by deriving from DataAnnotationsModelMetadataProvider
. Then override GetMetadataForProperty
and call base, to get metadata. Then change DisplayName
based on your logic by reading from your text manager.
You also need to register the new metadata provider as ModelMetadataProviders.Current
in App_Start
.
using System;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web.Mvc;
public class MyCustomModelMetadataProvider : DataAnnotationsModelMetadataProvider
{
protected override ModelMetadata GetMetadataForProperty(Func<object> modelAccessor,
Type containerType,
PropertyDescriptor propertyDescriptor)
{
var metadata = base.GetMetadataForProperty(modelAccessor,
containerType, propertyDescriptor);
var display = propertyDescriptor.Attributes
.OfType<DisplayAttribute>().FirstOrDefault();
if (display != null)
{
metadata.DisplayName = TextManager.GetValue(display.Name);
}
return metadata;
}
}
And then register it in Application_Start()
:
ModelMetadataProviders.Current = new MyCustomModelMetadataProvider();
For more information take a look at DataAnnotationsModelMetadataProvider.cs source code in ASP.NET MVC sources.
This approach is useful when you want to change the way that you provide metadata for model. For example when you want to load display name and description from an external file rather than resources, without changing existing attributes.
Option 2 - Create new Metadata attributes
Another standard solution for creating metadata-aware attributes is creating an attribute and implementing IMetadataAware
interface. Then in implementation of OnMetadataCreated
you can easily set properties of metadata
.
This approach doesn't need to register a new meta data provider. This approach is supported by the default metadata provider and is useful for creating new metadata-aware attributes:
using System;
using System.Web.Mvc;
public class CustomMetadataAttribure : Attribute, IMetadataAware
{
public string Key { get; set; }
public CustomMetadataAttribure(string key) => this.Key = key;
public void OnMetadataCreated(ModelMetadata metadata)
{
metadata.DisplayName = TextManager.GetValue(this.Key);
}
}
This approach is useful when you want to extend metadata attributes and add a few more attributes. For example when you want to add some attributes to control rendering. You can set ModelMetadata
properties or add some new values to its AdditionalValues
dictionary.