/// <summary> /// 购物车项 /// </summary> public class CartItem { /// <summary> /// 书 /// </summary> public Book Book { get; set; } /// <summary> /// 数量 /// </summary> public int Quantity { get; set; } }
2.修改一下之前的 Details.cshtml,增加“添加到购物车”的按钮:
@model Wen.BooksStore.WebUI.Models.BookDetailsViewModels @{ ViewBag.Title = "Books"; } @foreach (var item in Model.Books) { <div> <h3>@item.Name</h3> @item.Description <h4>@item.Price.ToString("C")</h4> @using (Html.BeginForm("AddToCart", "Cart")) { var id = item.Id; @Html.HiddenFor(x => id); @Html.Hidden("returnUrl", Request.Url.PathAndQuery) <input type="submit" value="+ 添加到购物车" /> } <br /> <hr /> </div> } <div> @Html.PageLinks(Model, x => Url.Action("Details", new { pageIndex = x, category = Model.CurrentCategory })) </div>
【备注】@Html.BeginForm() 方法默认会创建一个 Post 请求方法的表单,为什么不直接使用 Get 请求呢,HTTP 规范要求,会引起数据变化时不要使用 Get 请求,将产品添加到一个购物车明显会出现新的数据变化,所以,这种情形不应该使用 Get 请求,直接显示页面或者列表数据,这种请求才应该使用 Get。
3.先修改下 css 中的样式
body { } #header, #content, #sideBar { display: block; } #header { background-color: green; border-bottom: 2px solid #111; color: White; } #header, .title { font-size: 1.5em; padding: .5em; } #sideBar { float: left; width: 8em; padding: .3em; } #content { border-left: 2px solid gray; margin-left: 10em; padding: 1em; } .pager { text-align: right; padding: .5em 0 0 0; margin-top: 1em; } .pager A { font-size: 1.1em; color: #666; padding: 0 .4em 0 .4em; } .pager A:hover { background-color: Silver; } .pager A.selected { background-color: #353535; color: White; } .item input { float: right; color: White; background-color: green; } .table { width: 100%; padding: 0; margin: 0; } .table th { font: bold 12px "Trebuchet MS", Verdana, Arial, Helvetica, sans-serif; color: #4f6b72; border-right: 1px solid #C1DAD7; border-bottom: 1px solid #C1DAD7; border-top: 1px solid #C1DAD7; letter-spacing: 2px; text-transform: uppercase; text-align: left; padding: 6px 6px 6px 12px; background: #CAE8EA no-repeat; } .table td { border-right: 1px solid #C1DAD7; border-bottom: 1px solid #C1DAD7; background: #fff; font-size: 14px; padding: 6px 6px 6px 12px; color: #4f6b72; } .table td.alt { background: #F5FAFA; color: #797268; } .table th.spec, td.spec { border-left: 1px solid #C1DAD7; }
4.再添加一个 CartController
/// <summary> /// 购物车 /// </summary> public class CartController : Controller { private readonly IBookRepository _bookRepository; public CartController(IBookRepository bookRepository) { _bookRepository = bookRepository; } /// <summary> /// 首页 /// </summary> /// <param></param> /// <returns></returns> public ViewResult Index(string returnUrl) { return View(new CartIndexViewModel() { Cart = GetCart(), ReturnUrl = returnUrl }); } /// <summary> /// 添加到购物车 /// </summary> /// <param></param> /// <param></param> /// <returns></returns> public RedirectToRouteResult AddToCart(int id, string returnUrl) { var book = _bookRepository.Books.FirstOrDefault(x => x.Id == id); if (book != null) { GetCart().AddBook(book, 1); } return RedirectToAction("Index", new { returnUrl }); } /// <summary> /// 从购物车移除 /// </summary> /// <param></param> /// <param></param> /// <returns></returns> public RedirectToRouteResult RemoveFromCart(int id, string returnUrl) { var book = _bookRepository.Books.FirstOrDefault(x => x.Id == id); if (book != null) { GetCart().RemoveBook(book); } return RedirectToAction("Index", new { returnUrl }); } /// <summary> /// 获取购物车 /// </summary> /// <returns></returns> private Cart GetCart() { var cart = (Cart)Session["Cart"]; if (cart != null) return cart; cart = new Cart(); Session["Cart"] = cart; return cart; } }
【备注】这里的购物车是通过 Session 会话状态进行保存用户的 Cart 对象。当会话过期(典型的情况是用户很长时间没有对服务器发起任何请求),与该会话关联的数据就会被删除,这就意味着不需要对 Cart 对象进行生命周期的管理。
【备注】RedirectToAction() 方法:将一个 HTTP 重定向的指令发给客户端浏览器,要求浏览器请求一个新的 Url。
5.在 Index 方法中选择右键新建视图,专门用于显示购物清单:
Index.cshtml 中的代码: