asp.net-mvcentity-framework-4modelmetadataprovider

Configure Custom MetadataProvider for ViewModel


I have a ViewModel for which want to be able to set Metadata properties dynamically. For example I would like to be able to customise the DisplayName and validation error messages using the value of other model properties. I plan to do this with a custom MetadataProvider, following Brad Wilson's article.

I want the provider only to be used with selected ViewModels. So my question is, how do I configure that? I have seen examples using ModelMetadataProviders.Current = new MyModelMetadataProvider(), but this would presumably use the custom provider for all model classes entities. Is it possible to configure a provider for a single ViewModel?


Solution

  • I'm pretty sure changing the current model metadata provider in the ViewModel is not safe once you start getting multiple users on the site, let alone thread safe. You might be able to use the attribute method but you'll still have to implement your own ModelMetadataProvider and set it to Current at the start of your app, then inspect for certain attributes and determine your ModelMetaData to return, if there are none then fall through to the base implementation. Though to be honest, the amount of restrictions that you're talking about, having it only handle selected view models but not being allowed to know or test for those view models? It sounds like you're doing something wrong elsewhere...

    UPDATE: When I needed a ModelMetadata provider I created one that looks something like this...

    public class MyMetadataProvider : DataAnnotationsModelMetadataProvider
    {
        protected override ModelMetadata CreateMetadata(IEnumerable<Attribute> attributes, Type containerType, Func<object> modelAccessor, Type modelType, string propertyName)
        {
            if ((containerType != typeof(MyType))
                return base.CreateMetadata(attributes, containerType, modelAccessor, modelType, propertyName);
    
            //setup custom ModelMetadata here
        }
    }