亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

一步步打造簡單的MVC電商網(wǎng)站BooksStore(2)

 更新時間:2017年04月06日 14:15:30   作者:反骨仔  
這篇文章主要和大家一起一步步打造一個簡單的MVC電商網(wǎng)站,MVC電商網(wǎng)站BooksStore第二篇,添加分類導(dǎo)航、加入購物車,具有一定的參考價值,感興趣的小伙伴們可以參考一下

一步步打造一個簡單的 MVC 電商網(wǎng)站 - BooksStore(二)

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

一步步打造一個簡單的 MVC 電商網(wǎng)站 - BooksStore(一)

一步步打造一個簡單的 MVC 電商網(wǎng)站 - BooksStore(二)

一步步打造一個簡單的 MVC 電商網(wǎng)站 - BooksStore(三)

一步步打造一個簡單的 MVC 電商網(wǎng)站 - BooksStore(四)

簡介

上一次我們嘗試了:創(chuàng)建項目架構(gòu)、創(chuàng)建域模型實體、創(chuàng)建單元測試、創(chuàng)建控制器與視圖、創(chuàng)建分頁和加入樣式,而這一節(jié)我們會完成兩個功能,分類導(dǎo)航與購物車。

主要功能與知識點如下:

分類、產(chǎn)品瀏覽、購物車、結(jié)算、CRUD(增刪改查) 管理、發(fā)郵件、分頁、模型綁定、認證過濾器和單元測試等(預(yù)計剩余兩篇,預(yù)計明天(因為周六不放假)和周三(因為周二不上班)發(fā)布)。

【備注】項目使用 VS2015 + C#6 進行開發(fā),有問題請發(fā)表在留言區(qū)哦,還有,頁面長得比較丑,請見諒。

目錄

添加分類導(dǎo)航

加入購物車

創(chuàng)建一個分部視圖 Partial View

一、添加分類導(dǎo)航

上一次我們把網(wǎng)頁劃分成了三個模塊,其中左側(cè)欄的部分尚未完成,左側(cè)欄擁有將書籍分類展示的功能。

圖 1

1.回到之前的BookDetailsViewModels 視圖模型,我們額外再添加一個新的屬性用作分類(CurrentCategory):

/// <summary>
 /// 書籍詳情視圖模型
 /// </summary>
 public class BookDetailsViewModels : PagingInfo
 {
 public IEnumerable<Book> Books { get; set; }

 /// <summary>
 /// 當前分類
 /// </summary>
 public string CurrentCategory { get; set; }
 }

2.修改完視圖模型,現(xiàn)在就應(yīng)該修改對應(yīng)的 BookController 中的Details 方法

/// <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 

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);
 }
 }
}

參數(shù)增加了一個 category,用于獲取分類的字符串,對應(yīng) Books 中的屬性的賦值語句改為_bookRepository.Books.Where(x => category == null || x.Category == category),這里的 Lambda 表達式x => category == null || x.Category ==category 的意思是,分類字符串為空就取庫中所有的 Book 實體,不為空時根據(jù)分類進行對集合進行篩選過濾。

還要對屬性 CurrentCategory 進行賦值。

別忘了,因為分頁是根據(jù) TotalItems 屬性進行的,所以還要修改地方_bookRepository.Books.Count(x => category == null || x.Category == category),通過 LINQ 統(tǒng)計不同分類情況的個數(shù)。

3.該控制器對應(yīng)的 Details.cshtml 中的分頁輔助器也需要修改,添加新的路由參數(shù):

<div class="pager">
 @Html.PageLinks(Model, x => Url.Action("Details", new { pageIndex = x, category = Model.CurrentCategory }))
</div>

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>
 <br />
 <hr />
 </div>
}

<div class="pager">
 @Html.PageLinks(Model, x => Url.Action("Details", new { pageIndex = x, category = Model.CurrentCategory }))
</div>

4.路由區(qū)域也應(yīng)當修改一下

RouteConfig.cs

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 }
  );
 }

5.現(xiàn)在新建一個名為 NavController 的控制器,并添加一個名為Sidebar 的方法,專門用于渲染左側(cè)邊欄。

不過返回的 View 視圖類型變成 PartialView 分部視圖類型:

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

在方法體在右鍵,添加一個視圖,勾上創(chuàng)建分部視圖。

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)”的概念,可以適用于重用導(dǎo)航控件之類的東西,使用類似 RenderAction() 的方法,在當前的視圖中輸出指定的動作方法。

因為需要在父視圖中呈現(xiàn)另一個 Action 中的分部視圖,所以原來的_Layout.cshtml布局頁修改如下:

現(xiàn)在,啟動的結(jié)果應(yīng)該和圖 1 是一樣的,嘗試點擊左側(cè)邊欄的分類,觀察主區(qū)域的變化情況。

二、加入購物車

圖 2

界面的大體功能如圖 2,在每本圖書的區(qū)域新增一個鏈接(添加到購物車),會跳轉(zhuǎn)到一個新的頁面,顯示購物車的詳細信息 - 購物清單,也可以通過“結(jié)算”鏈接跳轉(zhuǎn)到一個新的頁面。

購物車是應(yīng)用程序業(yè)務(wù)域的一部分,因此,購物車實體應(yīng)該為域模型。

1.添加兩個類:

Cart.cs 有添加、移除、清空和統(tǒng)計功能:

/// <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>
 /// 統(tǒng)計總額
 /// </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>
 /// 數(shù)量
 /// </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() 方法默認會創(chuàng)建一個 Post 請求方法的表單,為什么不直接使用 Get 請求呢,HTTP 規(guī)范要求,會引起數(shù)據(jù)變化時不要使用 Get 請求,將產(chǎn)品添加到一個購物車明顯會出現(xiàn)新的數(shù)據(jù)變化,所以,這種情形不應(yīng)該使用 Get 請求,直接顯示頁面或者列表數(shù)據(jù),這種請求才應(yīng)該使用 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 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 會話狀態(tài)進行保存用戶的 Cart 對象。當會話過期(典型的情況是用戶很長時間沒有對服務(wù)器發(fā)起任何請求),與該會話關(guān)聯(lián)的數(shù)據(jù)就會被刪除,這就意味著不需要對 Cart 對象進行生命周期的管理。

【備注】RedirectToAction() 方法:將一個 HTTP 重定向的指令發(fā)給客戶端瀏覽器,要求瀏覽器請求一個新的 Url。

5.在 Index 方法中選擇右鍵新建視圖,專門用于顯示購物清單:

Index.cshtml 中的代碼:

@model Wen.BooksStore.WebUI.Models.CartIndexViewModel

<h2>我的購物車</h2>

<table class="table">
 <thead>
 <tr>
  <th>書名</th>
  <th>價格</th>
  <th>數(shù)量</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">繼續(xù)購物</a>
</p>

我想,這一定是一個令人激動的時刻,因為我們已經(jīng)完成了這個基本的添加到購物車的功能。

三、創(chuàng)建一個分部視圖 Partial View

分部視圖,是嵌入在另一個視圖中的一個內(nèi)容片段,并且可以跨視圖重用,這有助于減少重復(fù),尤其需要在多個地方需要重復(fù)使用相同的數(shù)據(jù)時。

在 Shared 內(nèi)部新建一個名為_BookSummary.cshtml 的視圖,并且把之前Details.cshtml 的代碼進行整理。

修改后的兩個視圖:

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>

以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

最新評論