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="row-@item.RecordId">
<td>
@Html.ActionLink(item.Album.Title, "Details", "Store", new { id = item.AlbumId }, null)
</td>
<td>
@item.Album.Price
</td>
<td id="item-count-@item.RecordId">
@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)生成购物项名称,并带有链接到该项的详细信息的超链接。