gpt4 book ai didi

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

转载 作者:qq735679552 更新时间:2022-09-29 22:32:09 27 4
gpt4 key购买 nike

CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.

这篇CFSDN的博客文章一步步打造简单的MVC电商网站BooksStore(2)由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.

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

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

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

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

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

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

简介 。

  上一次我们尝试了:创建项目架构、创建域模型实体、创建单元测试、创建控制器与视图、创建分页和加入样式,而这一节我们会完成两个功能,分类导航与购物车.

  主要功能与知识点如下:

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

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

  。

目录 。

  • 添加分类导航
  • 加入购物车
  • 创建一个分部视图 Partial View

  。

1、添加分类导航 。

  上一次我们把网页划分成了三个模块,其中左侧栏的部分尚未完成,左侧栏拥有将书籍分类展示的功能.

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

图 1 。

  。

  1.回到之前的 BookDetailsViewModels 视图模型,我们额外再添加一个新的属性用作分类(CurrentCategory):

 
    /// <summary>    /// 书籍详情视图模型    /// </summary>    public class BookDetailsViewModels : PagingInfo    {        public IEnumerable<Book> Books { get; set; }        /// <summary>        /// 当前分类        /// </summary>        public string CurrentCategory { get; set; }    }
 

  。

  2.修改完视图模型,现在就应该修改对应的 BookController 中的 Details 方法 。

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

 
        /// <summary>        /// 详情        /// </summary>        /// <param name="category">分类</param>        /// <param name="pageIndex">页码</param>        /// <returns></returns>        public ActionResult Details(string category, int pageIndex = 1)        {            var model = new BookDetailsViewModels            {                Books =                    _bookRepository.Books.Where(x => category == null || x.Category == category)                        .OrderBy(x => x.Id)                        .Skip((pageIndex - 1) * PageSize)                        .Take(PageSize),                CurrentCategory = category,                PageSize = PageSize,                PageIndex = pageIndex,                TotalItems = _bookRepository.Books.Count(x => category == null || x.Category == category)            };            return View(model);        }
 
一步步打造简单的MVC电商网站BooksStore(2)
namespace Wen.BooksStore.WebUI.Controllers{    public class BookController : Controller    {        private readonly IBookRepository _bookRepository;        public int PageSize = 5;        public BookController(IBookRepository bookRepository)        {            _bookRepository = bookRepository;        }        /// <summary>        /// 详情        /// </summary>        /// <param name="category">分类</param>        /// <param name="pageIndex">页码</param>        /// <returns></returns>        public ActionResult Details(string category, int pageIndex = 1)        {            var model = new BookDetailsViewModels            {                Books =                    _bookRepository.Books.Where(x => category == null || x.Category == category)                        .OrderBy(x => x.Id)                        .Skip((pageIndex - 1) * PageSize)                        .Take(PageSize),                CurrentCategory = category,                PageSize = PageSize,                PageIndex = pageIndex,                TotalItems = _bookRepository.Books.Count(x => category == null || x.Category == category)            };            return View(model);        }    }}
BookController.cs

  

  参数增加了一个 category,用于获取分类的字符串,对应 Books 中的属性的赋值语句改为 _bookRepository.Books.Where(x => category == null || x.Category == category),这里的 Lambda 表达式 x => category == null || x.Category == category 的意思是,分类字符串为空就取库中所有的 Book 实体,不为空时根据分类进行对集合进行筛选过滤.

  还要对属性 CurrentCategory 进行赋值.

  别忘了,因为分页是根据 TotalItems 属性进行的,所以还要修改地方 _bookRepository.Books.Count(x => category == null || x.Category == category),通过 LINQ 统计不同分类情况的个数.

  。

  3.该控制器对应的 Details.cshtml 中的分页辅助器也需要修改,添加新的路由参数:

<div class="pager">    @Html.PageLinks(Model, x => Url.Action("Details", new { pageIndex = x, category = Model.CurrentCategory }))</div>
一步步打造简单的MVC电商网站BooksStore(2)
 1 @model Wen.BooksStore.WebUI.Models.BookDetailsViewModels 2  3 @{ 4     ViewBag.Title = "Books"; 5 } 6  7 @foreach (var item in Model.Books) 8 { 9     <div class="item">10         <h3>@item.Name</h3>11         @item.Description12         <h4>@item.Price.ToString("C")</h4>13         <br />14         <hr />15     </div>16 }17 18 <div class="pager">19     @Html.PageLinks(Model, x => Url.Action("Details", new { pageIndex = x, category = Model.CurrentCategory }))20 </div>
Details.cshtml

  。

  4.路由区域也应当修改一下 。

一步步打造简单的MVC电商网站BooksStore(2)
        public static void RegisterRoutes(RouteCollection routes)        {            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");            routes.MapRoute(                name: "Default",                url: "{controller}/{action}",                defaults: new { controller = "Book", action = "Details" }            );            routes.MapRoute(                name: null,                url: "{controller}/{action}/{category}",                defaults: new { controller = "Book", action = "Details" }            );            routes.MapRoute(                name: null,                url: "{controller}/{action}/{category}/{pageIndex}",                defaults: new { controller = "Book", action = "Details", pageIndex = UrlParameter.Optional }            );        }
RouteConfig.cs

  。

  5.现在新建一个名为 NavController 的控制器,并添加一个名为 Sidebar 的方法,专门用于渲染左侧边栏.

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

  不过返回的 View 视图类型变成 PartialView 分部视图类型:

 
        public PartialViewResult Sidebar(string category = null)        {            var categories = _bookRepository.Books.Select(x => x.Category).Distinct().OrderBy(x => x);            return PartialView(categories);        }
 

  在方法体在右键,添加一个视图,勾上创建分部视图.

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

  Sidebar.cshtml 修改为:

 
@model IEnumerable<string><ul>    <li>@Html.ActionLink("所有分类", "Details", "Book")</li>    @foreach (var item in Model)    {        <li>@Html.RouteLink(item, new { controller = "Book", action = "Details", category = item, pageIndex = 1 }, new { @class = item == ViewBag.CurrentCategory ? "selected" : null })</li>    }</ul>
 

  

  MVC 框架具有一种叫作“子动作(Child Action)”的概念,可以适用于重用导航控件之类的东西,使用类似 RenderAction() 的方法,在当前的视图中输出指定的动作方法.

  因为需要在父视图中呈现另一个 Action 中的分部视图,所以原来的 _Layout.cshtml 布局页修改如下:

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

  。

  现在,启动的结果应该和图 1 是一样的,尝试点击左侧边栏的分类,观察主区域的变化情况.

  。

2、加入购物车 。

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

 图 2 。

  界面的大体功能如图 2,在每本图书的区域新增一个链接(添加到购物车),会跳转到一个新的页面,显示购物车的详细信息 - 购物清单,也可以通过“结算”链接跳转到一个新的页面.

  

  购物车是应用程序业务域的一部分,因此,购物车实体应该为域模型.

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

  1.添加两个类:

  Cart.cs 有添加、移除、清空和统计功能:

 
    /// <summary>    /// 购物车    /// </summary>    public class Cart    {        private readonly List<CartItem> _cartItems = new List<CartItem>();        /// <summary>        /// 获取购物车的所有项目        /// </summary>        public IList<CartItem> GetCartItems => _cartItems;        /// <summary>        /// 添加书模型        /// </summary>        /// <param name="book"></param>        /// <param name="quantity"></param>        public void AddBook(Book book, int quantity)        {            if (_cartItems.Count == 0)            {                _cartItems.Add(new CartItem() { Book = book, Quantity = quantity });                return;            }            var model = _cartItems.FirstOrDefault(x => x.Book.Id == book.Id);            if (model == null)            {                _cartItems.Add(new CartItem() { Book = book, Quantity = quantity });                return;            }            model.Quantity += quantity;        }        /// <summary>        /// 移除书模型        /// </summary>        /// <param name="book"></param>        public void RemoveBook(Book book)        {            var model = _cartItems.FirstOrDefault(x => x.Book.Id == book.Id);            if (model == null)            {                return;            }            _cartItems.RemoveAll(x => x.Book.Id == book.Id);        }        /// <summary>        /// 清空购物车        /// </summary>        public void Clear()        {            _cartItems.Clear();        }        /// <summary>        /// 统计总额        /// </summary>        /// <returns></returns>        public decimal ComputeTotalValue()        {            return _cartItems.Sum(x => x.Book.Price * x.Quantity);        }    }
 

  CartItem.cs 表示购物车中的每一项:

 
    /// <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 class="item">        <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 class="pager">    @Html.PageLinks(Model, x => Url.Action("Details", new { pageIndex = x, category = Model.CurrentCategory }))</div>
 

  。

  【备注】@Html.BeginForm() 方法默认会创建一个 Post 请求方法的表单,为什么不直接使用 Get 请求呢,HTTP 规范要求,会引起数据变化时不要使用 Get 请求,将产品添加到一个购物车明显会出现新的数据变化,所以,这种情形不应该使用 Get 请求,直接显示页面或者列表数据,这种请求才应该使用 Get.

  。

  3.先修改下 css 中的样式 。

一步步打造简单的MVC电商网站BooksStore(2)
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;    }
Site.css

  。

  4.再添加一个 CartController 。

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

 
    /// <summary>    /// 购物车    /// </summary>    public class CartController : Controller    {        private readonly IBookRepository _bookRepository;        public CartController(IBookRepository bookRepository)        {            _bookRepository = bookRepository;        }        /// <summary>        /// 首页        /// </summary>        /// <param name="returnUrl"></param>        /// <returns></returns>        public ViewResult Index(string returnUrl)        {            return View(new CartIndexViewModel()            {                Cart = GetCart(),                ReturnUrl = returnUrl            });        }        /// <summary>        /// 添加到购物车        /// </summary>        /// <param name="id"></param>        /// <param name="returnUrl"></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 name="id"></param>        /// <param name="returnUrl"></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 方法中选择右键新建视图,专门用于显示购物清单:

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

  Index.cshtml 中的代码:

 
@model Wen.BooksStore.WebUI.Models.CartIndexViewModel<h2>我的购物车</h2><table class="table">    <thead>        <tr>            <th>书名</th>            <th>价格</th>            <th>数量</th>            <th>总计</th>        </tr>    </thead>    <tbody>        @foreach (var item in Model.Cart.GetCartItems)        {            <tr>                <td>@item.Book.Name</td>                <td>@item.Book.Price</td>                <td>@item.Quantity</td>                <td>@((item.Book.Price * item.Quantity).ToString("C"))</td>            </tr>        }        <tr>            <td> </td>            <td> </td>            <td>总计:</td>            <td>@Model.Cart.ComputeTotalValue().ToString("C")</td>        </tr>    </tbody></table><p>    <a href="@Model.ReturnUrl">继续购物</a></p>
 

  。

  我想,这一定是一个令人激动的时刻,因为我们已经完成了这个基本的添加到购物车的功能.

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

  。

3、创建一个分部视图 Partial View 。

  分部视图,是嵌入在另一个视图中的一个内容片段,并且可以跨视图重用,这有助于减少重复,尤其需要在多个地方需要重复使用相同的数据时.

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

  在 Shared 内部新建一个名为 _BookSummary.cshtml 的视图,并且把之前 Details.cshtml 的代码进行整理.

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

  。

  修改后的两个视图:

  Details.cshtml 。

 
@model Wen.BooksStore.WebUI.Models.BookDetailsViewModels@{    ViewBag.Title = "Books";}@foreach (var item in Model.Books){    Html.RenderPartial("_BookSummary", item);}<div class="pager">    @Html.PageLinks(Model, x => Url.Action("Details", new { pageIndex = x, category = Model.CurrentCategory }))</div>
 

  。

  _BookSummary.cshtml 。

 
@model Wen.BooksStore.Domain.Entities.Book<div class="item">    <h3>@Model.Name</h3>    @Model.Description    <h4>@Model.Price.ToString("C")</h4>    @using (Html.BeginForm("AddToCart", "Cart"))    {        var id = Model.Id;        @Html.HiddenFor(x => id);        @Html.Hidden("returnUrl", Request.Url.PathAndQuery)        <input type="submit" value="+ 添加到购物车" />    }    <br />    <hr /></div>
 

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我。 原文链接:http://www.cnblogs.com/liqingwen/p/6647538.html 。

最后此篇关于一步步打造简单的MVC电商网站BooksStore(2)的文章就讲到这里了,如果你想了解更多关于一步步打造简单的MVC电商网站BooksStore(2)的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com