改善 Details 和 Delete 方法 (C#)
注意
這裡提供本教學課程的更新版本,其中使用 ASP.NET MVC 5 和 Visual Studio 2013。 新的教學指示更安全、更易於遵循且示範更多功能。
本教學課程將說明基本概念,簡介如何使用 Microsoft Visual Web Developer 2010 Express Service Pack 1 (Visual Studio Microsoft 的免費版本) 建置 ASP.NET MVC Web 應用程式。 開始之前,請確定您已安裝下列必要項目。 您可按以下連結安裝所有專案:Web Platform Installer。 或者可使用下列連結個別安裝必要條件:
- Visual Studio Web Developer Express SP1 必要條件
- ASP.NET MVC 3 工具更新
- SQL Server Compact 4.0 (執行階段 + 工作支援)
如果您使用 Visual Studio 2010 而非 Visual Web Developer 2010,請按以下連結安裝必要條件:Visual Studio 2010 必要條件。
本主題隨附內含 C# 原始程式碼的 Visual Web Developer 專案。 下載 C# 版本。 如果您偏好使用 Visual Basic,請切換至本教學課程的 Visual Basic version 版。
在本教學課程的這部分,您將瞭解如何改善自動產生的 Details
和 Delete
方法。 這些變更不是必要步驟,但只要使用一小段程式碼,就可以輕鬆增強應用程式。
改善 Details 和 Delete 方法
當您建構 Movie
控制器之後,ASP.NET MVC 產生的程式碼運作良好,但您希望能提升健全度,只要進行一小部分的調整就能做到。
開啟 Movie
控制器並修改 Details
方法,在找不到電影時傳回 HttpNotFound
。 您也應該修改 Details
方法,對傳遞至該方法的識別碼設定預設值。 (您在本教學課程的 第 6 部分,也曾對 Edit
方法做過類似變更)。不過,您必須將 Details
方法的傳回類型從 ViewResult
變更為 ActionResult
,因為 HttpNotFound
方法不會傳回 ViewResult
物件。 以下範例呈現已修改的 Details
方法。
public ActionResult Details(int id = 0)
{
Movie movie = db.Movies.Find(id);
if (movie == null)
{
return HttpNotFound();
}
return View(movie);
}
Code First 可讓您使用 Find
方法輕鬆搜尋資料。 此方法內建重要的安全性功能,即程式碼會先驗證 Find
方法是否已找到電影,然後才嘗試執行任何動作。 比方說,駭客可能會將透過 http://localhost:xxxx/Movies/Details/1
連結建立的 URL 變更為類似 http://localhost:xxxx/Movies/Details/12345
(或不代表實際電影的其他值),導致站台發生錯誤。 若未檢查 Null 電影,可能會導致資料庫錯誤。
同樣地,請變更 Delete
和 DeleteConfirmed
方法,指定 ID 參數的預設值,並在找不到電影時傳回 HttpNotFound
。 Movie
控制器中已更新的 Delete
方法如下所示。
// GET: /Movies/Delete/5
public ActionResult Delete(int id = 0)
{
Movie movie = db.Movies.Find(id);
if (movie == null)
{
return HttpNotFound();
}
return View(movie);
}
//
// POST: /Movies/Delete/5
[HttpPost, ActionName("Delete")]
public ActionResult DeleteConfirmed(int id = 0)
{
Movie movie = db.Movies.Find(id);
if (movie == null)
{
return HttpNotFound();
}
db.Movies.Remove(movie);
db.SaveChanges();
return RedirectToAction("Index");
}
請注意,Delete
方法不會刪除資料。 如果您執行刪除作業以回應 GET 要求 (或是執行相關編輯作業、建立作業或任何會變更資料的其他作業),則會造成安全性漏洞。
我們將可刪除資料的 HttpPost
方法命名為 DeleteConfirmed
,以提供 HTTP POST 方法的唯一簽章或名稱。 這兩個方法簽章如下所示:
// GET: /Movies/Delete/5
public ActionResult Delete(int id = 0)
//
// POST: /Movies/Delete/5
[HttpPost, ActionName("Delete")]
public ActionResult DeleteConfirmed(int id = 0)
通用語言執行平台 (CLR) 需要多載方法,以提供唯一簽章 (方法名稱相同但參數清單不同)。 不過,這裡還會用到兩個 Delete 方法 (分別用於 GET 和 POST),且兩者都有相同的簽章。 (它們都需要接受單一整數作為參數)。
若要解決此問題,您可以執行幾項動作。 其一是指定不一樣的方法名稱。 這是我們在前述範例的作法。 不過,這麼做會導致一個小問題:ASP.NET 會依名稱將 URL 區段與動作方法對應,一旦您重新命名方法,路由通常就會找不到這個方法。 解決辦法正如您看到的這個範例:將 ActionName("Delete")
屬性新增至 DeleteConfirmed
方法。 此方法會有效執行路由系統的對應,以便 POST 要求中含有 /Delete/ 的 URL 找到 DeleteConfirmed
方法。
避免方法同名問題的另一個解方,是以人工方式變更 POST 方法的簽章,並加入未使用的參數。 例如,有些開發人員會新增參數類型 FormCollection
並傳遞至 POST 方法,然後就不使用參數:
public ActionResult Delete(FormCollection fcNotUsed, int id = 0)
{
Movie movie = db.Movies.Find(id);
if (movie == null)
{
return HttpNotFound();
}
db.Movies.Remove(movie);
db.SaveChanges();
return RedirectToAction("Index");
}
結語
現在您已有一個完整的 ASP.NET MVC 應用程式,資料則儲存在 SQL Server Compact 資料庫中。 您可建立、讀取、更新、刪除和搜尋電影。
本基本教學課程可協助您開始製作控制器、建立控制器與檢視的關聯,以及傳遞硬式編碼資料。 接著,您建立並設計資料模型。 Entity Framework Code First 會從資料模型即時建立資料庫,而 ASP.NET MVC Scaffolding 系統會自動產生基本 CRUD 作業的動作方法和檢視。 接著您新增了搜尋表單,讓使用者搜尋資料庫。 您變更資料庫以納入新的資料行,然後更新兩個頁面,以建立及顯示這項新資料。 您已使用 DataAnnotations
命名空間中的屬性標記資料模型,以新增驗證。 產生的驗證會在用戶端和伺服器上執行。
如果您想部署應用程式,建議先在本機 IIS 7 伺服器上測試。 您可以使用此 Web Platform Installer 連結,啟用 ASP.NET 應用程式的 IIS 設定。 請參閱下列部署連結:
在此建議您繼續參閱中級程度的教學課程 (為 ASP.NET MVC 應用程式建立 Entity Framework 資料模型和「MVC Music 市集),並且瀏覽 MSDN 上有關 ASP.NET 的文章,以及善用 https://asp.net/mvc 的豐富影片和資源,深入瞭解 ASP.NET MVC! ASP.NET MVC 論壇是提問的絕佳平台。
敬祝您使用愉快!
— Scott Hanselman (http://hanselman.com 和 Twitter 上的 @shanselman);Rick Anderson blogs.msdn.com/rickAndy