MVC3中Model Binding找不到的继承接口属性,但在MVC2中工作正常

jes*_*vin 10 asp.net-mvc model-binding asp.net-mvc-3

更新:解决了问题.

Darin Dimitrov的答案包含另一个相关问题的链接.该页面上提出的解决方案之一最终为我们工作.


原始问题

下面的代码示例在MVC 2中工作但在MVC 3中引发异常.有谁知道为什么MVC 3引入了这个突破性的变化?有没有办法让这个在MVC 3中工作,同时还允许我在视图中将视图模型描述为一个接口?

StackOverflow上还有另一个相关的问题,但它没有给我任何关于为什么MVC 2和MVC 3之间存在差异的信息.

模型

public interface IPerson {
    string Name { get; set; }
}

public interface ISpy : IPerson {
    string CodeName { get; set; }
}

public class Spy : ISpy {
    public string Name { get; set; }
    public string CodeName { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

控制器动作

public ActionResult Index() {
    var model = new Spy { Name = "James Bond", CodeName = "007" };
    return View(model);
}
Run Code Online (Sandbox Code Playgroud)

MVC2查看(完美工作)

<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage<MvcApp.Models.ISpy>" %>
<p>CodeName: <%: Html.TextBoxFor(x => x.CodeName) %></p>
<p>Name: <%: Html.TextBoxFor(x => x.Name) %></p>
Run Code Online (Sandbox Code Playgroud)

MVC3视图(抛出异常)

@model MvcApp.Models.ISpy
<p>Name: @Html.TextBoxFor(x => x.Name)</p>
<p>CodeName: @Html.TextBoxFor(x => x.CodeName)</p>
Run Code Online (Sandbox Code Playgroud)

MVC3异常信息

我在下面显示相关的异常信息,但您可以在此处查看错误页面的整个输出:https://gist.github.com/1443750.

Runtime Exception
System.ArgumentException: The property **`MvcApp.Models.ISpy.Name`** could not be found.

Source Error:

Line 1:  @model MvcApp.Models.ISpy
Line 2:  <p>CodeName: @Html.TextBoxFor(x => x.CodeName)</p>
Line 3:  <p>Name: @Html.TextBoxFor(x => x.Name)</p>


Stack Trace:

[ArgumentException: The property MvcApp.Models.ISpy.Name could not be found.]
   System.Web.Mvc.AssociatedMetadataProvider.GetMetadataForProperty(Func`1 modelAccessor, Type containerType, String propertyName) +502169
   System.Web.Mvc.ModelMetadata.GetMetadataFromProvider(Func`1 modelAccessor, Type modelType, String propertyName, Type containerType) +101
   System.Web.Mvc.ModelMetadata.FromLambdaExpression(Expression`1 expression, ViewDataDictionary`1 viewData) +421
   System.Web.Mvc.Html.InputExtensions.TextBoxFor(HtmlHelper`1 htmlHelper, Expression`1 expression, IDictionary`2 htmlAttributes) +58
   System.Web.Mvc.Html.InputExtensions.TextBoxFor(HtmlHelper`1 htmlHelper, Expression`1 expression) +50
   ASP._Page_Views_Home_Index_cshtml.Execute() in c:\Projects\MvcApplication1\MvcApplication1\Views\Home\Index.cshtml:3
Run Code Online (Sandbox Code Playgroud)

帮助我们Darin Dimitrov,你是我们唯一的希望.

Dar*_*rov 9

我已经把这个问题提请微软注意了.不幸的是,我得到的回答是:抱歉这是设计上的.我个人得出的结论是,MVC团队正在设计一个有缺陷的产品,如果这是设计的话.并且他们不应该因为做出这样的设计决定而受到指责,他们是因为在发行说明文档的重大变更部分中没有任何提及它而受到指责.如果他们提到它,那么即使我们故意了解这一突破性变化,我们在做出迁移决定时也会是我们的错.

无论如何,这是一个相关的问题.

以下是MVC团队的回答:

不幸的是,代码实际上正在利用已修复的错误,其中用于ModelMetadata目的的表达式容器无意中设置为声明类型而不是包含类型.由于虚拟属性和验证/模型元数据的需要,必须修复此错误.

拥有基于接口的模型不是我们鼓励的(也不是,考虑到错误修复所施加的限制,可以实际支持).切换到抽象基类可以解决问题.