天天看点

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

继续阅读