您现在的位置是:网站首页> 编程资料编程资料

一步步打造简单的MVC电商网站BooksStore(3)_实用技巧_

2023-05-24 365人已围观

简介 一步步打造简单的MVC电商网站BooksStore(3)_实用技巧_

一步步打造一个简单的 MVC 电商网站 - BooksStore(三)

本系列的 GitHub地址:https://github.com/liqingwen2015/Wen.BooksStore

一步步打造一个简单的 MVC 电商网站 - BooksStore(一)

一步步打造一个简单的 MVC 电商网站 - BooksStore(二)

一步步打造一个简单的 MVC 电商网站 - BooksStore(三)

一步步打造一个简单的 MVC 电商网站 - BooksStore(四)

简介

上一节我们完成了两个主要功能:添加到购物车和分类导航,这一节我们会完成整个购物车的流程,以及订单处理。

该系列主要功能与知识点如下:

分类、产品浏览、购物车、结算、CRUD(增删改查) 管理、发邮件、分页、模型绑定、认证过滤器和单元测试等(预计剩余两篇,周三(因为周二不上班)先发布一篇)。

【备注】项目使用 VS2015 + C#6 进行开发,有问题请发表在留言区哦,还有,页面长得比较丑,请见谅。

目录

完成购物车

订单结算

一、完成购物车

上一节其实已经完成了移除购物车和清空购物车的方法,只是尚未将可供用户操作的按钮放在页面区域。除了增加这两个按钮,也会在页面顶部的位置增加购物车的摘要(用于显示用户的购物总额)。

下面是上一节已经写好的 CartController 代码。

 ///  /// 购物车 ///  public class CartController : Controller { private readonly IBookRepository _bookRepository; public CartController(IBookRepository bookRepository) { _bookRepository = bookRepository; } ///  /// 首页 ///  ///  ///  public ViewResult Index(string returnUrl) { return View(new CartIndexViewModel() { Cart = GetCart(), ReturnUrl = returnUrl }); } ///  /// 添加到购物车 ///  ///  ///  ///  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 }); } ///  /// 从购物车移除 ///  ///  ///  ///  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 }); } ///  /// 获取购物车 ///  ///  private Cart GetCart() { var cart = (Cart)Session["Cart"]; if (cart != null) return cart; cart = new Cart(); Session["Cart"] = cart; return cart; } } 

1.加入移除书籍和清空购物车的功能

Index.cshtml

 @model Wen.BooksStore.WebUI.Models.CartIndexViewModel 

我的购物车

@foreach (var item in Model.Cart.GetCartItems) { }
书名价格数量总计
@item.Book.Name@item.Book.Price@item.Quantity@((item.Book.Price * item.Quantity).ToString("C")) @using (Html.BeginForm("RemoveFromCart", "Cart")) { @Html.Hidden("id", item.Book.Id) @Html.HiddenFor(x => x.ReturnUrl) }
总计:@Model.Cart.ComputeTotalValue().ToString("C") @using (Html.BeginForm("Clear", "Cart")) { @Html.HiddenFor(x => x.ReturnUrl) }

【备注】@Html.Hidden("id", item.Book.Id) 是用于生成隐藏的字段,如果直接使用@Html.HiddenFor(),生成的 name 将会是 item.Book.Id ,将和 CartController 中 RemoveFromCart(int id, string return) 的参数不匹配。

显示的效果如下:

2.添加摘要:我们在购物车存放了许多东西,通过摘要,可以显示购物总额的缩略图,我们选择的位置在顶部右上角的一个比较显眼的位置进行显示它,当然,还需要有点击的跳转按钮方便显示所有的购物清单页面。

继续在 CartController 下新增一个 Action,名为 Summary,返回值是一个分部视图:

 ///  /// 摘要 ///  ///  public PartialViewResult Summary() { return PartialView(GetCart()); } 

对应的Summary.cshtml

 @model Wen.BooksStore.Domain.Entities.Cart 
你的购物车:@Model.ComputeTotalValue() @Html.ActionLink("结算", "Checkout", "Cart", new { retunUrl = Request.Url.PathAndQuery }, null)

对应的布局页_Layout.cshtml 修改的地方为:

_Layout.cshtml

@ViewBag.Title
@RenderBody()

添加了新的东西,css 也要进行修改:

Site.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; } .bookSummary { width: 15%; float: right; margin-top: 1.5%; } 

二、订单结算

购物完毕就是结算页面了,这里的订单结算并不涉及支付接口的调用,只是使用邮件的形式进行通知而已。

这里,我设计结算的时候需要要求用户输入一些信息,如姓名、地址和邮箱等信息,在点击确定时我再将这些输入的信息与购物清单的信息从系统的邮箱发到你所输入的邮箱当中。一个比较直观的图:

1.在 Entities 中添加一个域模型 Contact.cs 表示联系人的信息。

 ///  /// 联系信息 ///  public class Contact { [Required(ErrorMessage = "姓名不能为空")] public string Name { get; set; } [Required(ErrorMessage = "地址不能为空")] public string Address { get; set; } [Required(ErrorMessage = "邮箱不能为空")] [RegularExpression(@"(\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*\w\w)", ErrorMessage = "输入的邮箱地址不合法")] public string Email { get; set; } } 

CartController.cs 添加一个用于结算的 Action:

 ///  /// 结算 ///  ///  public ViewResult Checkout() { return View(new Contact()); } 

Checkout.cshtml 中的:

 @model Wen.BooksStore.Domain.Entities.Contact 
@using (Html.BeginForm()) {
@Html.ValidationSummary()
姓名: @Html.TextBoxFor(x => x.Name)
地址: @Html.TextBoxFor(x => x.Address)
邮箱: @Html.TextBoxFor(x => x.Email)
}

这里使用的是模型校验,_Layout.cshtml 布局页需要引入js:

@ViewBag.Title
@RenderBody()

尝试运行,会出现以下页面,如果信息不填的话会出现相关的错误提示:

2.接下来,要进入“提交”后的流程了。

现在还需要一个组件用于处理订单,创建一个用于订单处理的接口,和一个该接口的实现,再通过 Ninject 进行两者的绑定:

 ///  /// 订单处理 ///  public interface IOrderProcessor { ///  /// 处理订单 ///  ///  ///  void ProcessOrder(Cart cart, Contact contact); } 

建立一个实现该接口用于处理订单的实体类,这里并不是调用支付接口,而是简单通过 BCL 中的进行邮件的发送。

EmailOrderProcessor.cs:

 ///  /// 邮件订单处理器 ///  public
                
                

-六神源码网