当我尝试将Metadatatype与viewmodel一起使用时,我得到InvalidOperationException

时间:2014-05-22 11:41:39

标签: c# asp.net-mvc data-annotations invalidoperationexception metadatatype

我有一个具有某些属性的模型。我使用带有MetadataType的分隔类来定义属性的要求。我还尝试将相同的元数据类与仅定义属性子集的viewmodel一起使用。这是一个简单的示例代码,用于澄清:

[MetadataType(typeof(Metadata))]
class ModelA
{

    public class Metadata
    {
         [Required]
         public object Property1 { get; set; }

         [Required]
         public object Property2 { get; set; }

    }

    public int Property1 { get; set; }
    public int Property2 { get; set; }
}

[MetadataType(typeof(ModelA.Metadata))]
class ViewModelA
{
    public int Property1 { get; set; }
}

问题是当剃刀引擎尝试处理视图时,它会抛出 InvalidOperationException ,并显示以下错误消息:

ViewModelA ”类型的相关元数据类型包含以下未知属性或字段: Property2 。请确保这些成员的名称与主要类型的属性名称相匹配。

在我的理解中,这里的问题是元数据包含视图模型没有的属性。但是,这种方式我并不真正理解拥有元数据类的优点。所以我的问题是

1)有没有办法防止抛出此异常?

2)如果没有,这种情况最好的模式是什么? (比如使用模型,视图模型,其中包含模型属性的子集,通过保持DRY方法来定义数据注释)。

1 个答案:

答案 0 :(得分:4)

MetadataTypeAttribute通常用于要将元数据应用于自动生成的对象的情况。如果要将元数据应用于对象本身,则在重新生成对象时将覆盖它们。

这通常通过部分类来完成。例如见下文。在这种情况下,您创建一个与自动生成的类同名的空的分部类,它当然命名相同,但是您向其添加MetadataType属性,并在其中包含嵌套的Metadata类。

您通常不会将此与其他类一起使用,因为其他类必须具有相同(或超集)的属性。

// Do no edit this class as it is auto generated
public partial class ModelA
{
    public int Property1 { get; set; }
    public int Property2 { get; set; }
}

// This class can be edited
[MetadataType(typeof(ModelA.Metadata))]
public partial class ModelA
{
    public class Metadata
    {
         [Required]
         public object Property1 { get; set; }

         [Required]
         public object Property2 { get; set; }

    }
}

所以,回答你的问题:

1)不,你无法阻止异常,因为元数据必须描述它的父类的所有属性,如果这些属性不存在,它就会抛出。

2)您必须创建备用元数据类。由于这与创建独立视图模型一样多,因此将子友类用于子集的视图模型没有任何实际好处。

很多人都卷入了DRY的概念。问题是每个软件实现都有竞争要求。 DRY通常与单一责任原则不一致。

MetadataTypeAttribute无论如何都要处理设计人员生成代码的方式。如果你正在使用Code First,那么我强烈反对使用MetadataTypeAttribute。