2011-05-03 19 views
0

我正在構建一個頁面來編輯各種產品類型。每種產品類型都有一個從ProductVM繼承的視圖模型(TentProductVM,BootProductVM)。我的MVC2視圖檢查模型類型並根據需要添加字段。例如,如果模型屬於BootProductVM類型,我會調用Html.TextBoxFor爲引導腳的尺寸添加一個字段。頁面顯示正常。MVC2使用子類的帖子

問題是帖子。我已經聲明瞭一個函數(在VB中),如下所示:

<HttpPost()>Function Edit(byval prod as ProductVM) As ActionResult 

當然,這個函數只接收來自基類ProductVM的表單數據。於是我又增加了一個功能,每個產品類型:

<HttpPost()>Function EditTent(byval prod as TentProductVM) As ActionResult 
<HttpPost()>Function EditBoot(byval prod as BootProductVM) As ActionResult 

,並指出查看到相應的崗位職能:

Using Html.BeginForm("Edit" & Model.ObjectTypeName, "Catalog") 

然而,當EditTent或EditBoot被調用,督促參數僅包含數據來自基類。所有在子類視圖模型中聲明的字段都保留默認值。

我在做什麼錯?還是有更好的方法? (顯而易見的解決方案是多頁,但由於ProductVM具有相對於子類衆多領域,我寧願不要。)


多次試驗之後,我決定不使用這種方法。首先,我無法使用FormCollection類型的Action參數來使其工作。其次,如果我使用局部視圖,我放棄的顯而易見的解決方案是有吸引力的。部分視圖具有與基類(ProductVM)相關的所有字段,僅保留常規視圖中與派生類(TentProductVM,BootProductVM)關聯的字段。

感覺就像我在與MVC自動魔法戰鬥,這是從來沒有正確的做法。

回答

1

有關MVC的一點要記住的是它基於「Convention over Configuration」思想。所以如果你將一個強類型的類實例傳遞給你的動作方法,它期望它被命名爲「model」。

試着改變你的聲明看起來像這樣:

<HttpPost()> Function EditTent(byval model as TentProductVM) As ActionResult 
<HttpPost()> Function EditBoot(byval model as BootProductVM) As ActionResult 

其他(不太理想的)選擇是期望在動作方法的FormCollection對象。

<HttpPost()> Function EditTent(byval form as FormCollection) as ActionResult 

更新

只是更新,包括下面的一些討論要點......爲了發佈一個強類型對象到控制器的操作方法,該類型必須匹配起來。

假設你的控制器的操作方法是這樣的:

<HttpPost()> Function EditTent(byval model as ProductVM) As ActionResult 

你的觀點應相應類型:

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<Your.Namespace.ProductVM>" %> 
+0

令我驚訝,我改變了參數的名稱爲「模型」,它被設置爲空! – Adventure 2011-05-03 18:04:07

+0

問題可能是我的視圖繼承了_System.Web.Mvc.ViewPage(MyNamespace.ProductVM)_但我的post函數參數是_BootProductVM_的子類? (如果編輯各種產品類型共享一個頁面,這當然是不可避免的。) – Adventure 2011-05-03 18:07:36

+0

這樣做。如果你要有一個共享的視圖,使用這種通用的ViewModel,你將不得不在你的操作方法中接受一個「ProductVM」。然後,將其映射到您的控制器方法內的實際數據模型。你也可以創建一個自定義的ModelBinder,但我認爲第一個選項是最簡單的。 – JasonOffutt 2011-05-03 19:52:10