天天看點

ASP.NET MVC 音樂商店 - 5 通過支架建立編輯表單 續

現在,Store Manager 控制器中已經包含了一定數量的代碼,我們從頭到尾重新過一下。

首先,在控制器中包含了标準的 MVC 控制器的代碼,為了使用友善,還可以引用我們的模型類所在的命名空間 MvcMusicStore.Models。控制器還擁有了一個私有的 MusicStoreEntities 的私有成員,以友善控制器中的每個 Action 通路資料庫。

Index 視圖擷取專輯的清單,包含每一個專輯引用的流派和藝術家資訊,向我們在前面 Store控制器的 Browse時候看到的,Index 視圖中需要包含對于連結到的流派和藝術家對象來顯示相關的資訊,是以,在 Index 的 Action 方法中,需要包含這些資料。

在 Details 方法中,類似于 Store 控制器的 Details 方法,通過專輯的 Id 來擷取專輯對象,這裡使用 Find() 方法完成,最後,把這個對象傳遞給視圖。

與前面看到的不同,Create 方法需要處理表單,當使用者第一次通路位址 /StoreManager/Create 的時候,使用者将會看到一個空的表單,HTML 頁面中包含一個 <form> 元素,其中包含了下拉清單和文本框等輸入元素,使用者可以借助他們輸入專輯的詳細資訊。

當使用者填寫了專輯的資訊之後,可以通過點選 “儲存” 按鈕來送出表單資訊到伺服器,我們de應用程式可以擷取這些資訊儲存到資料庫中。在使用者點選 “儲存” 的時候,浏覽器發出一個 Http 的 Post 請求,到 /StoreManager/Create 位址,表單的内容作為這個 Post 請求的一部分發送回伺服器。

ASP.NET MVC 允許我們容易地分割這兩種同樣對于 Create 方法的請求處理,通過提供兩個同名的 Create 方法,一個用來處理 Http Get 請求,一個用來處理 Http Post 請求,區分的方式是在處理 Post 請求的方法前面增加一個 [HttpPost] 的标簽。如果增加 [HttpGet] 标簽,則表示這個方法僅僅處理 Http Get 請求。通常沒有這個标簽,則表示無論是 Get 請求還是 Post 請求都可以由這個 Action 方法處理。

我們曾經在這個教程的開始使用過 ViewBag, 但是,沒有深入讨論它,ViewBag 允許我們向視圖傳遞資訊而不需要首先定義強類型的 Model,在建立專輯的 Action 中,因為在表單中需要兩個清單框,我們需要向視圖傳遞清單所需要的資料,以便在視圖中填充下拉清單框,最簡單的方式就是通過 ViewBag 來實作。

ViewBag 是動态對象,這意味着你可以使用 ViewBag.Foo 或者 ViewBag.YourNameHere 形式的屬性而不需要預先定義這些屬性,控制器中的代碼使用 ViewBag.GenreId 和 ViewBag.Artisid 傳遞流派和藝術家的資訊以便生成表單中下拉清單的值,以後,用來在新建立的專輯中使用。

傳遞到視圖的下拉清單的值使用 SelectList 對象表示,對于我們的要求,使用下面的代碼。

方法中的三個參數被用于建立這個對象:

用來生成下拉清單中資訊的集合,注意,不是一個字元串集合,我們這裡是流派對象的集合。

方法的第二個參數提供下拉清單中的值,這是一個字元串,實際上是流派對象的一個屬性 GenreId。

最後的參數提供下拉清單中顯示出來的值,這裡使用流派的 Name 屬性。

了解了上面的内容,代碼就很簡單了,兩個 SelectList 對象通過 ViewBag 傳遞給視圖,沒有使用模型對象,我們也沒有建立這樣用途的模型。

下拉清單的資料已經被傳遞到了視圖中,現在,我們看一下視圖如何使用這些資料顯示一個下拉清單,在 Create 視圖中,将原來顯示流派辨別的代碼

修改為

這裡使用了 HtmlHelper ,一個用于視圖中生成 Html 的實用工具,使用 HtmlHelper 可以保持我們的視圖清楚和易讀。Html.DropDownList 助手方法由 ASP.NET MVC 提供,後面可以看到,我們也可以提供自己的助手方法進行擴充。 

Html.DropDownList 方法需要兩個參數,從哪裡擷取顯示用的清單,和哪一個值需要被預先選中,方法的第一個參數, GenreId,告訴DropDownList 從模型對象或者 ViewBag 對象中尋找名為 GenreId 的屬性值,第二個參數用來指出下拉清單預設選中的值。這是建立專輯的表單,是以,沒有需要預先選中的值,這裡傳遞了一個 String.Empty 。

我們在前面讨論過,對于一個表單可以有兩個對應的處理方法,一個處理 Http Get 請求顯示表單,另外一個用于處理 Http Post 請求,用于處理送出的表單資料,注意,在控制器中,處理 Http Post 請求的方法需要通過标簽 [HttpPost] 進行标注,這樣,這個方法将會被 ASP。NET 僅僅用來處理 Post 請求。

這個 Action 方法完成四個任務:

讀取表單的資料

檢查表單的資料是否通過了驗證規則

如果表單通過了驗證,儲存資料,然後顯示更新之後的專輯清單

如果表單沒有通過驗證,重新顯示帶有驗證提示資訊的表單。 

控制器處理的表單送出中包含了流派的辨別 GenreId 和 藝術家辨別 ArtistId,這些來自下拉清單框,以及通過文本框輸入的 Title,Price 等等資料,雖然可以直接通過 FormCollection 來通路表單資料,但是,更好的做法是使用 ASP.NET MVC 内置提供的模型綁定。

當 Action 方法的參數是模型類型的時候,ASP.NET MVC 将會試圖使用表單中的資料來填充對象的屬性,它通過檢查表單參數的名字是否比對模型對象的屬性來進行,例如,對于專輯對象的 GenreId 屬性來說,它将會在表單資料中查找名為 GenreId 的值賦予它。當使用标準的模型方式生成視圖的時候,表單會使用模型對象的屬性名稱來生成表單輸入項目的名稱,這樣,在發出表單的時候,請求參數就會正好匹 配模型的屬性了。

通過通路 ModelState 的 IsValid 屬性就可以檢查模型是否通過驗證。這裡我們還沒有為 Album 提供任何的驗證規則,後面我們就會提供,是以,這裡的驗證并沒有實際的作用。驗證的重要性取決于我們定義的在模型上的驗證規則,如果我們已經提供了對于 ModelState 的 IsValid 檢查的話,以後增加驗證規則就不需要修改這裡的代碼。

如果送出的資料通過了驗證,下一步就可以儲存到資料庫中,使用 EF,僅僅需要将模型對象加入到 Albums 的集合中,然後調用 SaveChanges 方法就可以了。

EF 将會生成适當的 SQL 指令來持久化對象,儲存資料之後,我們重定向到專輯清單的頁面,以便看到更新之後的内容。這可以通過調用 RedirectToAction 方法,并提供 Action 方法的名稱來完成。在這裡,我們使用 Index 。 

如果沒有通過驗證,與 GET 處理的時候相同,我們通過 ViewBag 傳遞下拉清單的值,通過模型傳遞其他的資料,驗證的提示資訊由 @HtmlValidationMessageFor 助手方法自動顯示在頁面上。

測試一下,運作程式,通路 /StoreManager/Create,你将會看到一個由 StoreManagerController 的 Create 方法處理  Http Get 請求生成的空白表單。

填寫一些内容,然後點選建立按鈕送出表單。

ASP.NET MVC 音樂商店 - 5 通過支架建立編輯表單 續

可以看到内容已經被添加。                       

ASP.NET MVC 音樂商店 - 5 通過支架建立編輯表單 續

編輯處理的一對 Action 方法非常類似我們剛剛看到的 Create 處理。由于編輯的情況需要對已經存在的唱片進行處理,在編輯的 Get 方法中,我們使用唱片的 Id 來加載原有的唱片,這個參數通過路由傳遞過來,實際的代碼類似在 Details 中看到的處理。除了專輯對象,同時還有處理下拉清單,是以,這裡也通過 ViewBag 來處理,這樣就允許我們在傳遞一個 Model 的同時還通過 ViewBag 傳遞了兩個額外的 SelectList。

處理 Post 請求的 Edit 方法也非常類似于 Create 的 Post 處理方法,僅有的不同就是不用建立一個新的專輯對象加入到集合中,而是将現有的專輯對象,注意已經通過模型綁定擷取了請求參數,将這個對象的狀态屬性 State 修改為 Modified ,這就回告訴 EF 我們正在修改一個存在的專輯對象,而不是建立一個新的。

注意,這個時候,編譯器會提示一個錯誤:

類型“System.Data.EntityState”在未被引用的程式集中定義。必須添加對程式集“System.Data.Entity, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089”的引用。         F:\Lesson\MVC\MvcMusicStore\MvcMusicStore\Controllers\StoreManagerController.cs 76     17     MvcMusicStore 

添加這個程式集的引用。

ASP.NET MVC 音樂商店 - 5 通過支架建立編輯表單 續
ASP.NET MVC 音樂商店 - 5 通過支架建立編輯表單 續

下面我們運作程式測試一下,浏覽/StoreManager,然後點選 Edit 連結。

ASP.NET MVC 音樂商店 - 5 通過支架建立編輯表單 續

點選 Save, 回到專輯清單,可以看到值已經被更新了。

ASP.NET MVC 音樂商店 - 5 通過支架建立編輯表單 續

删除的處理模式與 Edit 和 Create 一樣,使用一個控制器的 Action 顯示确認資訊,使用另外一個 Action 來處理送出。

删除的 Get 處理非常類似于前面的 Details 處理。

使用 Delete 視圖模闆顯示強類型的 Album 表單。

預設的 Delete 視圖使用模型來顯示資訊,但是,我們僅僅需要簡單地顯示确認資訊就可以了,把這個視圖修改一下,變成下面的樣子。

這樣,确認頁面就成了下面的樣子。

ASP.NET MVC 音樂商店 - 5 通過支架建立編輯表單 續

點選 Delete 按鈕之後,将導緻表單發送到伺服器,執行 DeleteConfirmed 的 Action 處理方法。

在我們的 Post 進行中,完成了下面的任務

通過專輯的 Id 加載專輯對象

删除專輯,然後儲存所做的修改

重新定向到 Index, 顯示删除專緝之後的清單。 

測試一下這些工作,運作程式,選擇一個專輯,然後删除它。

ASP.NET MVC 音樂商店 - 5 通過支架建立編輯表單 續

點選删除之後,顯示了第一張專輯的删除确認頁面。

ASP.NET MVC 音樂商店 - 5 通過支架建立編輯表單 續

點選删除之後,原來的專輯已經消失了。

ASP.NET MVC 音樂商店 - 5 通過支架建立編輯表單 續

我們的管理首頁存在一個潛在的問題,我們的專輯名稱和藝術家名稱可能比較長,這會影響到我們的頁面。下面我們建立一個自定義的 HtmlHelper 擴充來使得我們可以輕易地截斷比較長的字元串。在視圖中顯示成這樣的效果

Rozor 的 @helper 可以使這個工作變得很容易實作,打開 /View/StoreManager/Index.cshtml視圖,直接在 @model 的下面增加下面的代碼。

頁面将會變成下面的樣子。

ASP.NET MVC 音樂商店 - 5 通過支架建立編輯表單 續

這個助手方法取得一個字元串和一個最大長度,如果字元串長度小于指定的長度,就直接傳回這個串,如果大于最大長度,那麼,就截斷字元串,然後在剩下的最後增加 “…”。

現在,我們使用這個截斷字元串的助手方法來確定專輯名稱和藝術家名稱小于 25 個字元,完整的視圖内容如下所示。

注意,這裡展示了簡單地在一個視圖中使用 HtmlHelper 的方式,關于更多的資訊,請參考:

如果希望在多個視圖中使用這個擴充的助手方法,可以如下進行。

注意,使用擴充方法必須 using 其命名空間

你也可以在配置檔案 web.config 中統一定義。