天天看點

Asp.net MVC3 一語道破

  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.路由的配置一定要将最深層次、精準的路由寫在前面,就像在捕獲代碼異常時:一定要将子(類)異常寫在最上面,如:

View Code

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對象

Ajax請求js代碼

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           }      

響應action代碼

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 對象。

繼續閱讀