2011-05-14 146 views
1

嘗試當模型對象在MVC3被實例化理解:當模型對象在MVC3(ASP.NET)創建

我有編輯「人」的示意圖。每個人可以有多個地址。我在人員視圖中顯示網格中的地址。

這顯示一個人很好用;我有一個局部視圖,它遍歷Person.Addresses並構建表格/網格。

創建新人時出現問題:人物對象爲空,並且Person.Addresses引用是非法的。我確定我在這裏錯過了一些相當基礎的東西:因爲MVC將會(自動奇蹟地)在「保存」時創建新的人員實例。如果我嘗試創建自己的對象實例,似乎會產生反作用,如果我這樣做,我不清楚如何將它連接到表單上的其他條目值。

最後一個併發症:Addresses的列表是可選的;完全不合法的地址。

由於關係數據非常普遍,所以必須有一個更簡單的解決方案來處理這個問題。所有澄清讚賞!

+0

因此,你實際上是一個人,你正在創造一個人嗎? – 2011-05-14 22:25:21

+0

正確。編輯人員時,模型對象已經存在。創建人員時,模型對象爲空。 – 2011-05-15 16:46:14

回答

3

這個問題的答案是,對象是從表單中的POST數據重新構成的。這是相當基本的,但是MVC隱藏了很多事情,當你試圖獲得你的(MVC)軸承時很難看到。

項目的順序是:

  1. 了所有必要的字段創建表;對未顯示的鍵(ID)使用隱藏字段。
  2. 用戶與網頁交互;然後按下表單提交按鈕。
  3. 所有字段數據都被髮送到控制器頁面。
  4. MVC將數據重新組成類對象。
  5. 將控制器頁面與重新構造的類實例調用爲形式參數。

注:

創建頁面時:一個形式與用於對象的每個部分的場產生被表示。 MVC爲ID和其他非顯示數據以及驗證規則使用隱藏字段。
值得注意的是,由_CreateOrEdit.cshtml頁面上列出的所有對象屬性所創建的形式(通常情況下)或者:

// Edit.cshtml 
@model Person 

@Html.Partial("_CreateOrEdit", Model) 

// _CreateOrEdit.cshtml 
@model Person 

@Html.HiddenFor(model => model.PersonID) 

@Html.LabelFor(model => model.first_name, "First Name") 
@Html.EditorFor(model => model.first_name) 

@Html.LabelFor(model => model.last_name, "Last Name") 
@Html.EditorFor(model => model.last_name) 

@Html.LabelFor(model => model.favorite_color, "Favorite Color") 
@Html.EditorFor(model => model.favorite_color) 

//etcetera 

,或者通過使用模板類(模板必須與他們代表的班級名稱相同,他們位於Views\Shared\EditorTemplates文件夾中)。

使用模板的頁面幾乎是相同的以前的方法:

// Edit.cshtml 
@model Person 

@Html.EditorForModel() 

// Shared\EditorTemplates\Person.cshtml 
@model Person 

@Html.HiddenFor(model => model.PersonID) 

@Html.LabelFor(model => model.first_name, "First Name") 
@Html.EditorFor(model => model.first_name) 

@Html.LabelFor(model => model.last_name, "Last Name") 
@Html.EditorFor(model => model.last_name) 

@Html.LabelFor(model => model.favorite_color, "Favorite Color") 
@Html.EditorFor(model => model.favorite_color) 

//etcetera 

使用模板方法可以很容易地(的對象)列表添加到窗體。 Person.cshtml變爲:

// Shared\EditorTemplates\Person.cshtml 
@model Person 

@Html.HiddenFor(model => model.PersonID) 

@Html.LabelFor(model => model.first_name, "First Name") 
@Html.EditorFor(model => model.first_name) 

@Html.LabelFor(model => model.last_name, "Last Name") 
@Html.EditorFor(model => model.last_name) 

@Html.LabelFor(model => model.favorite_color, "Favorite Color") 
@Html.EditorFor(model => model.favorite_color) 

@EditorFor(model => model.Addresses) 

//etcetera 

// Shared\EditorTemplates\Address.cshtml 
@model Address 
@Html.HiddenFor(model => model.AddressID) 

@Html.LabelFor(model => model.street, "Street") 
@Html.EditorFor(model => model.street) 

@Html.LabelFor(model => model.city, "City") 
@Html.EditorFor(model => model.city) 

//etcetera 

MVC將處理在必要時創建的列表中的每個地址多份表單條目。

POST正好相反;創建模型對象的新實例,調用默認的無參數構造函數,然後MVC填充每個字段。通過顛倒@Html.EditorFor(model.List)的序列化過程來填充列表。

public class Person 
{ 
    public List<Address> Addresses; 

    public Person() 
    { 
     // You always need to create this List object 
     Addresses = new List<Address>(); 
    } 

    ... 
} 

,涵蓋的是:需要注意的是,你必須確保你的類創建在構造函數列表中的有效容器否則MVC的名單重新憲法將失敗是很重要的。幕後有很多事情要做,但都是可追蹤的。

兩點很重要,如果你有麻煩與此:

  1. 請確保您有@Html.HiddenFor(...)爲需要「生存」之旅回服務器的一切。
  2. 使用Fiddler或HTTPLiveHeaders(Firefox插件)檢查POST數據的內容。這將讓您驗證正在發回的數據以重新構建新的類實例。我偏愛Fiddler,因爲你可以在任何瀏覽器中使用它(並且它特別好地顯示錶單數據)。

最後一點:有關於動態添加/刪除從MVC列表中元素的好文章:http://jarrettmeyer.com/post/2995732471/nested-collection-models-in-asp-net-mvc-3這是一個很好的文章,以合作,通過 - 是的,這確實與MVC3和剃刀工作。

0

我假設的地址是在一個表格中,而不是實際的輸入元素,可能只是<td> info </td >? 如果是這樣,那麼他們將不會被實例化,因爲沒有數據被髮回服務器。 您必須使用回傳的元素創建此數據,以便將它們映射(按名稱)到其屬性。模型聯編程序將實例化對象,並在回發時將它們傳遞給控制器​​,如果它可以找到適當命名的發佈表單(或查詢字符串)元素。

+0

那麼,你會將地址表附加到元素列表中,以便它可以成爲POST數據的一部分嗎?如果是這樣,你會如何做到這一點? – 2011-05-15 16:48:27

+0

@Robert最簡單的方法是做一些AJAX事情,就像SO上的評論系統是如何工作的。當您點擊添加評論時,評論通過AJAX發佈,div更新爲新內容。您可以使用強類型的局部視圖來完成此操作。 – TheHurt 2011-05-15 17:05:05