【发布时间】:2015-05-19 23:17:55
【问题描述】:
我似乎遇到了一个奇怪的问题,经过数小时的挠头,我似乎已将问题缩小到partial classes 和virtual properties 的组合。当我覆盖位于单独文件中的部分类中的属性时,MVC 会复制我视图中的字段。我正在使用 Visual Studio 2013,可以按照以下步骤复制该问题:
- 打开 Visual Studio 并创建一个新项目。在类别下选择 Web,然后选择“ASP.NET Web Application”。我的目标是 .NET 4.5。
- 从模板选择中选择“空”,然后选中 MVC 复选框,以便添加核心文件夹和引用。
- 创建项目后,右键单击
Models文件夹并创建一个名为MyModel.cs的新类。
将这些行添加到新文件中:
public abstract partial class MyOriginalModel
{
public virtual string FirstName { get; set; }
public virtual string LastName { get; set; }
}
public partial class MyModel : MyOriginalModel
{
}
- 现在再次右键单击
Models文件夹并创建另一个名为MyModelCustom.cs的新类。
将这些行添加到文件中:
public partial class MyModel
{
[System.ComponentModel.DisplayName("First Name")]
[System.ComponentModel.DataAnnotations.Required]
public override string FirstName
{
get
{
return base.FirstName;
}
set
{
base.FirstName = value;
}
}
[System.ComponentModel.DisplayName("Last Name")]
[System.ComponentModel.DataAnnotations.Required]
public override string LastName
{
get
{
return base.LastName;
}
set
{
base.LastName = value;
}
}
}
- 现在构建项目,然后右键单击
Controllers文件夹并添加一个新控制器。选择“具有读/写操作的 MVC 5 控制器”并将其命名为NamesController。右键单击 Create 方法并转到“添加视图”。在模板下拉列表中,选择Create,对于模型类下拉列表,选择MyModel。
一旦 MVC 创建模板,您将看到它添加了两次 First Name 和 Last Name。这个问题似乎与部分类有关,因为如果我将MyModelCustom.cs 的内容移动到MyModel.cs,一切正常。但是,它不仅仅是部分类。如果我在部分类中创建一个新属性(而不是重载一个),它不会复制该属性。所以它似乎是部分类和覆盖虚拟属性的组合。
有人可以确认这是一个错误还是我做错了什么?
【问题讨论】:
-
是的,MVC 使用反射。你直观地理解它必须。您会期望 Scaffolding 引擎会按类型分析您的模型,递归地为脚手架创建元数据映射。但该框架试图尽可能多地从模板和元数据中提取。与将模型映射到自然表达式相比,该框架似乎不太关心模型的准确性(大多数 Razor 助手使用未编译的函数 -- 表达式)。
-
这就是你的问题。脚手架引擎扫描您的每个部分,并使用表达式映射它们的属性。它忽略了虚拟可以并且正在被覆盖的事实。 BC 它们可以被覆盖,头脑简单的预编译器不会引发任何标志。但它只是预编译——完成了一半的工作。我怀疑如果您不扔这么多曲线球,该框架会更好地理解。部分问题并不是什么新鲜事。部分和继承得到普遍的抱怨。但虚拟可能是最糟糕的。也许使虚拟抽象可以解决它...
-
我完全同意戴夫的观点。只有一件事我想尝试看看它是否有效,就是在属性被覆盖的 MyModel 上继承你的类 MyOriginalModel 。并且让空的 MyModel 类不继承任何东西。
-
@ShashankChaturvedi,我很好奇会发生什么。我敢打赌它会起作用。
-
我马上要去这里开会。但今天晚些时候,我会尝试一下,让你们知道它是否有效。
标签: c# asp.net-mvc asp.net-mvc-5