MVC脚手架正在复制我的模型字段

Ice*_*ind 11 c# asp.net-mvc asp.net-mvc-5

我似乎遇到了一个奇怪的问题,经过几个小时的搔痒,我似乎已经将问题缩小到部分类虚拟属性的组合.当我覆盖部分类中的属性,坐在单独的文件中时,MVC会复制我视图中的字段.我正在使用Visual Studio 2013,可以通过以下步骤复制该问题:

  1. 打开Visual Studio并创建一个新项目.在类别下选择Web,然后选择"ASP.NET Web应用程序".我的目标是.NET 4.5.
  2. 从模板选择中选择"Empty",然后选中MVC复选框,以便添加核心文件夹和引用.
  3. 创建项目后,右键单击该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
{

}
Run Code Online (Sandbox Code Playgroud)
  1. 现在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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)
  1. 现在构建项目,然后右键单击该Controllers文件夹并添加一个新控制器.选择"具有读/写操作的MVC 5控制器"并调用它NamesController.右键单击Create方法,然后转到"Add View".在模板下拉列表下,选择Create并为"模型类"下拉列表选择MyModel.

一旦MVC创建模板,你会看到它添加First NameLast Name的两倍.这个问题似乎与部分类有关,因为如果我将内容MyModelCustom.cs移入MyModel.cs,则一切正常.但是,它不仅仅是部分类.如果我在分部类中创建一个新属性(而不是重载一个),则它不会复制该属性.所以它似乎是部分类和重写虚拟属性的组合.

有人可以确认这是一个错误还是我做错了什么?

Dav*_*ich 2

查看 MvcScaffolding EnvDTETypeLocator.cs的 CodePlex 源代码

    /// <summary>
    /// Out of a set of CodeType instances, some of them may be different partials of the same class.
    /// This method filters down such a set so that you get only one partial per class.
    /// </summary>
    private static List<CodeType> PickArbitraryRepresentativeOfPartialClasses(IEnumerable<CodeType> codeTypes)
    {
        var representatives = new List<CodeType>();
        foreach (var codeType in codeTypes) {
            var codeClass2 = codeType as CodeClass2;
            if (codeClass2 != null) {
                var matchesExistingRepresentative = (from candidate in representatives.OfType<CodeClass2>()
                                                     let candidatePartials = candidate.PartialClasses.OfType<CodeClass2>()
                                                     where candidatePartials.Contains(codeClass2)
                                                     select candidate).Any();
                if (!matchesExistingRepresentative)
                    representatives.Add(codeType);
            } else {
                // Can't have partials because it's not a CodeClass2, so it can't clash with others
                representatives.Add(codeType);
            }
        }
        return representatives;
    }
}
Run Code Online (Sandbox Code Playgroud)

:

:

1) PickArbitraryRepresentativeOfPartialClasses,该方法使用Linqany()来确认codeType as CodeClass2有成员。

CodeClass2是EnvDTE的部分类类型,EnvDTE 是 Visual Studio 的核心自动化库,负责 IDE 代码生成(设计时反射)。

2)如果类强制转换为CodeClass2确实有成员,则将该类添加到representatives

3)当评估分部类时,将在不同的上下文中访问每个文件(通常会导致应覆盖的元素的合并)


运行时反射和设计时反射之间的一个有趣区别: 原文如此

ASP.NET 控件在运行时在页面内执行或在设计时在主机设计器内使用时具有两组不同的功能。运行时功能根据配置确定控件输出的标记。相反,设计时功能受益于可视化设计器(例如 Microsoft Visual Studio 2005)。设计时功能使页面作者能够以声明性和所见即所得(所见即所得)的方式配置运行时控件。 -你-得到)的方式。

结论:

MVC 脚手架确实使用了反射,但它是不太可靠的设计时反射。

设计时反射与运行时反射不同。完全编译的类是继承解析、部分组合和优先级解析的最终结果。设计时反射可以对如何使用复杂的多部分类型进行最佳猜测。

如果您想依赖脚手架,最好不要突破它的极限。当您遇到这样的错误时,请尝试简化您的 ViewModel:

  • 尝试巩固你的部分课程
  • 尝试删除您的摘要/虚拟内容