Asp.net mvc 向MVC ModelMetadata添加新属性

Asp.net mvc 向MVC ModelMetadata添加新属性,asp.net-mvc,asp.net-mvc-4,modelmetadata,modelmetadataprovider,Asp.net Mvc,Asp.net Mvc 4,Modelmetadata,Modelmetadataprovider,我看到了其他解决方法,例如附加值,但我想知道是否有可能最终出现这样一种情况,即您可以向模板视图中可用的ModelMetadata对象添加新属性 例如,您可以: @ViewData.ModelMetadata.MvvmBound 我想在编辑器和显示模板中使用它向呈现的HTML元素添加MVVM属性 我完全迷路了,但以下是我迄今为止的努力: public class MyModelMetaDataProvider : DataAnnotationsModelMetadataProvider {

我看到了其他解决方法,例如附加值,但我想知道是否有可能最终出现这样一种情况,即您可以向模板视图中可用的ModelMetadata对象添加新属性

例如,您可以:

@ViewData.ModelMetadata.MvvmBound
我想在编辑器和显示模板中使用它向呈现的HTML元素添加MVVM属性

我完全迷路了,但以下是我迄今为止的努力:

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; }
}  
问题是,如果我尝试在视图中使用MyProperty,它将无法识别,这是我预期的,因为VS不知道自定义ModelMetadata类


我甚至不确定这是否可能

ModelMetadata
类中有一个字典
AdditionalValues

您可以使用
AdditionalMetadata
属性向该字典添加值,如中所示:

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

    public string PropertyB{ get; set; }
}
您可以在
字符串
编辑器模板中检查这些内容,例如:

@{
    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
编辑器模板中,您可以执行以下操作(记住将扩展方法的名称空间添加到/Views文件夹中的Web.config文件中):

因为
ModelMetadata.AdditionalValues
是一个
字典
,所以您不限于为每个键存储一个简单的值。您可以按照上面的代码创建自己的类,该类包含所需的所有属性、一个可用于设置每个值并将该类的实例保存到AdditionalValues字典的属性,以及一个从字典中提取该类实例的扩展方法

如您所见,无需使用自己的
ModelMetadata
类或扩展
ModelMetadataProvider
,您就可以走得更远

希望有帮助

public static class ModelMetadataExtensions
{
    public static bool IsMvvmBound(this ModelMetadata metadata)
    {
        if (!metadata.AdditionalValues.ContainsKey("MvvmBound")) return false;
        return (bool)metadata.AdditionalValues["MvvmBound"];
    }
}
<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>
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; }
}