模型綁定在 MVC3 中找不到繼承的介面屬性,但在 MVC2 中工作正常
更新:問題已解決。
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; } }控制器動作
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幫助我們達林·季米特洛夫,你是我們唯一的希望。
我已經提請微軟注意這個問題。不幸的是,我得到的回應是:抱歉,這是設計使然。我個人從這樣的答案中得出的結論是 MVC 團隊正在設計一個有缺陷的產品,如果這是設計使然的話。他們不應該因為做出這樣的設計決定而受到責備,他們應該責怪在發行說明文件的重大更改部分中沒有提及它。如果他們提到了這一點,那麼即使我們故意知道重大變化,當我們做出遷移決定時也是我們的錯。
無論如何,這是一個相關的問題。
這是 MVC 團隊的回答:
不幸的是,程式碼實際上利用了一個已修復的錯誤,即用於 ModelMetadata 目的的表達式容器被無意中設置為聲明類型而不是包含類型。由於需要虛擬屬性和驗證/模型元數據,因此必須修復此錯誤。
我們不鼓勵使用基於介面的模型(考慮到錯誤修復所施加的限制,我們也不可以實際支持)。切換到抽象基類可以解決這個問題。
我發現了一個可悲的解決方法,它允許您使用這個模型結構:
@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>嗯。