上一節我們創建了自己的第一個MVC3項目,並了解了Controller和View的添加方法。今天我們將仿照大米返利網注冊模塊寫個小例子,來進一步了解Model、Action、Form等相關內容。
【情景假設】
- 首頁--歡迎頁面,簡單介紹大米返利網,並提供注冊鏈接;
- 注冊--用戶使用網站之前要先注冊為會員,注冊頁面還要對用戶填寫的信息進行有效性驗證;
- 注冊完成--完成之后會跳轉到一個提示頁面,並向用戶郵箱發送一封郵件。
一. 首頁
1. 將上一節的Index頁面用作首頁,再添加一些說明文字。
首頁 View代碼
ViewBag.Title = "首頁";
}
< h2 >@ViewBag.hello </ h2 >
< p >大米返利網提供淘寶網等多家商城的返現優惠, < br />
返現比例高,提現速度快,注冊贈1元,滿3元提現。 </ p >
< p >點此注冊 </ p >
接下來我們就要為“點此注冊”提供鏈接頁面了。
二. 添加注冊頁面
1. 創建數據Model
MVC中的M代表的領域模型,是應用程序中極其重要的部分之一,一個設計完好的MVC項目往往從設計完好的model開始,然后在此基礎上繼續添加controller和view。在我們的項目中,model是對現實世界對象的封裝,定義規則、處理等等。具體實現時Model一般就是對項目中通用性對象的屬性、方法進行封裝而來的C#類,然后controller和view以一定的方式暴露給客戶端。
接下來我們添加一個用戶信息的model類:右鍵models文件夾->Add->Class->UserInfo.cs->Ok.
UserInfo.cs Code
/// 注冊用戶實體
/// </summary>
public class UserInfo
{
/// <summary>
/// 自動編號
/// </summary>
public int Id { get; set; }
/// <summary>
/// 用戶名
/// </summary>
public string UserName { get; set; }
/// <summary>
/// 密碼(明文簡單示例)
/// </summary>
public string Password { get; set; }
/// <summary>
/// qq號碼
/// </summary>
public string QQ { get; set; }
/// <summary>
/// 郵箱地址
/// </summary>
public string Email { get; set; }
}
2. 添加Action
在IndexController中添加新的action:
public ActionResult Register()
{
return View();
}
3. 添加強類型View
- 創建view:強類型view目的是展現針對具體類型的實體,指定具體類型之后MVC會為其提供許多快捷的操作。需要注意的是,在添加強類型View之前,我們要先編譯整個MVC項目,否則添加View時就會找不到先前添加的UserInfo實體。
添加步驟:
在Register Action代碼塊內右鍵->Add View->選中 Create a strongly type view復選框->Model class下拉框選擇UserInfo->提供的模板選擇Empty->Add。如下圖所示:
添加完成之后我們發現新添加的View是以@model的Razor代碼開頭的。接下來我們將會看到,這正式強類型view以及它能提供諸多便捷的關鍵所在。
三、編輯表單
1. View代碼
@using(Html.BeginForm())
{
< p >用戶名: @Html.TextBoxFor(m=>m.UserName) </ p >
< p >密碼:@Html.PasswordFor(m=>m.Password) </ p >
< p >確認密碼:@Html.PasswordFor(m=>m.Password) </ p >
< p >QQ:@Html.TextBoxFor(m=>m.QQ) </ p >
< p >Email:@Html.TextBoxFor(m=>m.Email) </ p >
< input type ="submit" value ="馬上注冊" />
}
這里用的是Razor語法,使用過程中VS為我們提供了豐富的智能感知。以前不熟悉的同學可能會看着滿眼的@符號不太自在,用一段時間就該上癮了,因為它真的很好上手。運行效果如下:
2. Html幾個helper方法:
首先,我們看一下頁面源代碼:
頁面源代碼
< form action ="/index/register" method ="post" >
< p >用戶名: < input id ="UserName" name ="UserName" type ="text" value ="" /></ p >
< p >密碼: < input id ="Password" name ="Password" type ="password" /></ p >
< p >確認密碼: < input id ="Password" name ="Password" type ="password" /></ p >
< p >QQ: < input id ="QQ" name ="QQ" type ="text" value ="" /></ p >
< p >Email: < input id ="Email" name ="Email" type ="text" value ="" /></ p >
< input type ="submit" value ="馬上注冊" />
</ form >
- 不難看出,通過Razor語法中的Html helper方法,將Model中的屬性用Input控件形式展現出來了。例如
生成html時,input控件type=”text”, id和name屬性都被賦值為"UserName“。對應html代碼為:
- 對於強類型view,書寫lamda語法時有着豐富的智能感知。如果不想寫成lamda形式,還可以這樣 @Html.TextBoxFor(“UserName”)
- Html.BeginForm:
代碼格式為@using(Html.BeginForm()){ …},通常使用using關鍵字是為了走出花括號時釋放較占資源的對象,而在這里可以理解為關閉<form>標簽。生成form屬性時,默認的action會提交回當前的url,而method默認設置為post。最終生成的html源碼為:<form action="/index/register" method="post"> ……</form>。
另外,在WebForm開發時,每個頁面只允許使用一個服務端form,並且包含ViewState以及postback邏輯,而在MVC中是沒有服務器端form這個概念的,沒有ViewState以及postback機制,每個頁面可以放置多個form。
- Html.ActionLink:用來添加action頁面的鏈接,我們可以在首頁為“點此注冊”添加鏈接:
四. 表單提交
1. HttpGet和HttpPost:
為了接收並處理提交的表單數據,我們還需要再添加一個Register action,這兩個action的作用是:
- 一個用來響應Http Get請求: 為action添加HttpGet特性(也可以省略),Get請求通常是用戶第一次訪問頁面時,通過該action初始化空白表單。
- 一個用來響應Http Post請求:為acton方法添加HttpPost特性,Html.BeginForm()創建的窗體默認被瀏覽器處理為Post請求。這個版本的action方法負責接收提交的表單數據並進行相應處理。
public ActionResult Register()
{
return View();
}
[HttpPost]
public ActionResult Register(UserInfo userInfo)
{
return View("Complete",userInfo);
}
2.Model Binding
在上面的post方法中,使用了MVC中一個非常不錯的特性---Model Binding,它可以解析傳來的數據並將其對應到領域模型的屬性。其實這個Model Binding過程是雙向的,當創建form數據時,input控件的值是根據與其name對應的model屬性來賦值的;反過來,當提交form表單時,通過model binding又可以根據input控件的name屬性來為model實體同名的屬性賦值,進而提交到post action方法。
五、表單驗證
在MVC應用程序中,我們一般把驗證添加在model實體而不放在用戶界面,這樣只要我們在一處定義了驗證規則便可以多處生效。ASP.NET MVC總具體實現方式是:使用System.ComponentModel.DataAnnotations 中定義的特性,將其聲明在model屬性作為驗證規則就可以生效了。
1. Model實體添加驗證規則
Model Validation Code
namespace DamifanliMvc3.Models
{
/// <summary>
/// 注冊用戶實體
/// </summary>
public class UserInfo
{
/// <summary>
/// 自動編號
/// </summary>
public int Id { get; set; }
/// <summary>
/// 用戶名
/// </summary>
[Required(ErrorMessage = " 請輸入用戶名 ")]
[RegularExpression( " ^[a-zA-Z][a-zA-Z0-9]{2,14}$ ", ErrorMessage = " 請輸入3-15位字母或數字 ")]
public string UserName { get; set; }
/// <summary>
/// 密碼(明文簡單示例)
/// </summary>
[Required(ErrorMessage = " 請輸入密碼 ")]
public string Password { get; set; }
/// <summary>
/// qq號碼
/// </summary>
[Required(ErrorMessage = " 請輸入QQ號碼 ")]
[RegularExpression( " [1-9][0-9]{4,} ",ErrorMessage = " 請輸入正確的qq號碼 ")]
public string QQ { get; set; }
/// <summary>
/// 郵箱地址
/// </summary>
[Required(ErrorMessage = " 請輸入郵箱地址 ")]
[RegularExpression( @" \w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)* ",ErrorMessage = " 請輸入正確的郵箱地址 ")]
public string Email { get; set; }
}
}
2.ModelState.IsValid
我們可以在Controller中使用ModelState.IsValid來檢驗是否存在驗證問題。
{
if ( ModelState.IsValid)
{
return View( " Complete ", userInfo); // Complete Action后續創建
}
return View();
}
3.錯誤提示
當用戶輸入不符合規則時,我們可以在view中使用Html.ValidationSummary()來提示用戶。
{
@Html.ValidationSummary()
<p>用戶名:@Html.TextBoxFor(m=>m.UserName)</p>
……
}
該方法會在頁面中放置一系列隱藏的li,MVC可以令這些位置可見並顯示model驗證屬性中定義的錯誤信息,如下圖所示。點擊注冊按鈕時該頁面不會進行跳轉,直到所有輸入都符合規范為止。值得慶幸的是,提交失敗時之前填寫的數據仍然會保留在頁面中。
查看頁面源代碼:
用戶名: < input class ="input-validation-error" data-val ="true" data-val-regex ="請輸入3-15位字母或數字" data-val-regex-pattern ="^[a-zA-Z][a-zA-Z0-9]{2,14}$" data-val-required ="請輸入用戶名" id ="UserName" name ="UserName" type ="text" value ="" />
</ p >
六、注冊完成頁面
1.添加Complete View:
在前面的post提交的Register中,我們已經給出了注冊完成時要跳轉的目標”Complete”,並且傳遞了變量userInfo,接下來我們添加一個強類型UserInfo類型的View。
修改代碼如下:
@{
ViewBag.Title = "注冊完成";
}
< h2 >注冊完成 </ h2 >
< p >
恭喜,您已注冊成功,請妥善保管注冊信息: < br />
賬號:@Model.UserName < br />
QQ:@Model.QQ < br />
Email:@Model.Email < br />
大米返利網祝您購物愉快!
</ p >
2. 發送郵件通知
@{
try
{
WebMail.SmtpServer = "smtp.sina.com";
WebMail.SmtpPort = 587;
WebMail.EnableSsl = true;
WebMail.UserName = "CathyChen";
WebMail.Password = "damifanli";
WebMail.From = "cathychen@sina.com";
WebMail.Send(@Model.Email,"成功注冊大米返利網",@Model.UserName+",您已成功注冊大米返利網,祝您購物愉快!");
}
catch
{
@:抱歉,通知郵件發送失敗!
}
}
小結:
到這里,今天的學習基本結束了。當然了這只是一個簡單的示例,實際使用中還有很多可以改進的地方,比如將發送郵件功能放在單獨的模塊中調用而不是將代碼塊嵌在View中,以便重復使用;另外,這里的錯誤處理使用的try…catch,其實可以跳轉到單獨的錯誤頁面。






