Asp.net MVC前兩年就聽說了,但一直沒有去用,中間只是粗略的了解了下,在前段時間做的欄目改版時才真正的去學習和使用——剛開始學,對其'路由'和請求解析執行的過程感覺比較神秘,但隨着項目中的應用、功能的逐一實現,發現所謂的Asp.net MVC也就那樣,清楚了核心的幾點東西,就可以比較'得心應手'的玩轉了。這篇博客就是要跟大家分享下:我所了解的Asp.net MVC和如何靈活使用!
本文目錄:
- 什么是ASP.NET MVC
- Asp.net MVC與傳統WebForm的主要區別
- 創建一個MVC應用程序並運行
- Controller,Model,View的介紹及關聯
- Global.asax 路由注冊及注意
- 路由或請求參數的獲取及路由調試
- 提交數據模型驗證
- MVC主要表單標簽類的用法介紹
- Ajax請求實現及返回Json對象
什么是ASP.NET MVC
MVC:Model-View-Controller,模型-視圖-控制器模式
Asp.net MVC是微軟的開發基於MVC開發的一個易於被測試的框架.它具有以下特性:
沒有數據回傳
沒有在頁面中保存視圖狀態
開發者可以完全掌控頁面的呈現過程
易於單元測試
易於測試驅動開發
可擴展、可替換
支持WebForm中的有關特性,如:用戶控件、母版頁、數據綁定、本地化等
不在基於文件目錄結構,而是將URL映射到控制器中
Asp.net MVC與傳統WebForm的主要區別
1.Asp.net MVC不再有傳統WebForm中的控件,於是開發人員不用再去了解每個控件的使用和其諸多事件的用法及響應順序等,降低了開發人員入門的難度,也讓web開發回歸原始——就是客戶端發送請求request,服務端響應response,類似於jsp,php...
2.Asp.net MVC易於測試,且相對傳統WebForm應用程序(目錄)結構更加清晰、頁面更加'干凈'。
創建一個MVC應用程序並運行
創建一個MVC應用程序,如下圖:
運行,如圖:
注:與傳統WebForm應用程序不同的是:1.不能設置起始頁——設置了也沒用,真正的起始頁是由路由和DefaultController決定的。
2.不能在vs和iis中瀏覽某個view頁面,只能在調試中執行。
Controller,Model,View的介紹及關聯
首先,對於一個URL請求,如:http://xysj.s187.com/storeclaim,應用程序會根據Global.asax文件里的路由配置,如下代碼:
1 routes.MapRoute("storeclaim", "storeclaim/{action}/{storename}/{pagenum}", new
2 {
3 controller = "storeclaim",
4 action = "Index",
5 storename = "",
6 pagenum = 1
7 });
找到最匹配的路由配置項,上面的路由已經限定了此路由請求的控制器是StoreClaimController(MVC控制器解析規則是:控制器名稱+Controller),並在參數url("storeclaim/{action}/{storename}/{pagenum}")中限定了匹配此路由的請求必須是以 當前網站域名/storeclaim 格式的Url,以上路由如果改為如下:
1 routes.MapRoute("storeclaim", "storeclaimoper/{action}/{storename}/{pagenum}", new 2 { 3 controller = "storeclaim", 4 action = "Index", 5 storename = "", 6 pagenum = 1 7 });
當請求http://xysj.s187.com/storeclaimoper Url時,實現的效果是一樣,因為請求的URl由哪個控制器處理是由 路由配置對象中的 controller = "storeclaim" 此行代碼決定的,
根據URl找到匹配的路由,並分析出了處理此請求的控制器,此時就需要清楚該由控制器中的那個action(操作)處理響應請求——上面的url因為沒有(傳遞或者說是附加)action路由參數,就
會根據 路由配置對象中的 action = "Index" 此行代碼,在StoreClaimController控制器類中找到名字為Index的方法
1 /// <summary>
2 /// 商家入駐控制器
3 /// </summary>
4 public class StoreClaimController : ControllerBase
5 {
6 public ActionResult Index()
7 {
8 CityCode city = GetCityInfo(Request);
9 StoreClaimStepModel model = new StoreClaimStepModel(city, this.Request.Cookies, this.RouteData.Values);
10 return View("xystoreinfo", model);
11 }
12 }
看上面代碼, return View("xystoreinfo", model); ——這行代碼,就是根據請求響應的一個View頁面,其中的View方法:第一個參數是指定了View的名稱,應用程序會根據當前
控制器的名稱在 View文件夾/當前控制器的名稱文件夾 下找到xystoreinfo名稱的View頁面,如圖:
;第二個參數是View頁面需要的數據模型實體對象(此對象可以用於呈現編輯或瀏覽產品詳情、列表等)。
看上圖紅色的區域,你就發現一個很熟悉的東西:泛型,是的,Asp.net MVC在創建視圖的時可以選擇強類型 設置此View的數據模型,如下圖
這樣就可以在View頁面中很方便的使用或呈現數據模型中的可訪問到的屬性或方法等,如:<%=Model.AssignedStoreId %>。
Global.asax 路由注冊及注意
1.路由的配置一定要將最深層次、精准的路由寫在前面,就像在捕獲代碼異常時:一定要將子(類)異常寫在最上面,如:

1 try
2 {
3 int a = 0;
4 a = 5 / a;
5 }
6 catch (InvalidOperationException ex)
7 {
8 throw ex;
9 }
10 catch (Exception ex)
11 {
12 throw ex;
13 }
對於路由,則是:

1 public static void RegisterRoutes(RouteCollection routes)
2 {
3 routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
4
5 routes.MapRoute(
6 "newroute", // 路由名稱
7 "{controller}/{action}/{keyword}/{pagenum}", // 帶有參數的 URL
8 new { controller = "Message", action = "GetList", keyword = "", pagenum = UrlParameter.Optional } // 參數默認值
9 );
10 routes.MapRoute( //此路由 相當於是最父級路由,一般寫在路由注冊的最后,避免覆蓋其它的自定義路由
11 "Default", // 路由名稱
12 "{controller}/{action}/{id}", // 帶有參數的 URL
13 new { controller = "Home", action = "Index", id = UrlParameter.Optional } // 參數默認值
14 );
15 }
2.每個注冊路由的路由配置對象中的 controller = "Message", action = "GetList" 這兩個屬性值必須要設置!
路由或請求參數的獲取及路由調試
1.路由參數的獲取,如下:

1 #region 路由參數獲得判斷
2 RouteValueDictionary dictRouteValue = this.RouteData.Values;
3 object routeValue = null;
4 string storeName = string.Empty;
5 if (dictRouteValue.TryGetValue("storename", out routeValue))
6 {
7 storeName = routeValue.ToString().Trim();
8 }
9 //如果參數 商家簡稱為空
10 if (routeValue == null || string.IsNullOrEmpty(storeName))
11 return null;
12 int pageNum = 1;
13 if (dictRouteValue.TryGetValue("pagenum", out routeValue))
14 {
15 pageNum = Convert.ToInt16(routeValue);
16 pageNum = pageNum <= 0 ? 1 : pageNum;
17 }
18 #endregion
2.路由中的 路由參數 不能從 Request中獲得,非路由參數的請求參數可以在Request對象中獲得,具體方式與WebForm中相同。
3.路由調試,即可以測試(指定)URl請求是否成功被某個路由配置匹配捕獲,此需要添加RouteDebug.dll程序集的引用,文后會附上此dll的下載。
提交數據模型驗證
此部分,我不想多說,你只需要新建一個帶有示例的MVC3應用程序 或 創建一個 支架模版為Edit或Create的視圖就可以比較清楚的其具體應用。看如下代碼,不得不說的是:MVC3
里的數據模型驗證還是挺不錯的!

1 public class ChangePasswordModel
2 {
3 [Required]
4 [DataType(DataType.Password)]
5 [Display(Name = "當前密碼")]
6 public string OldPassword { get; set; }
7
8 [Required]
9 [StringLength(100, ErrorMessage = "{0} 必須至少包含 {2} 個字符。", MinimumLength = 6)]
10 [DataType(DataType.Password)]
11 [Display(Name = "新密碼")]
12 public string NewPassword { get; set; }
13
14 [DataType(DataType.Password)]
15 [Display(Name = "確認新密碼")]
16 [Compare("NewPassword", ErrorMessage = "新密碼和確認密碼不匹配。")]
17 public string ConfirmPassword { get; set; }
18 }

1 <%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<MVC3_Test.Models.ChangePasswordModel>" %>
2
3 <asp:Content ID="changePasswordTitle" ContentPlaceHolderID="TitleContent" runat="server">
4 更改密碼
5 </asp:Content>
6
7 <asp:Content ID="changePasswordContent" ContentPlaceHolderID="MainContent" runat="server">
8 <h2>更改密碼</h2>
9 <p>
10 請使用以下表單更改密碼。
11 </p>
12 <p>
13 新密碼必須至少包含 <%: Membership.MinRequiredPasswordLength %> 個字符。
14 </p>
15
16 <script src="<%: Url.Content("~/Scripts/jquery.validate.min.js") %>" type="text/javascript"></script>
17 <script src="<%: Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js") %>" type="text/javascript"></script>
18
19 <% using (Html.BeginForm()) { %>
20 <%: Html.ValidationSummary(true, "密碼更改不成功。請更正錯誤並重試。") %>
21 <div>
22 <fieldset>
23 <legend>帳戶信息</legend>
24
25 <div class="editor-label">
26 <%: Html.LabelFor(m => m.OldPassword) %>
27 </div>
28 <div class="editor-field">
29 <%: Html.PasswordFor(m => m.OldPassword) %>
30 <%: Html.ValidationMessageFor(m => m.OldPassword) %>
31 </div>
32
33 <div class="editor-label">
34 <%: Html.LabelFor(m => m.NewPassword) %>
35 </div>
36 <div class="editor-field">
37 <%: Html.PasswordFor(m => m.NewPassword) %>
38 <%: Html.ValidationMessageFor(m => m.NewPassword) %>
39 </div>
40
41 <div class="editor-label">
42 <%: Html.LabelFor(m => m.ConfirmPassword) %>
43 </div>
44 <div class="editor-field">
45 <%: Html.PasswordFor(m => m.ConfirmPassword) %>
46 <%: Html.ValidationMessageFor(m => m.ConfirmPassword) %>
47 </div>
48
49 <p>
50 <input type="submit" value="更改密碼" />
51 </p>
52 </fieldset>
53 </div>
54 <% } %>
55 </asp:Content>
MVC主要表單標簽類的用法介紹

1 <%=Html.Pager(Model.PageList, new PagerOptions
2 {
3 ContainerTagName = "span",
4 PageIndexParameterName = "pagenum",
5 AlwaysShowFirstLastPageNumber = true,
6 NumericPagerItemCount = 5,
7 HorizontalAlign = "right"
8 }, new
9 {
10 Style = "float:right;width:80%"
11 })%>

1 <%:Html.TextBoxFor(m => m.Name, new { style = "width: 70%", maxlength = "60" })%>
2 <%:Html.TextAreaFor(m => m.BusinessSphere, new { id="txtBusinessSphere",style="background-color: #ffffff; width: 70%; color: #000000" })%>
3 <%:Html.CheckBoxFor(m=>m.IsShow) %>
4 是否顯示
5 <%:Html.HiddenFor(m => m.HoursBegin)%>
Ajax請求實現及返回Json對象

1 _AjaxRequest("POST","/storeclaim/GetBulidingNum",function (data) {
2 if (!isLoadShow && (data == null || !data.IsSuc)) {
3 _ShowTipMes("所選建築物信息獲取失敗或不存在!");
4 return;
5 }
6 _storageData.Dict_BuildingNum[buildingID] = data;
7 dataObj=data;
8 },null,"bulidingId=" + buildingID,false);
9
10 //ajax請求方法(isAsync:是否是異步請求)
11 function _AjaxRequest(type, url, successFun, errorFun, data, isAsync) {
12 $.ajax({
13 type: type,
14 url: url,
15 async: isAsync,
16 data: data,
17 success: function (data) {
18 successFun && successFun(data);
19 },
20 error: function (data) {
21 errorFun && errorFun(data);
22 }
23 });
24 }

1 /// <summary>
2 /// 獲得指定建築物的樓層
3 /// </summary>
4 /// <returns></returns>
5 [HttpPost]
6 public ActionResult GetBulidingNum()
7 {
8 int bulidingId = this.GetFormInt("bulidingId");
9 if (bulidingId <= 0)
10 return null;
11 MapBuilding building = GetMapBuilding(bulidingId);
12 bool isSuc = building != null;
13 int floor = 0, subterranean = 0;
14 if (isSuc)
15 {
16 floor = building.Floor;
17 subterranean = building.Subterranean;
18 }
19 return Json(new { IsSuc = isSuc, Floor = floor, Subterranean = subterranean });
20 }
MVC3里提供了很方便的json數據對象構造方法Json:創建一個將指定對象序列化為 JavaScript 對象表示法 (JSON) 的 System.Web.Mvc.JsonResult 對象。
好了,比較匆忙的寫完了這篇已經拖了幾天的博客,感覺想把自己懂的東西寫的讓別人能比較容易看懂或者面面俱到並不是一件容易的事——正像這篇博客的標題,我寫的無論詳細好壞與否,也只能算是'道破',如果你想更深入的了解和學習,就得自己多用、多想、更全面的了解,也希望看了感覺有疑問或在Asp.net MVC3方面有更多了解的朋友,能大家一起交流學習!