前面给SportsStore添加了分页的功能。接着我们添加导航控制,通过左边的菜单来分类显示数据。

首先修改SportsStore.WebUI.Models下的ProductsListViewModel.cs,增加一个CurrentCategory属性public string CurrentCategory{get;set;}。
接着修改List action方法,能够通过传入的CurrentCategory来过滤查询的产品列表。修改后的List action方法如下所示:

public ViewResult List(string category, int page = 1) { 

            ProductsListViewModel viewModel = new ProductsListViewModel            {                Products = repository.Products.Where(p => category == null || p.Category == category)                .OrderBy(p => p.ProductID)                .Skip((page - 1) * PageSize)                .Take(PageSize),                PagingInfo = new PagingInfo                {                    CurrentPage = page,                    ItemsPerPage = PageSize,                    TotalItems = category == null ? repository.Products.Count() : repository.Products.Where(e => e.Category == category).Count()                }            };            return View(viewModel);}

通过.where扩展方法我们进行了一个纵向的筛选,将指定Category的Product筛选出来。

重定义URL组合

之前我们看到了一种URl是这样的/?category=Soccer.在webform里面这个是常见的,但是在MVC里面,可以有更加优雅的方式来代替。我们需要修改global.asax.cs里面的RegisterRoutes方法。如下所示:

        public static void RegisterRoutes(RouteCollection routes)        {            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

            routes.MapRoute(null,"",//匹配空的URL                new { controller = "Product", action = "List", category = (string)null, page = 1 }                );

            routes.MapRoute(null,"Page{page}",new { controller = "Product", action = "List", category = (string)null },new { page = @"\d+" }//约束:页面必须是数字                );

            routes.MapRoute(null,"{category}",//匹配 /Football or /AnythingWithNoSlash                new { controller = "Product", action = "List", page = 1 }                );

            routes.MapRoute(null,"{category}/Page{page}",//匹配 /Football/Page567                new { controller = "Product", action = "List" },//默认                new { page = @"\d+" }//必须为数字

                );            routes.MapRoute(null,"{category}/Page{page}",//匹配/Football/Page567                new { controller = "Product", action = "List" },//默认                new { page = @"\d+" }//约束                );

            routes.MapRoute("Default", // 路由名称                "{controller}/{action}/{id}", // 带有参数的 URL                new { controller = "Product", action = "List", id = UrlParameter.Optional } // 参数默认值            );

        }

上面的集中组合分别代表以下集中URL的组合:


ASP.NET的路由系统(Routing System)被MVC用来处理来自客户端的请求,但是也会请求向外输出的符合我们URL组合的URL,以及我们能嵌入在web pages里面输出的URL。这样就能够保证URL在我们程序里面是一直不变的。对于路由这块,后面的章节有详细的讲解,所以如果我们这里不太明白,也没关系。

Url.Action方法是我们创建对外输出链接(outgoing links)最方便的一种方式,在List.cshtml里面已经使用过。由于我们需要添加支持对Category的筛选并且把数据传递给helper方法。如下所示:

@model SportsStore.WebUI.Models.ProductsListViewModel@{    ViewBag.Title = "Products";}<h2>    Product List</h2>@foreach (var p in Model.Products){@*    <div class="item">        <h3>@p.Name</h3>        @p.Description        <h4>@p.Price.ToString("c")</h4>    </div> *@    Html.RenderPartial("ProductSummary", p);}<div class="pager">    @Html.PageLinks(Model.PagingInfo, x => Url.Action("List", new { page = x, category = Model.CurrentCategory }))</div>

分页的链接是形如:http://<myserver>:<port>/Page2 的,这个表示显示所有Product里面的第2页。http://<myserver>:<port>/Chess/Page2这个就会只显示Category为Chess的Product。

绑定一个Category的导航菜单

我们需要显示一个导航的菜单共用户选择,然后显示对应的Product列表。并且我们会在多个Controller里面使用Category的列表,所以我们需要一个独立的,可重用的这样一个Category的列表。在ASP.NET MVC框架里面有子Action(child actions)的概念,对于创建一个可重用的导航控制菜单来说非常合适。child actions需要使用HTML的辅助方法RenderAction,它能够让我们包含一个对应view的action方法的输出。这里,我们可以创建一个新的Controller:NavController,并创建一个Menu的action方法,用来呈现一个导航菜单,并将来自action方法的输出注入到layout里面。

添加NavController,如下所示:

    public class NavController : Controller    {private IProductsRepository repository;public NavController(IProductsRepository repo)        {            repository = repo;        }

public PartialViewResult Menu(string category=null)        {            ViewBag.SelectedCategory = category;//这里使用的ViewBag将选中的Category传递给View。            IEnumerable<string> categories = repository.Products                .Select(x => x.Category)                .Distinct()                .OrderBy(x => x);return PartialView(categories);        }    }

因为要在所有的页面都使用这个导航菜单,所以需要注入到_layout里面,修改后的_layout如下所示:

<!DOCTYPE html><html><head>    <title>@ViewBag.Title</title>    <link href="@Url.Content("~/Content/Site.css")" rel="stylesheet" type="text/css" />    <script src="@Url.Content("~/Scripts/jquery-1.5.1.min.js")" type="text/javascript"></script></head><body>    <div id="header">        <div class="title">            Sports Store</div>    </div>    <div id="categories">        @{Html.RenderAction("Menu", "Nav");}    </div>    <div id="content">        @RenderBody()    </div></body></html>

Note:RenderAction()跟RenderPartial()一样,都是直接将内容写入Response Stream。

也就是意味着返回值是void,因此也就不能使用Razor里面的“@”标签,而是将它包括在@{}这样一个闭合的块里面。

如果你不喜欢这样,可以使用action方法来替代。
接着添加Menu的view,在Menu Controller上右键添加View,注意:这里的view是一个Partial view,类似webform里面的customer control.如下所示:

@model IEnumerable<string>@{    Layout = null;}@Html.ActionLink("Home", "List", "Product")@foreach (var link in Model){    @Html.RouteLink(link, new { controller = "Product", action = "List", category = link, page = 1 }, new { @class = link == ViewBag.SelectedCategory ? "selected" : null }) }

接着添加一个样式,如下所示:

View Code

DIV#categories A {     font: bold 1.1em "Arial Narrow","Franklin Gothic Medium",Arial; display: block;     text-decoration: none; padding: .6em; color: Black;     border-bottom: 1px solid silver; } DIV#categories A.selected { background-color: #666; color: White; } DIV#categories A:hover { background-color: #CCC; } DIV#categories A.selected:hover { background-color: #666; } 

在Menu的View里面有这样一个@classe用法,我们在匿名对象里使用@class作为一个新的参数传递给RouteLink方法。这里的“@”不是一个Razor的tag,我们使用了C#里面的一个功能,通过给class添加一个@符合来避免html里面的class和C#里面定义类的关键字class发生冲突。如果这里没有加上@符合,就会被C#编译器认为是定义了一个类。当我们添加了@符合后,编译就知道我们是在匿名类型里面添加的一个参数名为class的参数。这也正好达到了我们的期望。

今天的笔记就到这里。后面会创建简单的购物车,总得来说这个项目实例主要是让我们能够对MVC有一个实际的认识,项目里面一些具体实现,比如分页是全部读出来后分页的。这可能不符合实际的要求,但这不重要。重要的是,通过这个实例对MVC有整体的认识,通过具体操作能够对以后的实际项目的开发积累点经验。如果你是跟着我的笔记操作,出现什么问题,请留言!我是自己已经操作了一遍后,倒过来写笔记的,所以中间的一些步骤我会选择性的舍弃。

晚安!

《Pro ASP.NET MVC 3 Framework》学习笔记之十四【示例项目SportsStore】相关推荐

  1. ASP.NET MVC 3 Framework 学习笔记

    前段时间因项目需要对ASP.NET MVC3进行了系统的学习,完成项目后感觉对原书中有些知识点还有一些理解不够透彻的地方,因此将<Freeman A. Sanderson S. -  Pro A ...

  2. 《Pro ASP.NET MVC 3 Framework》学习笔记之十七【示例项目SportsStore】

    接下来是关于SportsStore的后台管理功能,也就是通常的CRUD操作. 首先添加一个AdminController,代码如下: View Code using System.Web.Mvc; u ...

  3. 《Pro ASP.NET MVC 3 Framework》学习笔记之十三【示例项目SportsStore】

    接着我们添加一个分页功能.修改ProductController,如下所示: public class ProductController : Controller {public int PageS ...

  4. 《Pro ASP.NET MVC 3 Framework》学习笔记之一【MVC的历程,优点,HelloWorld】

    序论:asp.net mvc出现已经有两三年的时间了(2009开始1.0版本),但是这么方面的中文学习资料仍然非常少,特别是asp.net mvc3,几乎就没有中文的学习书籍.在英文的书籍中有两本是非 ...

  5. ASP.Net MVC开发基础学习笔记(5):区域、模板页与WebAPI初步

    http://blog.jobbole.com/85008/ ASP.Net MVC开发基础学习笔记(5):区域.模板页与WebAPI初步 2015/03/17 · IT技术 · .Net, Asp. ...

  6. 《Pro ASP.NET MVC 3 Framework》英文原版教材个人勘误

    2011年6月27日,Apress今年比较吸引人的<Pro ASP.NET MVC 3 Framework>一书终于发布了. http://www.apress.com/978143023 ...

  7. Windows保护模式学习笔记(十四)—— 阶段测试

    Windows保护模式学习笔记(十四)-- 阶段测试 题目一 解题步骤 题目二 解题步骤 题目一 描述:给定一个线性地址,和长度,读取内容 int ReadMemory(OUT BYTE* buffe ...

  8. OpenCV学习笔记(十四):重映射:remap( )

    OpenCV学习笔记(十四):重映射:remap( ) 图像的坐标映射是通过原图像与目标图像之间建立一种映射关系,这种映射关系有两种,一种是计算原图像任意像素在映射后图像的坐标位置,另一种是计算变换后 ...

  9. QT学习笔记(十四):QLayout的属性介绍

    QT学习笔记(十四):QLayout的属性介绍 主要包括QBoxLayout.和QGridLayout以及QFormLayout等的参数类似. 我主要说明一下QGridLayout在QtDesigne ...

  10. MATLAB学习笔记(十四)

    MATLAB学习笔记(十四) 一.线性方程组求解 1.1 直接法 1.1.1 利用左除运算符 1.1.2 利用矩阵分解 1.2 迭代法 1.2.1 雅可比(Jacobi)迭代法 1.2.2 高斯-赛德 ...

最新文章

  1. Uber AI简单方法实现大规模语言模型的精细控制
  2. python写web自动化_使用Python+selenium实现第一个自动化测试脚本
  3. matplotlib中文乱码问题 解决 有代码例子
  4. python 输入数字变成密码_如何在python中检查数字的“密码”
  5. 2019牛客多校第三场 F.Planting Trees
  6. 使用IoC 容器清洁工厂设计模式
  7. Deno 是面向代码的浏览器?
  8. 《Java程序性能优化》-葛一鸣
  9. 数学模型建立常用方法
  10. 一文读懂量化系统接入及相关平台
  11. vue-element-admin——登录页面添加自定义背景
  12. NLP系列——(2)特征提取
  13. Matlab实现给黑白图片上色
  14. 日月年时分秒转换为年月日时分秒
  15. pandas如何将两个表根据某个数组合并
  16. 第十周 项目二 小刚破译加密密码
  17. 杰普(briup)软件公司JAVA培训项目《电信宽带运营支撑系统(WOSS)》
  18. 打印机驱动下载,有哪些下载途径推荐?
  19. [转](55)_KPCR, _NT_TIB, _KPRCB
  20. VXLAN技术在数据中心的应用

热门文章

  1. java调用hp打印机驱动_惠普打印机驱动修改JDK问题–现象:javac不能用了 | 学步园...
  2. 数据建模_浅谈数据仓库建设中的数据建模方法
  3. 怎么用计算机模拟宇宙,为了弄懂宇宙的形成 科学家用电脑模拟了800万个宇宙...
  4. java中long的包装类_Java中基本数据的包装类
  5. 20200909:链表类题目集合下
  6. 任何时候都不要轻易满仓
  7. SCPPO(二十六):测算过程中问题的解决总结
  8. 世界首个!AI农作物病害检测竞赛火热进行中 | AI Challenger 全球AI挑战赛
  9. 特斯拉遭遇史上最大单季亏损,马斯克放言无人车3个月内横穿美国
  10. “众矢之的”马库斯回应14个问题,将深度学习质疑到底