视图模型- PagingInfo 类:

    public class PagingInfo
{
public int TotalItems { get; set; }
public int ItemsPerPage { get; set; }
public int CurrentPage { get; set; }
public int TotalPages { get { return (int)Math.Ceiling((decimal)TotalItems / ItemsPerPage); } }
}

创建 “HtmlHelpers” 文件夹,在 PagingHelper 类中定义 HTML 辅助器方法 PageLinks:

    public static class PagingHelpers
{
/// <summary>
/// HTML 的扩展方法,用来生成页面链接
/// </summary>
/// <param name="html">第一个参数带“this”,表示这是一个扩展方法</param>
/// <param name="pagingInfo">所需的分页信息</param>
/// <param name="pageUrl">第3个参数是一个方法,该方法的输入参数是int类型(这里是页码),返回string类型(这里是输出URL)</param>
/// <returns></returns>
public static MvcHtmlString PageLinks(this HtmlHelper html, PagingInfo pagingInfo, Func<int, string> pageUrl)
{
StringBuilder result = new StringBuilder();
for (int i = ; i <= pagingInfo.TotalPages; i++)
{
TagBuilder tag = new TagBuilder("a"); //添加一个<a>标签
tag.MergeAttribute("href", pageUrl(i)); //标签所指向的页数,第二个参数是一个方法,而方法的参数是当前的i
tag.InnerHtml = i.ToString(); //标签显示的文本
if (i == pagingInfo.CurrentPage)
{
tag.AddCssClass("selected"); //对当前页的<a>标签添加值为selected的class属性
tag.AddCssClass("btn-primary");
}
tag.AddCssClass("btn btn-default"); //对所有的<a>标签都添加值为“默认按钮”的class属性
result.Append(tag.ToString());
}
return MvcHtmlString.Create(result.ToString());
}
}

生成页面链接的 Html.PageLinks 方法

    需要引入视图模型所在的命名空间

为更好的向视图传递数据,更好的做法是将控制器发送给视图的所有数据封装成一个单一的视图模型:

  public class UserListViewModel
  {
    public IEnumerable<t_user> Users { get; set; }    //页面显示需要的数据
    public PagingInfo PagingInfo { get; set; }      //分页信息
    public string CurrentCategory { get; set; }    //当前分类
}

在视图中添加的显示分页链接的代码:

<div>
@Html.PageLinks(Model.PagingInfo, x => Url.Action("动作方法名", new { page = x, category = Model.CurrentCategory }))
  <!-- 该扩展方法的第二个参数传递的是一个方法,该方法指明了在扩展方法的某一步中要实现什么功能,而且就像普通参数一样可以在循环中被重复使用 -->
  <!-- 具体的是:在一个循环中,当当前值小于所需要的页面总数时,传入当前要生成的链接对应的页码(int 类型),生成对应的链接(包含了页码和分类) -->
  <!-- 如果每次视图模型都带有 PagingInfo 属性,则方法中的第一个实参 “Model.PagingInfo” 就总是不用改变,而对于链接所生成的具体信息,全在于后面的动作方法名以及匿名对象中的属性名和对应的值 -->
  <!-- new 的是一个路由值对象,可以填充路由设置中对应的部分 -->
</div>

带有分页和并根据所选分类进行过滤的(Product)控制器:

    public class ProductController : Controller
{
private IProductsRepository repository; //用于……
public int PageSize = ; //分页中每页显示的项目数 public ProductController(IProductsRepository productRepository) //通过初始化器声明依赖项
{
this.repository = productRepository;
} public ViewResult List(string category,int page=)
{
ProductsListViewModel model = new ProductsListViewModel {
Products= repository.Products.Where(p=>category==null||p.Category==category).OrderBy(p => p.id).Skip((page - ) * PageSize).Take(PageSize),
PagingInfo=new PagingInfo {
CurrentPage = page,
ItemsPerPage = PageSize,
TotalItems = category == null ? repository.Products.Count() : repository.Products.Where(e=>e.Category==category).Count()  //将分类考虑进分页信息
},
CurrentCategory = category
};
return View(model);
}
} 使用 SQLSuger 的简单类似实现:

    public ActionResult GetComStaffs(int page=1)
    {
      UserListViewModel result = new UserListViewModel();
      using (var db = new SqlSugarClient(DBHelper.connectionString))
      {
        var lusers = db.Queryable<t_user>().Where(u => u.Isdel == false).ToList(); //db.Queryable<t_user>().Where(u => u.Isdel == false).OrderBy(u=>u.id).ToPageList(page, 10);

        result.Users = lusers.Skip((page - 1) * 10).Take(10);
        result.PagingInfo = new PagingInfo { CurrentPage = page, TotalItems = lusers.Count,ItemsPerPage=10 };
      }
      return View(result);
    }

调整 URL 方案 —— 修改 App_Start / RouteConfig.cs 文件中的 RegisterRoutes 方法:

    public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
       //重点看第二个参数(这个参数对应着实际的链接的形式),后面的匿名类型对象对应着当出现这种情况时自动补齐的值
routes.MapRoute(null, "", new { controller = "Product", action = "List", category = (string)null, page = }); routes.MapRoute(null, "Page{page}", new { controller = "Product", action = "List", category = (string)null }, new { page = @"\d+" }); routes.MapRoute(null, "{category}", new { controller = "Product", action = "List", page= }); routes.MapRoute(null, "{category}/Page{page}", new { controller = "Product", action = "List" }, new { page = @"\d+" }); routes.MapRoute(null, "{controller}/{action}");
}
}

生成分类列表(定义 “Nav” 控制器和 “Menu” 方法):

    public class NavController : Controller
{
private IProductsRepository repository; public NavController(IProductsRepository repo)    //构造器
{
repository = repo;
} public PartialViewResult Menu(string category=null)
{
       //这里是处于多样性的目的,更常规的做法是床架一个视图模型,它含有分类列表和所选分类
ViewBag.selectedCategory = category;     //将选择的分类通过控制器的动作方法再传递给视图,用来 “高亮显示当前分类” IEnumerable<string> categories = repository.Products.Select(x => x.Category).Distinct().OrderBy(x => x);
return PartialView(categories); //返回一个分部视图(分类导航菜单确实也只是整个页面的一部分)
}
}

    在 “分类导航菜单” 控制器中添加一个构造器,其参数接受的是 IProductRepository 的一个实现。(其效果是声明了一个由 Ninject 进行解析的依赖项,用以创建这个 NavController 类的实例)

    在 “Menu” 动作方法中使用 LINQ 查询从存储库获取分类列表,并将它们传递给视图。(返回的是分部视图)

分类导航菜单对应的分部视图:

@model IEnumerable<string>

<!-- 添加了一个叫做“Home”的链接,它将出现在分类列表的顶部,并在无分类过滤器作用的情况下列举所有产品。(这是用 ActionLink 辅助器方法来实现的) -->
@Html.ActionLink("Home","List","Product",null,new { @class = "btn btn-block btn-default btn-lg"})
<!-- 枚举分类名称,并用 RouteLink 方法为每个分类创建链接。—— 该辅助器方法与 ActionLink 类似,但在根据路由配置生成URL时,它让笔者能够有针对性地在匿名对象中提供一组“键/值”对,它们为路由的各个片段提供了数据 -->
@foreach (var link in Model)
{
@Html.RouteLink(link,new { controller= "Product",action="List",category=link,page= },new { @class = "btn btn-block btn-default btn-lg"
   + (link == ViewBag.selectedCategory ? " btn-primary" : "") })    //如果当前link的值与SelectedCategory的值匹配,则为待创建的元素添加高亮样式
}

定义购物车实体(在文件夹 Entities 中定义):

    public class Cart
{
private List<CartLine> lineCollection = new List<CartLine>(); public IEnumerable<CartLine> Lines { get { return lineCollection; } } //通过该属性对购物车的内容进行访问 //添加
public void AddItem(Product product, int quantity)
{
CartLine line = lineCollection.Where(p => p.Product.id == product.id).FirstOrDefault(); //添加之前要分购物车里是否已经有该商品
if (line == null)
{
lineCollection.Add(new CartLine { Product = product, Quantity = quantity });
}
else
{
line.Quantity += quantity;
}
} //移除
public void RemoveLine(Product product)
{
lineCollection.RemoveAll(l => l.Product.id == product.id);
} //计算总价
public decimal ComputeTotalValue()
{
return lineCollection.Sum(e => e.Product.Price * e.Quantity);
} //清空
public void Clear()
{
lineCollection.Clear();
}
} public class CartLine //表示又客户所选的一个产品和用户想要购买的数量
{
public Product Product { get; set; }
public int Quantity { get; set; }
}

产品信息列表 + “加入购物车”按钮:

@model SportsStore.Domain.Entities.Product

<div class="well">
<h3>
<strong>@Model.Name</strong>
<span class="pull-right label label-primary">@Model.Price.ToString("c")</span>
</h3>
<!-- 添加“加入购物车”按钮 -->
@using (Html.BeginForm("AddToCart", "Cart"))
{
<div class="pull-right">
<!-- 给表单添加一组隐藏的子标签 -->
@Html.HiddenFor(x => x.id)
@Html.Hidden("returnUrl",Request.Url.PathAndQuery)
<!-- “加入购物车”按钮 -->
<input type="submit" class="btn-success" value="加入购物车" />
</div>
}
<span class=" lead">@Model.Description</span>
</div>

实现购物车控制器(CartController):

    public class CartController : Controller
{
private IProductsRepository repository;
//带有依赖项的构造器
public CartController(IProductsRepository repo)
{
repository = repo;
} public ViewResult Index(string returnUrl)
{
return View(new CartIndexViewModel { Cart = GetCart(), ReturnUrl = returnUrl });
} #region 对于这两个方法,这里使用了与 HTML 表单中 input 元素相匹配的参数名(分部视图ProductSummary中的表单),这可以让 MVC框架将输入的表单的 POST变量自动与这些参数关联起来。(笔者不需要自己去处理)
public RedirectToRouteResult AddToCart(int id, string returnUrl)
{
Product product = repository.Products.FirstOrDefault(p => p.id == id);
if (product != null)
{
GetCart().AddItem(product, );
}
return RedirectToAction("Index", new { returnUrl });
} public RedirectToRouteResult RemoveFromCart(int id, string returnUrl)
{
Product product = repository.Products.FirstOrDefault(p => p.id == id);
if (product != null)
{
GetCart().RemoveLine(product);
}
return RedirectToAction("Index", new { returnUrl });
}
#endregion //获取购物车
private Cart GetCart()
{
Cart cart = (Cart)Session["Cart"];
if (cart == null)
{
cart = new Cart();
Session["Cart"] = cart; //使用ASP.NET的会话状态特性存储和接收Cart对象(本程序中的购物车并没有保存的数据库——持久性不够)
}
return cart;
}
}

显示购物车所需视图模型:

    public class CartIndexViewModel
{
public Cart Cart { get; set; }
public string ReturnUrl { get; set; }
}

显示购物车内容的视图:

@model SportsStore.WebUI.Models.CartIndexViewModel

@{
ViewBag.Title = "购物车";
} <h2>购物车</h2>
<table class="table">
  <!-- 表头 -->
<thead>
<tr>
<th>商品</th>
<th>数量</th>
<th class="text-right">单价</th>
<th class="text-right">总价</th>
</tr>
</thead>
  <!-- 表格内容。给这些元素的 class 属性所赋的值用于表格和元素的对齐方式 -->
<tbody>
@foreach (var line in Model.Cart.Lines)
{
<tr>
<td class="text-left">@line.Product.Name</td>
<td class="text-center">@line.Quantity</td>
<td class="text-right">@line.Product.Price.ToString("c")</td>
<td class="text-right">@((line.Quantity*line.Product.Price).ToString("c"))</td>
</tr>
}
</tbody>
  <!-- 表格底部 -->
<tfoot>
<tr>
<td colspan="" class="text-right">合计:</td>
<td class="text-right">@Model.Cart.ComputeTotalValue().ToString("c")</td>
</tr>
</tfoot>
</table>
<div class="text-center">
<a class="btn btn-primary" href="@Model.ReturnUrl">继续购买</a>
</div>

    该视图枚举了购物车中的各条信息,并为各条信息添加了一个表格行。

新建 ASP.NET MVC 项目快速代码的更多相关文章

  1. 在ASP.NET MVC项目中使用极验验证(geetest)

    时间 2016-03-02 18:22:37 smallerpig 原文  http://www.smallerpig.com/979.html 主题 ASP.NET MVC   geetest开发体 ...

  2. 1.2 认识ASP.NET MVC项目结构

    1.开发环境 操作系统:xp.vista.windows 7.windows 8.windows server 2003|2008|2008R2|2012: 集成开发环境IDE: Vsiual Stu ...

  3. 在 ASP.NET MVC 项目中使用 WebForm、 HTML

    原文地址:http://www.cnblogs.com/snowdream/archive/2009/04/17/winforms-in-mvc.html ASP.NET MVC和WebForm各有各 ...

  4. ASP.NET MVC项目

    ASP.NET MVC项目里创建一个aspx视图 先从控制器里添加视图 视图引擎选"ASPX(C#)",使用布局或模板页不要选. 在Views\EAV目录里,生成的aspx是个单独 ...

  5. 习题-任务2初始ASP.NET MVC项目开发

    一.选择题 1.在ASP.NET MVC项目的RouteConfig.cs文件中,(    )方法注册了默认的路由配置. A.RegisterMap    B.RegisterRoutes    C. ...

  6. 2.2 利用项目模板创建ASP.NET MVC项目

    1.启动VS2012,点击“文件|新建|项目”. 2.在新建项目的窗口中,选择ASP.NET MVC 4应用程序. 3.在新ASP.NET MVC 4项目窗口中的“选择模板”列表中选择“基本”模板,在 ...

  7. 基于BUI开发Asp.net MVC项目

    因工作性质参于并开发过一些Web应用程序,前端项目框架也用了不少,比如MiniUI.ExtJS.以及定制的项目前端框架.无意中看到BUI前端框架,第一眼就被它的优雅布局所吸引.简洁的项目门户Banne ...

  8. ASP.NET MVC项目实现BasePage基类用作ASPX.CS网页继承

    在ASP.NET MVC项目开发,还是需要创建一些Web Page来实现一些功能,如呈现报表等... 但是一旦项目的.ASPX网页太多了,其中的程序代码也会有代码冗余,出现这些情况,我们得需要对这些代 ...

  9. ASP.NET MVC项目中App_Code目录在程序应用

    学习ASP.NET MVC,如果你是开发ASP.NET MVC项目的,也许你去为项目添加前ASP.NET项目的APP_Code目录,在这里创建与添加的Class类,也许你无法在MVC项目所引用. 那这 ...

随机推荐

  1. Spring Boot 踩坑之路之 Configuration Annotation Proessor not found in classpath

    1. 出现spring boot Configuration Annotation Proessor not found in classpath的提示是在用了@ConfigurationProper ...

  2. SQL学习之MYSQL的常用命令和增删改查语句和数据类型

    连接命令:mysql -h[主机地址] -u[用户名] -p[用户密码] 创建数据库:create database [库名] 显示所有数据库: show databases; 打开数据库:use [ ...

  3. luogu P3387 【模板】缩点

    题目 好久没法博客了 这次就水个板子题目吧 tarjan缩点之后重新建图 而且边权应该都是正的(要不我怎么能这么轻松水过去) 在新图上记忆化一下就好了 f[i] 表示 开头选i这个点 的 路径最大值 ...

  4. Inversion of Control Containers and the Dependency Injection pattern

    https://martinfowler.com/articles/injection.html One of the entertaining things about the enterprise ...

  5. 【附4】springboot源码解析-run()

    public ConfigurableApplicationContext run(String... args) { StopWatch stopWatch = new StopWatch(); / ...

  6. Mybatis配置映射文件中parameterType的用法小结

    原创: 在mybatis映射接口的配置中,有select,insert,update,delete等元素都提到了parameterType的用法,parameterType为输入参数,在配置的时候,配 ...

  7. C++作业:Circle_area

    Github链接: Circle_area 代码: main.cpp #include "circle_area.h" #include <iostream> #inc ...

  8. 第五次程序设计作业 C++计算器雏形 调用文件输入输出

    一.C++计算器作业系列链接 第三次作业:C++计算器雏形 第三次作业附加:代码规范 第四次作业:命令行的调用及计算 MyGithub 二.本次作业相关 要求:第五次程序设计作业 根据这一次的作业要求 ...

  9. UVa 11572 唯一的雪花(滑动窗口)

    https://vjudge.net/problem/UVA-11572 题意:输入一个长度为n的序列A,找到一个尽量长的连续子序列,使得该序列中没有相同的元素. 思路:很简单的题,也没啥好解释的了. ...

  10. Codeforces Beta Round #94 div 2 C Statues dfs或者bfs

    C. Statues time limit per test 2 seconds memory limit per test 256 megabytes input standard input ou ...