原文地址:http://www.asp.net/mvc/tutorials/iteration-1-create-the-application-cs javascript
紫色永恆的翻譯:http://www.cnblogs.com/024hi/archive/2009/03/19/ASP_NET_MVC_SAMPLE_CONTACT_MANAGER_1.html css
系列將演示如何經過ASP.NET MVC framework結合單元測試、TDD、Ajax、軟件設計原則及設計模式建立一個完整的Contact Manager應用。本系列共七個章節,也是七次迭代過程。我是在紫色永恆的博客看到文章後開始實踐這個系列的。開發環境是ASP.NET MVC 3.0(Razor),Visual Studio 2010SP1,SQL2008。因爲和上面兩文裏的環境不一樣,代碼相對來講有部分變化,因此我也對照上兩文記錄一下個人實踐過程。疏漏之處請拍磚~ html
在這個系列中,咱們將從頭到尾的建立一個Contact Management應用程序。咱們能夠經過它來管理聯繫信息,如名字、電話號碼、電子郵件地址等等。 java
咱們將經過迭代的方式開發這個應用,並在每次迭代的過程當中逐漸的擴展和改善該應用程序。 jquery
本次迭代 web
在第一次迭代中,咱們先創建最基本最簡單的應用程序,而後在接下來的迭代中,逐漸改善程序的設計。 sql
Contact Manager是一個基本的數據庫驅動的應用程序。你可使用它創建新的聯繫人,編輯已存在的聯繫人亦或者刪除這些聯繫人。 數據庫
本次迭代咱們將完成以下步驟: c#
開發環境是ASP.NET MVC 3.0(Razor),Visual Studio 2010SP1,SQL2008。 設計模式
若是沒有ASP.NET MVC 3.0請經過web平臺安裝程序安裝:
運行vs2010而後選擇新建項目。在新建項目窗口選擇c# web模板裏的ASP.NET MVC 3 Web應用程序。項目名稱輸入ContactManager後按肯定創建(如圖1)。
圖1.新建項目
點擊肯定後,跳轉到圖2。在這個界面能夠選擇模板的具體類型是空模板仍是示例應用程序,咱們選Internet應用程序。接下來是視圖引擎選擇,傳統的ASPX仍是新發布的Razor,這裏咱們選擇Razor引擎。這裏咱們還要建立單元測試項目ContactManager.Tests,由於在之後的迭代裏咱們計劃加入單元測試。在建立mvc項目時添加測試項目要比完成時再添加要簡單多了。
圖2.建立單元測試及選擇Razor引擎
點擊肯定咱們就建立了一個MVC3.0的應用程序。能夠在解決方案資源管理器中看到圖3。若是看不到解決方案資源管理器窗口請到視圖裏打開(或者按CTRL+W打開)。
注意:解決方案裏包括了兩個項目:ASP.NET MVC項目和測試項目。名字分別爲ContactManager、ContactManager.
圖3.解決方案資源管理器
建立的實例項目裏包含不少的controllers 和views的sample文件。在咱們往下作以前先刪除掉沒用的文件。(實際項目裏能夠在建立的項目模板裏圖2選擇空)在圖3的窗口中點擊右鍵並選擇刪除。刪除的列表以下:
\Controllers\HomeController.cs
\Views\Home\About.cshtml
\Views\Home\Index.cshtml
同時測試項目裏刪除以下:
\Controllers\HomeControllerTest.cs
Contact Manager 是一個數據庫驅動的web應用,因此咱們創建一個數據庫來存儲contact信息。
本系列咱們使用sql server2008。安裝vs2010時候已經一塊兒安裝,若是你選擇了的話:)
右擊解決方案資源管理器中的App_Data文件夾選擇 添加-》新建項,而後如圖4,選擇數據模板裏的SQLServer數據庫,名稱填入ContactManagerDB.mdf 按添加。
圖 04: 創建數據庫
創建數據庫完成後,App_Data文件夾裏能夠看到ContactManagerDB.mdf。雙擊ContactManagerDB.mdf打開服務器資源管理器鏈接數據庫。在表上右擊選擇添加新表打開表設計器(圖05).第一個字段Id右鍵設置成主鍵而且設置爲增量種子,具體如圖。完成後保存爲表Contacts
圖 05: 表設計器
在建立完表後右擊表Contacts,選擇顯示錶數據,而後添加幾條數據來進行後面的測試。
咱們要爲上面建立的Contacts建立一個實體模型。本系列咱們使用Microsoft Entity Framework 來建立(簡稱EF)。固然也能夠用其餘的框架,例如NHibernate, LINQ to SQL, or ADO.NET。
經過如下幾步來創建:
圖 06: 添加新項
圖 07: 選擇模型內容
圖 08: 選擇數據鏈接
圖 09: 選擇數據庫對象
完成嚮導後會自動打開數據實體模型設計界面。能夠看到一個類Contact(圖10)
圖10: 類Contact
這裏咱們已經建立了數據庫模型,咱們可使用Contact 類表明數據庫的contact 記錄。
下面建立咱們的Home controller。Home controller是mvc應用的默認入口。
在Controllers 文件夾右擊,選擇添加-》控制器(圖11)。.注意選上圖中的複選框來自動生成建立、更新、刪除等方法.
圖 11: 添加Home Conntroller
建立完後獲得以下代碼的類
Listing 1 - Controllers\HomeController.cs
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; namespace ContactManager.Controllers { public class HomeController : Controller { // // GET: /Home/ public ActionResult Index() { return View(); } // // GET: /Home/Details/5 public ActionResult Details(int id) { return View(); } // // GET: /Home/Create public ActionResult Create() { return View(); } // // POST: /Home/Create [HttpPost] public ActionResult Create(FormCollection collection) { try { // TODO: Add insert logic here return RedirectToAction("Index"); } catch { return View(); } } // // GET: /Home/Edit/5 public ActionResult Edit(int id) { return View(); } // // POST: /Home/Edit/5 [HttpPost] public ActionResult Edit(int id, FormCollection collection) { try { // TODO: Add update logic here return RedirectToAction("Index"); } catch { return View(); } } // // GET: /Home/Delete/5 public ActionResult Delete(int id) { return View(); } // // POST: /Home/Delete/5 [HttpPost] public ActionResult Delete(int id, FormCollection collection) { try { // TODO: Add delete logic here return RedirectToAction("Index"); } catch { return View(); } } } }
Contacts列表
要列出Contacts 表的記錄,咱們須要建立Index的action和view。Home controller 已經生成了Index() action,修改以下:
Listing 2 - Controllers\HomeController.cs
... using ContactManager.Models; ... private ContactManagerDBEntities _entities = new ContactManagerDBEntities(); // // GET: /Home/ public ActionResult Index() { return View(_entities.Contacts.ToList()); } ...
注意引用ContactManager.Models!這裏編譯一下整個解決方案,否則在action上右擊添加視圖會出問題。在index()上右擊選添加視圖打開添加視圖窗口。
圖12 添加視圖
圖13 添加視圖
名稱自動生成爲Index,選擇建立強類型視圖模型類裏選擇Contact,支架模板裏選擇List,母版也選擇/Views/Shared/_Layout.cshtml。能夠看到index的view以下:
Listing 3 - Views\Home\Index.cshtml
@model IEnumerable<ContactManager.Models.Contact> @{ ViewBag.Title = "Index"; Layout = "~/Views/Shared/_Layout.cshtml"; } <h2>Index</h2> <p> @Html.ActionLink("Create New", "Create") </p> <table> <tr> <th></th> <th> FirstName </th> <th> LastName </th> <th> Phone </th> <th> Email </th> </tr> @foreach (var item in Model) { <tr> <td> @Html.ActionLink("Edit", "Edit", new { id=item.Id }) | @Html.ActionLink("Details", "Details", new { id=item.Id }) | @Html.ActionLink("Delete", "Delete", new { id=item.Id }) </td> <td> @item.FirstName </td> <td> @item.LastName </td> <td> @item.Phone </td> <td> @item.Email </td> </tr> } </table>
本系列咱們不作聯繫人的詳細界面,因此刪除上面的@Html.ActionLink("Details", "Details", new { id=item.Id }) | ,這時能夠按F5運行程序看看效果了(圖14)。
要添加新聯繫人信息,咱們要在Home controller裏添加2個Create() actions,一個用來返回建立聯繫人的HTML表單,另一個來執行實際的數據庫插入操做。Create()方法代碼以下:
Listing 4 - Controllers\HomeController.cs (with Create methods)
// // GET: /Home/Create public ActionResult Create() { return View(); } // // POST: /Home/Create [AcceptVerbs(HttpVerbs.Post)] public ActionResult Create([Bind(Exclude = "Id")] Contact contactToCreate) { if (!ModelState.IsValid) return View(); try { _entities.AddToContactSet(contactToCreate); _entities.SaveChanges(); return RedirectToAction("Index"); } catch { return View(); } }
第一個Create()在HTTP GET時候被調用,它只是簡單的返回一個用來添加聯繫人的表單,而第二個Create()只有在HTTP POST時候纔會被調用,它往數據庫裏添加新聯繫人。
第二個Create()方法接收一個Contact的實例。表單值提交後被MVC框架自動的綁定到contact類,每個表單域對應contact的一個屬性。[Bind]屬性綁定主鍵Id。和上面同樣在create方法上右擊選擇添加視圖(圖16)。
圖16
添加視圖窗口裏選擇以下(圖17):
圖 17: 添加視圖
添加後自動生成的Create的view以下.
Listing 5 - Views\Home\Create.cshtm
@model ContactManager.Models.Contact @{ ViewBag.Title = "Create"; Layout = "~/Views/Shared/_Layout.cshtml"; } <h2>Create</h2> <script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script> <script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script> @using (Html.BeginForm()) { @Html.ValidationSummary(true) <fieldset> <legend>Contact</legend> <div class="editor-label"> @Html.LabelFor(model => model.FirstName) </div> <div class="editor-field"> @Html.EditorFor(model => model.FirstName) @Html.ValidationMessageFor(model => model.FirstName) </div> <div class="editor-label"> @Html.LabelFor(model => model.LastName) </div> <div class="editor-field"> @Html.EditorFor(model => model.LastName) @Html.ValidationMessageFor(model => model.LastName) </div> <div class="editor-label"> @Html.LabelFor(model => model.Phone) </div> <div class="editor-field"> @Html.EditorFor(model => model.Phone) @Html.ValidationMessageFor(model => model.Phone) </div> <div class="editor-label"> @Html.LabelFor(model => model.Email) </div> <div class="editor-field"> @Html.EditorFor(model => model.Email) @Html.ValidationMessageFor(model => model.Email) </div> <p> <input type="submit" value="Create" /> </p> </fieldset> } <div> @Html.ActionLink("Back to List", "Index") </div>
如今運行程序能夠點擊Create New菜單到建立頁面(圖18)
圖 18: 建立頁面
修改Conntroller裏的Edit方法以下:
Listing 6 - Controllers\HomeController.cs (with Edit methods)
// // GET: /Home/Edit/5 public ActionResult Edit(int id) { var contactToEdit = (from c in _entities.Contacts where c.Id == id select c).FirstOrDefault(); return View(contactToEdit); } // // POST: /Home/Edit/5 [HttpPost] public ActionResult Edit(Contact contactToEdit) { if (!ModelState.IsValid) return View(); try { var originalContact = (from c in _entities.Contacts where c.Id == contactToEdit.Id select c).FirstOrDefault(); //_entities.ApplyPropertyChanges(originalContact.EntityKey.EntitySetName, contactToEdit); _entities.ApplyCurrentValues<Contact>(originalContact.EntityKey.EntitySetName, contactToEdit); _entities.SaveChanges(); return RedirectToAction("Index"); } catch { return View(); } }
第一個Edit方法顯示頁面,第二個處理post的數據。在Edit方法上右擊選擇添加視圖打開添加視圖界面,選擇以下(圖19)
圖 19: 添加eidt視圖
添加完成生成以下代碼:
Listing 7 - Views\Home\Edit.cshtml
@model ContactManager.Models.Contact @{ ViewBag.Title = "Edit"; Layout = "~/Views/Shared/_Layout.cshtml"; } <h2>Edit</h2> <script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script> <script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script> @using (Html.BeginForm()) { @Html.ValidationSummary(true) <fieldset> <legend>Contact</legend> @Html.HiddenFor(model => model.Id) <div class="editor-label"> @Html.LabelFor(model => model.FirstName) </div> <div class="editor-field"> @Html.EditorFor(model => model.FirstName) @Html.ValidationMessageFor(model => model.FirstName) </div> <div class="editor-label"> @Html.LabelFor(model => model.LastName) </div> <div class="editor-field"> @Html.EditorFor(model => model.LastName) @Html.ValidationMessageFor(model => model.LastName) </div> <div class="editor-label"> @Html.LabelFor(model => model.Phone) </div> <div class="editor-field"> @Html.EditorFor(model => model.Phone) @Html.ValidationMessageFor(model => model.Phone) </div> <div class="editor-label"> @Html.LabelFor(model => model.Email) </div> <div class="editor-field"> @Html.EditorFor(model => model.Email) @Html.ValidationMessageFor(model => model.Email) </div> <p> <input type="submit" value="Save" /> </p> </fieldset> } <div> @Html.ActionLink("Back to List", "Index") </div>
修改Delete方法以下:
Listing 8 - Controllers\HomeController.cs (Delete methods)
// GET: /Home/Delete/5 public ActionResult Delete(int id) { var contactToDelete = (from c in _entities.Contacts where c.Id == id select c).FirstOrDefault(); return View(contactToDelete); } // // POST: /Home/Delete/5 [HttpPost] public ActionResult Delete(Contact contactToDelete) { try { var originalContact = (from c in _entities.Contacts where c.Id == contactToDelete.Id select c).FirstOrDefault(); _entities.DeleteObject(originalContact); _entities.SaveChanges(); return RedirectToAction("Index"); } catch { return View(); } }
一樣爲Dlete添加視圖後運行。點擊Delete到確認頁面(圖20):
圖20: 刪除確認頁面
系統爲咱們默認生成的Controller有時候並非咱們須要的,在類名上右擊選擇重構-》重命名打開重命名界面(圖21)
圖21: 重命名controller
圖22重命名界面
重命名以後Visual Studio 會自動去改動view文件夾裏的相關東西。如\Views\Home 文件夾改成\Views\Contact文件夾。
這時候運行會出錯,須要同步修改Global.asax 裏的默認路由。
routes.MapRoute( "Default", // 路由名稱 "{controller}/{action}/{id}", // 帶有參數的 URL new { controller = "Contact", action = "Index", id = UrlParameter.Optional } // 參數默認值 );
在第一次迭代裏,咱們建立了Contact Manager 的各項基本功能(增刪改查),充分利用了vs2010的自動生成Controller和view的強大,也體會到了ef框架帶給咱們的便利。
在下一次的迭代中,咱們將修改母版頁的css來提高應用體驗。還有咱們將爲表單添加驗證等……