【问题标题】:Inherited interface property not found by Model Binding in MVC3 but works fine in MVC2模型绑定在 MVC3 中找不到继承的接口属性,但在 MVC2 中工作正常
【发布时间】:2018-03-07 00:58:25
【问题描述】:

更新:问题已解决。

Darin Dimitrov 的回答包含指向另一个相关问题的链接。该页面上的One of the proposed solutions 最终为我们工作。


原始问题

下面的代码示例在 MVC 2 中有效,但在 MVC 3 中引发异常。有谁知道为什么 MVC 3 引入了这种重大更改?有没有办法让它在 MVC 3 中工作,同时仍然允许我将视图模型描述为视图中的接口?

StackOverflow 上还有另一个 related question,但它没有提供任何关于 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; }
}

控制器动作

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

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>

MVC3 视图(抛出异常)

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

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

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

【问题讨论】:

  • +1 呼吁达林。必须在约翰内。

标签: asp.net-mvc asp.net-mvc-3 model-binding


【解决方案1】:

我已经brought this issue 引起了 Microsoft 的注意。不幸的是,我得到的回应是:抱歉,这是设计使然。我个人从这样的答案中得出的结论是,MVC 团队正在设计一个有缺陷的产品,如果这是设计使然的话。他们不应该因为做出这样的设计决定而受到指责,他们应该指责在发行说明文档的重大更改部分中没有提及它。如果他们提到了这一点,那么即使我们故意知道重大变化,我们在做出迁移决定时也是我们的错。

无论如何,这是一个related question

这是 MVC 团队的回答:

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

我们不鼓励使用基于接口的模型(也不是, 鉴于错误修复所施加的限制,实际上可以 支持)。切换到抽象基类可以解决这个问题。

【讨论】:

  • 感谢您的回答达林。不幸的是,这是阻止我们团队升级到 MVC3 的一个障碍。 :(
  • 更新:您链接到的相关问题中的答案之一为我们解决了问题。该答案位于此处:stackoverflow.com/a/7826906/5651
  • 我不明白为什么使用IPerson 作为@model 可以,而ISpy 不行。在此示例中,当一个接口从另一个接口继承时会出现问题,并且所有关于为什么会发生这种情况的描述都是关于接口上的属性与实现不具有相同属性的属性。
【解决方案2】:

我发现了一个可悲的解决方法,它允许您使用此模型结构:

@model MvcApp.Models.IPerson
<p>Name: @Html.TextBoxFor(x => x.Name)</p>
@Html.Partial('_SpyBox')

在_SpyBox.cshtml中

@model MvcApp.Models.ISpy
<p>CodeName: @Html.TextBoxFor(x => x.CodeName)</p>

嗯。

【讨论】:

    【解决方案3】:

    改变这一行:

    @model MvcApp.Models.ISpy
    

    @model MvcApp.Models.Spy
    

    【讨论】:

    • 我需要任何实现 ISpy 的视图模型都可以重用视图。虽然您的建议“有效”,但它实际上并不能解决问题或回答我的问题。
    • 因此,在这种情况下,您将传递您的视图模型,而不是 ISpy 或 Spy。它将是 @model MvcApp.Models.SpyViewModel 或您命名的任何名称。然后在视图中它将是 x.spy.Name,其中 spy 是视图模型的属性。
    • 你从来没有说过这个问题?我解决了你的异常。您在帖子中没有提及使用视图模型。
    • 你是对的。我真的没有问过问题。我已经更新了。
    • 您的界面不包含名为 Name 的属性。它包含一个名为 CodeName 的属性。如果您在视图中引用 Name 的行并且只引用 codename 是否有效?
    猜你喜欢
    • 1970-01-01
    • 2011-05-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多