新建 ASP.NET MVC 项目快速代码
视图模型- 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 项目快速代码的更多相关文章
- 在ASP.NET MVC项目中使用极验验证(geetest)
时间 2016-03-02 18:22:37 smallerpig 原文 http://www.smallerpig.com/979.html 主题 ASP.NET MVC geetest开发体 ...
- 1.2 认识ASP.NET MVC项目结构
1.开发环境 操作系统:xp.vista.windows 7.windows 8.windows server 2003|2008|2008R2|2012: 集成开发环境IDE: Vsiual Stu ...
- 在 ASP.NET MVC 项目中使用 WebForm、 HTML
原文地址:http://www.cnblogs.com/snowdream/archive/2009/04/17/winforms-in-mvc.html ASP.NET MVC和WebForm各有各 ...
- ASP.NET MVC项目
ASP.NET MVC项目里创建一个aspx视图 先从控制器里添加视图 视图引擎选"ASPX(C#)",使用布局或模板页不要选. 在Views\EAV目录里,生成的aspx是个单独 ...
- 习题-任务2初始ASP.NET MVC项目开发
一.选择题 1.在ASP.NET MVC项目的RouteConfig.cs文件中,( )方法注册了默认的路由配置. A.RegisterMap B.RegisterRoutes C. ...
- 2.2 利用项目模板创建ASP.NET MVC项目
1.启动VS2012,点击“文件|新建|项目”. 2.在新建项目的窗口中,选择ASP.NET MVC 4应用程序. 3.在新ASP.NET MVC 4项目窗口中的“选择模板”列表中选择“基本”模板,在 ...
- 基于BUI开发Asp.net MVC项目
因工作性质参于并开发过一些Web应用程序,前端项目框架也用了不少,比如MiniUI.ExtJS.以及定制的项目前端框架.无意中看到BUI前端框架,第一眼就被它的优雅布局所吸引.简洁的项目门户Banne ...
- ASP.NET MVC项目实现BasePage基类用作ASPX.CS网页继承
在ASP.NET MVC项目开发,还是需要创建一些Web Page来实现一些功能,如呈现报表等... 但是一旦项目的.ASPX网页太多了,其中的程序代码也会有代码冗余,出现这些情况,我们得需要对这些代 ...
- ASP.NET MVC项目中App_Code目录在程序应用
学习ASP.NET MVC,如果你是开发ASP.NET MVC项目的,也许你去为项目添加前ASP.NET项目的APP_Code目录,在这里创建与添加的Class类,也许你无法在MVC项目所引用. 那这 ...
随机推荐
- Django框架----数据库表的单表查询
一.添加表记录 对于单表有两种方式 # 添加数据的两种方式 # 方式一:实例化对象就是一条表记录 Frank_obj = models.Student(name ="海东",cou ...
- 计算概论(A)/基础编程练习1(8题)/4:求一元二次方程的根
#include<stdio.h> #include<math.h> int main() { // 待解方程数目 int n; scanf("%d", & ...
- shell中参数及带色彩打印
shell脚本中的一些函数参数说明如下: #!/bin/bash echo 显示参数的个数: $# echo 以单个字符串把每个参数连接起来: $* echo 显示脚本当前运行的进程id: $$ ec ...
- P4878 [USACO05DEC]layout布局
P4878 [USACO05DEC]layout布局 差分约束 最短路径最长路,最长路径最短路 本题求的是最长路径,所以跑最短路 根据题意连边,然后spfa即可 注意要判断图的连通性,所以新建一个虚拟 ...
- jQuery 概述
jQuery 概述 版权声明:未经博主授权,内容严禁分享转载! 什么是 JavaScript 类库 JavaScript 类库是指已经被封装好的一系列 JavaScript 函数,能够实现一些特定的功 ...
- 简单的Django实现图片上传,并存储进MySQL数据库 案例——小白
目标:通过网页上传一张图片到Django后台,后台接收并存储进数据库 真是不容易!!这个案例的代码网上太乱,不适合我,自己摸索着写,终于成功了,记录一下,仅供自己参考,有的解释可能不对,自己明白就好, ...
- 2018-2019-1 1723《程序设计与数据结构》第1&2周作业 总结
作业地址 第一周作业: https://edu.cnblogs.com/campus/besti/CS-IMIS-1723-2/homework/2092 提交情况如图: 第二周作业: https:/ ...
- 0x30、0x37
1.write_date(0x30+shi)加0x30是什么意思 答: 将数字0-9转化为字符'0'-'9' 1.write_date(0x37+bai)加0x37是什么意思 答: 将大于9的数字转化 ...
- EF、Repository、Factory、Service间关系
EF和Repository 实体(Entities):具备唯一ID,能够被持久化,具备业务逻辑,对应现实世界业务对象. 值对象(Value objects):不具有唯一ID,由对象的属性描述,一般为内 ...
- 返回json格式数据乱码
本文为博主原创,未经允许不得转载: 原本返回json格式数据的代码: @ResponseBody @RequestMapping(value = "getListByTime", ...