Add New Property to MVC ModelMetadata

I see alternative approaches to this, such as AdditionalValues, but I wonder if it is possible to end up in a script where you can add a new property to the ModelMetadata object, available as templates.

For example, you could:

@ViewData.ModelMetadata.MvvmBound

I want to use this in editor and display templates to add MVVM attributes to rendered HTML elements.

I am 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 that I'm trying to use MyProperty in a view that is not recognized, which I expected, because VS does not know about the standard ModelMetadata class.

I'm not even sure if this is possible?

+4
1

ModelMetadata AdditionalValues.

AdditionalMetadata, :

public class DummyModel
{
    [AdditionalMetadata("MvvmBound", true)]
    public string PropertyA{ get; set; }

    public string PropertyB{ get; set; }
}

string, :

@{
    bool isBound = false;
    if(ViewData.ModelMetadata.AdditionalValues.ContainsKey("MvvmBound"))
    {
        isBound = (bool)ViewData.ModelMetadata.AdditionalValues["MvvmBound"];    
    }
}

//use isBound to set some attributes in the html element

DummyModel, , :

@ModelMetadata.FromLambdaExpression(x => x.PropertyA, ViewData).AdditionalValues["MvvmBound"] 

, . , AdditionalValues, . :

public static class ModelMetadataExtensions
{
    public static bool IsMvvmBound(this ModelMetadata metadata)
    {
        if (!metadata.AdditionalValues.ContainsKey("MvvmBound")) return false;
        return (bool)metadata.AdditionalValues["MvvmBound"];
    }
}

. , DummyModel - ( Web.config /Views ):

<h3>WholeModel Is MvvmBound?: @ViewData.ModelMetadata.IsMvvmBound()</h3>
<h3>PropertyA Is MvvmBound?: @ModelMetadata.FromLambdaExpression(x => x.PropertyA, ViewData).IsMvvmBound()</h3>
<h3>PropertyB Is MvvmBound?: @ModelMetadata.FromLambdaExpression(x => x.PropertyB, ViewData).IsMvvmBound()</h3>

, IMetadataAware, , :

public class IsMvvmBoundAttribute : Attribute, IMetadataAware 
{
    public IsMvvmBoundAttribute()
    {
        this.IsMvvmBound = true;
    }

    public bool IsMvvmBound { get; set; }

    //This is the single method of IMetadataAware, and what allows us to add the values into the AdditionalValues dictionary
    public void OnMetadataCreated(ModelMetadata metadata)
    {
        metadata.AdditionalValues.Add("MvvmBound", this.IsMvvmBound);
    }
}

public class DummyModel
{
    //[AdditionalMetadata("MvvmBound", true)] <- replaced with the new attribute
    [IsMvvmBoundAttribute]
    public string PropertyA{ get; set; }

    public string PropertyB{ get; set; }
}

ModelMetadata.AdditionalValues Dictionary<string,object>, . , , , , , AdditionalValues ​​ , .

, , ModelMetadata ModelMetadataProvider.

, !

+10

Source: https://habr.com/ru/post/1534798/


All Articles