Account 控制器包含了LogOn、LogOff、Register、ChangePassword、ChangePasswordSuccess这几个Action。每个Action都对应的有相应的View。
首先来看看LogOn的View。MVC Music Store这个案例使用的是MVC3,View部分采用的是Razor模板,Razor模板对应的View的后缀名为cshtml。
在Razor模板中,第一行代码的意思就是指定该模板所对应呈现数据的Model类型。例如:
@model MvcMusicStore.Models.LogOnModel
aspx模板写法:
<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage<MvcMusicStore.Models.LogOnModel>" %>
这种写法比老式的使用page指令的方式要少些很多的代码,并且更清晰明了。嘿嘿,看到Razor的这种模板之后,个人感觉非常爽!当然Razor模板不止这么点东西,查了下资料。请参考《Introducing “Razor” – a new view engine for ASP.NET 》,英文不好的可以查看《介绍“Razor”— ASP.NET的一个新视图引擎》。
第三行的代码一般如下:
@{
ViewBag.Title = "Log On";
}
这里给ViewBag.Title变量赋值。这个变量是在母版页Shared文件夹_Layout.cshtml中的标题部分设置文档标题用的变量。并且这个变量是.NET Framework 4.0的一个新的特性--动态表达式(动态表达式是在在运行的时候解析的)。简单的讲就是随时可以给某个对象添加一个属性并使用,而不需要向一起那样先声明才能使用。好东西,不过这种做法也有点让人小疑惑一把。因为第一次看这个的时候,找了半天都没找到这个变量是什么东西,还以为是ViewBag里面的已经声明好的变量,找到ViewBag定义查看的时候却什么都没有,ViewBag是个dynamic(动态类型参考)类型的变量。
LogOn.cshtml这个页面的部分代码说明:
1 @model MvcMusicStore.Models.LogOnModel
2
3 @{
4 ViewBag.Title = "Log On";
5 }
6
7 < h2 > Log On </ h2 >
8 < p >
9 Please enter your username and password. @Html.ActionLink("Register", "Register") if you don't have an account.
10 </ p >
11
12 < script src ="@Url.Content(" ~/Scripts/jquery.validate.min.js")" type ="text/javascript" ></ script >
13 < script src ="@Url.Content(" ~/Scripts/jquery.validate.unobtrusive.min.js")" type ="text/javascript" ></ script >
14
15 @Html.ValidationSummary(true, "Login was unsuccessful. Please correct the errors and try again.")
16
17 @using (Html.BeginForm()) {
18 < div >
19 < fieldset >
20 < legend > Account Information </ legend >
21
22 < div class ="editor-label" >
23 @Html.LabelFor(m => m.UserName)
24 </ div >
25 < div class ="editor-field" >
26 @Html.TextBoxFor(m => m.UserName)
27 @Html.ValidationMessageFor(m => m.UserName)
28 </ div >
29
30 < div class ="editor-label" >
31 @Html.LabelFor(m => m.Password)
32 </ div >
33 < div class ="editor-field" >
34 @Html.PasswordFor(m => m.Password)
35 @Html.ValidationMessageFor(m => m.Password)
36 </ div >
37
38 < div class ="editor-label" >
39 @Html.CheckBoxFor(m => m.RememberMe)
40 @Html.LabelFor(m => m.RememberMe)
41 </ div >
42
43 < p >
44 < input type ="submit" value ="Log On" />
45 </ p >
46 </ fieldset >
47 </ div >
48 }
第9行:@Html.ActionLink("Register", "Register") 意思是通过HTMLHelper对象产生一个链接到Register Action的超级连接标记。HTMLHelper对象是专门用于呈现HTML元素用的一个系统内置对象。
第12行:@Url.Content("~/Scripts/jquery.validate.min.js") 意思是通过URLHelper对象将括号内的服务器虚拟路径转换为绝对路径。URLHelper对象包含一系列专门处理MVC生产URL地址的方法。
第15行:@Html.ValidationSummary(true, "Login was unsuccessful. Please correct the errors and try again.") 意思是通过HTMLHelper对象,呈现出界面验证登陆出现错误后的消息。
第17行和第48行:@using (Html.BeginForm()) {意思是这其中的HTML代码将包含在表单当中。
第23行:@Html.LabelFor(m => m.UserName) 将来生成一个标签,里面的数据为模型中的UserName
第26行: @Html.TextBoxFor(m => m.UserName)生成一个文本框,里面的数据为模型中的用户名。
第27行:@Html.ValidationMessageFor(m => m.UserName)生成一个验证消息显示控件。
第34行:@Html.PasswordFor(m => m.Password) 生成一个密码框,用于模型中的密码呈现和输入。
第39行:@Html.CheckBoxFor(m => m.RememberMe)生成一个复选框,用于记住密码
Register.cshtml、ChangePassword.cshtml的代码与登陆界面的代码差不多,这里不过多的说明了。
CHeckout部分AddressAndPayment.cshtml、Complete.cshtml也都非常简单,即便上和上面的差不多。这里也不说明了。
Home部分Index.cshtml这个view中个循环提取代码:
@foreach (var album in Model)
{
< li >< a href ="@Url.Action(" Details", "Store",
new { id = album.AlbumId })" >
< img alt ="@album.Title" src ="@album.AlbumArtUrl" />
< span > @album.Title </ span > </ a >
</ li >
}
这里通过迭代model中每个album元素,并生成出对应的html标记呈现数据。
Shared文件夹部分的代码是整个站点共享View,保存了母版页、错误处理页面、以及Album编辑页面。
Album.cshtml、Error.cshtml页面都非常简单易懂,这里不做过多说明。
_Layout.cshtml中的代码:
< body >
< div id ="header" >
< h1 >< a href ="/" > ASP.NET MVC MUSIC STORE </ a ></ h1 >
< ul id ="navlist" >
< li class ="first" >< a href ="@Url.Content(" ~")" id ="current" > Home </ a ></ li >
< li >< a href ="@Url.Content(" ~/Store/")" > Store </ a ></ li >
< li > @{Html.RenderAction("CartSummary", "ShoppingCart");} </ li >
< li >< a href ="@Url.Content(" ~/StoreManager/")" > Admin </ a ></ li >
</ ul >
</ div >
@{Html.RenderAction("GenreMenu", "Store");}
< div id ="main" >
@RenderBody()
</ div >
< div id ="footer" >
built with < a href ="http://asp.net/mvc" > ASP.NET MVC 3 </ a >
</ div >
</ body >可以看出整个母版分为三个部分,头部、菜单、主体正文、脚部。
@{Html.RenderAction("GenreMenu", "Store");}用于请求GenreMenu Action生成出菜单。
@RenderBody()用于呈现将来的内容页面。
ShoppingCart购物车文件夹部分,两个视图,一个是CartSummary.cshtml、另一个是Index.cshtml。
CartSummary.cshtml只有一句代码
@Html.ActionLink("Cart (" + ViewData["CartCount"] + ")",
"Index",
"ShoppingCart",
new { id = "cart-status" })用于生成链接到购物车信息的链接。
Index.cshtml页面的javascript脚本比较多。
1 $( function () {
2 // Document.ready -> link up remove event handler
3 $( " .RemoveLink " ).click( function () {
4 // Get the id from the link
5 var recordToDelete = $( this ).attr( " data-id " );
6
7 if (recordToDelete != '' ) {
8
9 // Perform the ajax post
10 $.post( " /ShoppingCart/RemoveFromCart " , { " id " : recordToDelete },
11 function (data) {
12 // Successful requests get here
13 // Update the page elements
14 if (data.ItemCount == 0 ) {
15 $( ' #row- ' + data.DeleteId).fadeOut( ' slow ' );
16 } else {
17 $( ' #item-count- ' + data.DeleteId).text(data.ItemCount);
18 }
19
20 $( ' #cart-total ' ).text(data.CartTotal);
21 $( ' #update-message ' ).text(data.Message);
22 $( ' #cart-status ' ).text( ' Cart ( ' + data.CartCount + ' ) ' );
23 });
24 }
25 });
26
27 });这个部分的代码用于在Dom加载完毕的时候,生成移除购物车项链接按钮的移除购物项的处理事件。移除购物项需要ajax通知服务器的ShoppingCart控制器中的RemoveFromCart Action处理移除项内容。
handleUpdate()方法在该案例中没有使用到。。。
HTML部分代码:
@foreach (var item in Model.CartItems)
{
< tr id ="[email protected]" >
< td >
@Html.ActionLink(item.Album.Title, "Details", "Store", new { id = item.AlbumId }, null)
</ td >
< td >
@item.Album.Price
</ td >
< td id ="[email protected]" >
@item.Count
</ td >
< td >
< a href ="#" class ="RemoveLink" data-id ="@item.RecordId" > Remove from cart </ a >
</ td >
</ tr >
}此处用于提取模型中的购物项内容,并生成表格中的一行购物项。
@Html.ActionLink(item.Album.Title, "Details", "Store", new { id = item.AlbumId }, null)生成购物项名称,并带有链接到该项的详细信息的超链接。