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?
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
}
}
You can't.
However, you can act as a proxy for all other models. Something like:
public class YourProvider<TViewModel>
{
public YourProvider(InnerProvider provider) {}
public ModelMetaData GetMetaData(SomeContext context)
{
if (context.ModelType != typeof(TViewModel))
return _innerProvider.GetMetaData(context);
//Other logic here.
}
}
And finally assign it as:
ModelMetadataProviders.Current
= new MyModelMetadataProvider<CustomViewModel>(ModelMetadataProviders.Current);