I'm seeing alternative approaches to this such as AdditionalValues, but I'm wondering if it's possible to end up in a scenario where you can add a new property to the ModelMetadata object available in template views.
For example you could have:
@ViewData.ModelMetadata.MvvmBound
I want to use this in Editor and Display templates to add MVVM attributes to the HTML elements being rendered.
I'm completely lost, but here are my efforts so far:
public class MyModelMetaDataProvider : DataAnnotationsModelMetadataProvider
{
protected new MyModelMetaData CreateMetadata(IEnumerable<Attribute> attributes, Type containerType, Func<object> modelAccessor, Type modelType, string propertyName)
{
ModelMetadata modelMetaData = base.CreateMetadata(attributes, containerType, modelAccessor, modelType, propertyName);
MyModelMetaData myMetaData = (MyModelMetaData)modelMetaData;
return myMetaData;
}
}
public class MyModelMetaData: ModelMetadata
{
public MyModelMetaData(ModelMetadataProvider provider, Type containerType, Func<object> modelAccessor, Type modelType, string propertyName)
: base(provider, containerType, modelAccessor, modelType, propertyName)
{
}
public int MyProperty { get; set; }
}
Then in global asax I use:
ModelMetadataProviders.Current =new MyModelMetaDataProvider();
The problem is if I try to use MyProperty in the view it isn't recognized, which I anticipated because VS isn't aware of the custom ModelMetadata class.
I'm not even sure this is possible?
There is a dictionary
AdditionalValues
in theModelMetadata
class. Ref hereYou can add values to that dictionary using the
AdditionalMetadata
attribute, as in:And you could check those in a
string
editor template, for example:You may also want to check those attributes in the editor template for
DummyModel
, which you can do retrieving the metadata for individual properties as in:There are some downsides of this code as it is. The approach requires to pass the key name to the AdditionalValues dictionary and you also need to cast the value from object to the proper type. You could create your own extension method for retrieving that value from the metadata without the need to manually provide the key name and manually perform a casting:
Which would allow you a cleaner code in the editor templates. For example in an editor template for the
DummyModel
above you could do something like (remember to add the namespace of the extension method to the Web.config file inside the /Views folder):You could pair that extension method with your custom attribute extending
IMetadataAware
so you don't need to hardcode the name of the key for the metadata value every time you use it on a property:Because
ModelMetadata.AdditionalValues
is aDictionary<string,object>
, you are not limited to storing a simple value per key. You can follow the code above to create you own class holding all the properties that you need, an attribute that you can use to set each of those values and saves an instance of that class to the AdditionalValues dictionary and an extension method that extracts the instance of that class from the dictionary.As you can see, you can go pretty far without the need for your own
ModelMetadata
class or extending theModelMetadataProvider
.Hope it helps!