作者:[美]Adam Freeman 來源:《精通ASP.NET MVC 4》ASP.NET MVC 是微軟的一個 Web開發框架,它整合了“模型—視圖—控制器(MVC)”架構的高效與整潔、敏捷開發的最新的思想與技術以及當前ASP.NET 平臺的精華部分。ASP.NET MVC 可以完全替代傳統的....
作者:[美]Adam Freeman 來源:《精通ASP.NET MVC 4》
ASP.NET MVC 是微軟的一個 Web開發框架,它整合了“模型—視圖—控制器(MVC)”架構的高效與整潔、敏捷開發的最新的思想與技術以及當前ASP.NET 平臺的精華部分。ASP.NET MVC 可以完全替代傳統的 ASP.NET Form,除了一些微不足道的 Web 小項目之外,在各種 Web 開發項目中都有明顯的優勢。
廢話不多說,開始第一個MVC應用程式吧。
1.準備工作站:
Visual Studio 2012,初學的話也可以使用微軟提供的免費版 Visual Studio Express 2012 For Web 。
2.創建 ASP.NET MVC 新項目
(1)創建 ASP.NET MVC 新項目 PartyInvites,模板為 Empty 。【 New(新建) -> Project(項目) -> New Project(新項目)】
(2).添加第一個控制器,命名為 HomeController 【右擊Controller文件夾 -> Add(添加) -> Controller(控制器)】
(3). VS 會在Controller 文件夾中創建一個 HomeController.cs 文件
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; namespace PartyInvites.Controllers { public class HomeController : Controller { public ActionResult Index() { return View(); } } }
(4).修改代碼代碼如下:
public class HomeController : Controller { public string Index() { return "Hello,MVC"; } }
(5).按 F5 調試,顯示效果如下:
3.渲染 Web 頁面
上面輸出的只是一個字元串"Hello,MVC"。為了產生一個隊瀏覽器請求進行相應的HTML,需要創建一個視圖(View)。
(1)首先修改 Index 動作方法
public class HomeController : Controller { /*在MVC體系架構中,傳入的請求是由控制器(Controller)處理的。 在控制器中的每一個 public 方法都稱為一個動作方法 (Action Method),即可以用某個 URL 通過 Web 來調用它,以執行一個動作*/ public ViewResult Index() { //這裡返回一個視圖。 //視圖是通過命名約定與動作方法相關聯的。這個動作叫做"Index",控制器叫做"Home"。 return View(); } }
(2)這時運行調試,MVC會視圖在"Views"文件夾中查找有這個名字的不同文件。
(3)創建視圖文件 Index.cshtml 【右擊 Index 動作方法(在方法名上或者方法體內) -> 添加視圖】
(4)簡單修改視圖文件,顯示文字 "Hello,MVC (Form the view)"
@{ Layout = null; } <!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width" /> <title>Index</title> </head> <body> <div> Hello,MVC (Form the view) </div> </body> </html>
(5)運行效果如下
(6)添加動態輸出,修改HomeController.cs 文件 Index 方法
public ViewResult Index() { int hour = DateTime.Now.Hour; //ViewBag 是一種動態對象,Greeting 屬性知道給其賦值的那一刻才會存在,其屬性名 Greeting 可以用任意屬性名來替代它,它會一樣工作 //這裡將一個值給 ViewBag.Greeting 屬性時,便是為視圖提供數據。 ViewBag.Greeting = hour < 12 ? "Good morning" : "Good afternoon"; return View(); }
(7)修改 Index.cshtml 文件
@{ Layout = null; } <!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width" /> <title>Index</title> </head> <body> <div> Hello,MVC @ViewBag.Greeting (Form the view) </div> </body> </html>
(8)運行效果如下
PS:Web 頁面從伺服器到瀏覽器的整個呈現的過程分為三步:
第一步是通過視圖引擎對視圖文件進行解析,將視圖文件中的代碼轉換成 HTML 標記,這一步叫做渲染。 第二步是將渲染後的 HTML 標記傳遞給客戶瀏覽器,這一步是頁面的傳遞。 第三步是瀏覽器接收到 HTML 後對其進行處理並呈現為 Web 頁面,這一步叫做呈現。 渲染是把頁面的非 HTML 代碼(控制項、頁面代碼等)轉換成 HTML 標記,這一步是由伺服器完成的。 而呈現是將 HTML 顯示成 Web 頁面,這一步工作是由瀏覽器完成的。
4. 創建一個簡單的數據錄入應用程式
(1)設置場景如下:
設想一個朋友要主辦一個“新年除夕晚會”,需要創建一個 Web 網站,以便讓被邀請人進行 RSVP(電子回覆)。這個網站需要以下四個關鍵特性: * 一個顯示此晚會信息的主頁; * 一個可以用來進行 RSVP 的表單; * 對 RSVP 表單的驗證,它將顯示一個"謝謝你"的頁面; * 當完成 RSVP 時,給晚會的主人發送一份電子郵件。(2)添加模型類 GuestResponse 【右擊 Models 文件夾 -> "添加" -> "類"】
public class GuestResponse { public string Name { get; set; } public string Email { get; set; } public string Phone { get; set; } //這裡設置WillAttend為一個 可空的的bool類型,意味著它可以是 true、false、null public bool? WillAttend { get; set; } }
(3)鏈接動作方法
a.添加一個指向 RSVP 表單的鏈接
@{ Layout = null; } <!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width" /> <title>Index</title> </head> <body> <div> Hello,MVC @ViewBag.Greeting (Form the view) <p>We're going to have an exciting party.<br /> You can letter us by clicking the link @Html.ActionLink("RSVP Now","RsvpForm")</p> </div> </body> </html>
PS:Html.ActionLink 是一個 HTML 輔助器方法,其作用是渲染一個超鏈接的 HTML 標記
b.如果現在點擊這個鏈接,會看到404錯誤,這是因為還沒有創建與這個/Home/RsvpForm 地址所對應的方法。可以把一個名為"RsvpForm"的方法加到 HomeController 類。
public class HomeController : Controller { public ViewResult Index() { int hour = DateTime.Now.Hour; ViewBag.Greeting = hour < 12 ? "Good morning" : "Good afternoon"; return View(); } public ViewResult RsvpForm() { return View(); } }
c.添加一個強類型視圖 RsvpForm 【右擊方法名 -> 添加視圖】
@model PartyInvites.Models.GuestResponse @{ Layout = null; } <!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width" /> <title>RsvpForm</title> </head> <body> <div> </div> </body> </html>
PS: 強類型視圖意在渲染一個特定的域類型,如果指定了想使用的類型,MVC將能夠創建便於使用這個類型的便捷手段。
(4)建立表單,修改 RsvpForm.cshtml 視圖文件如下
@model PartyInvites.Models.GuestResponse @{ Layout = null; } <!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width" /> <title>RsvpForm</title> </head> <body> @using (Html.BeginForm()) { <p>Your name:@Html.TextBoxFor(x => x.Name)</p> <p>Your email:@Html.TextBoxFor(x => x.Email)</p> <p>Your phone:@Html.TextBoxFor(x => x.Phone)</p> <p> Will you attend? @Html.DropDownListFor(x => x.WillAttend, new[] { new SelectListItem() { Text = "Yes, I'll be there", Value = bool.TrueString }, new SelectListItem() { Text = "No, I can't come", Value = bool.FalseString } }, "Choose an option") </p> <input type="submit" value="Submit RSVP" /> } </body> </html>
(5)處理表單
a.在 HomeController 控制器類中添加一個支持POST請求的動作方法
using PartyInvites.Models; using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; namespace PartyInvites.Controllers { public class HomeController : Controller { public ViewResult Index() { int hour = DateTime.Now.Hour; ViewBag.Greeting = hour < 12 ? "Good morning" : "Good afternoon"; return View(); } [HttpGet] //GET 請求是某人點擊一個鏈接時瀏覽器正常發出的請求。 //當有人第一次訪問/Home/RsvpForm 時,這個動作版本負責顯示最初的空白表單 public ViewResult RsvpForm() { return View(); } [HttpPost] //預設情況下,用 Html.BeginForm() 渲染的表單是由瀏覽器作為一個 POST 請求遞交的。 //這個動作版本負責接受所遞交的數據,並決定用它做什麼。 public ViewResult RsvpForm(GuestResponse guestResponse) { //TODO:對晚會的組織者發送 Email 響應 //這個View 方法的調用告訴MVC,查找一個名為"Thanks"的視圖,並把GuestResponse 對象傳遞給這個視圖 return View("Thanks",guestResponse); } } }
b.右擊方法名創建強類型視圖 Thanks
c.修改視圖文件Thanks.cshtml
@model PartyInvites.Models.GuestResponse @{ Layout = null; } <!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width" /> <title>Thanks</title> </head> <body> <div> <h1>Thank you, @Model.Name!</h1> @if (Model.WillAttend == true) { @:It's great that you're coming. The drinks are already in the fridge! } else { @:Sorry to hear that you can't make it, but thanks for letting us know. } </div> </body> </html>
d.運行程式,效果如下:
(6)添加驗證。現在,到了對應用程式添加驗證的時候了。如果不做此事,用戶可能會輸入無意義的數據,甚至遞交一個空白表單。
ASP.NET MVC 支持驗證規則聲明,驗證規則是以 System.ComponentModel.DataAnnotations 命名空間中的註解屬性進行定義的。
a.修改 GuestResponse 模型類如下:
using System.ComponentModel.DataAnnotations; namespace PartyInvites.Models { public class GuestResponse { [Required(ErrorMessage="Please enter your name")] public string Name { get; set; } [Required(ErrorMessage="Please enter your email address")] [RegularExpression(".+\\@.+\\..+",ErrorMessage="Please enter a valid email address")] public string Email { get; set; } [Required(ErrorMessage = "Please enter your phone number")] public string Phone { get; set; } [Required(ErrorMessage = "Please specify whether you'll attend")] //WillAttend 屬性使用了一個可空的 bool 類型就是為了可以運用 Required 驗證註解屬性 public bool? WillAttend { get; set; } } }
b.修改 RsvpForm 的POST 方法
[HttpPost] public ViewResult RsvpForm(GuestResponse guestResponse) { if (ModelState.IsValid) { return View("Thanks", guestResponse); } else { //有驗證錯誤 return View(); } }
c.在 RsvpForm 視圖中使用 Html.ValidationSummary (驗證摘要)輔助器方法可以完成這種工作。
<body> @using (Html.BeginForm()) { @Html.ValidationSummary() <p>Your name: @Html.TextBoxFor(x => x.Name)</p> <p>Your email: @Html.TextBoxFor(x => x.Email)</p> <p>Your phone: @Html.TextBoxFor(x => x.Phone)</p> <p> Will you attend? @Html.DropDownListFor(x => x.WillAttend, new[] { new SelectListItem() { Text = "Yes, I'll be there", Value = bool.TrueString }, new SelectListItem() { Text = "No, I can't come", Value = bool.FalseString } }, "Choose an option") </p> <input type="submit" value="Submit RSVP" /> } </body>
d.運行效果如下:
e.一般我們需要高亮無效欄位,這裡用CSS文件實現,新建文件夾 Content ,併在文件夾中新建樣式文件 Site.css 如下,並引用
field-summary-error { color: #f00; } field-summary-valid { display: none; } .input-validation-error { border: 1px solid #f00; background-color: #fee; } .validation-summary-errors { font-weight: bold; color: #f00; } validation-summary-valid { display: none; }
(7)完成示例
這個示例應用程式的最後需求是,將完成了的 RSVP 用電子郵件發給邀請的賓客和晚會的組織者。可以添加一個動作方法,使用.NET 框架的 E-mail 類來創建併發送一份郵件消息,以完成這一任務。
a.這裡使用 WebMail 輔助器,修改 thanks.cshtml 視圖文件如下:
@model PartyInvites.Models.GuestResponse @{ Layout = null; } <!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width" /> <title>Thanks</title> </head> <body> <div> @{ try { WebMail.SmtpServer = "smtp.example.com";//傳送電子郵件的 STMP 伺服器的名稱 WebMail.SmtpPort = 587; //SMTP 事務的埠 WebMail.EnableSsl = true;//設置在發送電子郵件時使用安全套接字層(SSL)來加密鏈接 WebMail.UserName = "mySmtpUsername";//用於發送電子郵件的電子郵件賬戶名 WebMail.Password = "mySmtpPassword";//設置發件人電子郵件賬戶的密碼 WebMail.From = "[email protected]";//設置發件人的電子郵件地址 WebMail.Send("[email protected]","RSVP Notification",Model.Name+" is "+((Model.WillAttend??false)?"":"not")+" attending"); } catch (Exception) { @:<b> Sorry - We couldn't send the email to confire your RSVP.</b> } } <h1>Thank you, @Model.Name!</h1> @if (Model.WillAttend == true) { @:It's great that you're coming. The drinks are already in the fridge! } else { @:Sorry to hear that you can't make it, but thanks for letting us know. } </div> </body> </html>
b.運行程式,收到消息郵件如下
(8) 源代碼:PartyInvites.zip