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

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

 更新時(shí)間:2017年04月06日 15:44:05   作者:反骨仔  
這篇文章主要和大家一起一步步打造一個(gè)簡單的MVC電商網(wǎng)站,MVC電商網(wǎng)站BooksStore第三篇,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

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

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

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

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

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

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

簡介

上一節(jié)我們完成了兩個(gè)主要功能:添加到購物車和分類導(dǎo)航,這一節(jié)我們會(huì)完成整個(gè)購物車的流程,以及訂單處理。

該系列主要功能與知識(shí)點(diǎn)如下:

分類、產(chǎn)品瀏覽、購物車、結(jié)算、CRUD(增刪改查) 管理、發(fā)郵件、分頁、模型綁定、認(rèn)證過濾器和單元測試等(預(yù)計(jì)剩余兩篇,周三(因?yàn)橹芏簧习啵┫劝l(fā)布一篇)。

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

目錄

完成購物車

訂單結(jié)算

一、完成購物車

上一節(jié)其實(shí)已經(jīng)完成了移除購物車和清空購物車的方法,只是尚未將可供用戶操作的按鈕放在頁面區(qū)域。除了增加這兩個(gè)按鈕,也會(huì)在頁面頂部的位置增加購物車的摘要(用于顯示用戶的購物總額)。

下面是上一節(jié)已經(jīng)寫好的 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;
 }
 }

1.加入移除書籍和清空購物車的功能

Index.cshtml

@model Wen.BooksStore.WebUI.Models.CartIndexViewModel

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

<table class="table">
 <thead>
 <tr>
  <th>書名</th>
  <th>價(jià)格</th>
  <th>數(shù)量</th>
  <th>總計(jì)</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>
  <td>
   @using (Html.BeginForm("RemoveFromCart", "Cart"))
   {
   @Html.Hidden("id", item.Book.Id)
   @Html.HiddenFor(x => x.ReturnUrl)
   <input type="submit" value="- 移除" />
   }
  </td>
  </tr>
 }
 <tr>
  <td> </td>
  <td> </td>
  <td>總計(jì):</td>
  <td>@Model.Cart.ComputeTotalValue().ToString("C")</td>
  <td>
  @using (Html.BeginForm("Clear", "Cart"))
  {
   @Html.HiddenFor(x => x.ReturnUrl)
   <input type="submit" value="清空購物車" />
  }
  </td>
 </tr>
 </tbody>

</table>

【備注】@Html.Hidden("id", item.Book.Id) 是用于生成隱藏的字段,如果直接使用@Html.HiddenFor(),生成的 name 將會(huì)是 item.Book.Id ,將和 CartController 中 RemoveFromCart(int id, string return) 的參數(shù)不匹配。

顯示的效果如下:

2.添加摘要:我們在購物車存放了許多東西,通過摘要,可以顯示購物總額的縮略圖,我們選擇的位置在頂部右上角的一個(gè)比較顯眼的位置進(jìn)行顯示它,當(dāng)然,還需要有點(diǎn)擊的跳轉(zhuǎn)按鈕方便顯示所有的購物清單頁面。

繼續(xù)在 CartController 下新增一個(gè) Action,名為 Summary,返回值是一個(gè)分部視圖:

/// <summary>
 /// 摘要
 /// </summary>
 /// <returns></returns>
 public PartialViewResult Summary()
 {
  return PartialView(GetCart());
 }

對(duì)應(yīng)的Summary.cshtml

@model Wen.BooksStore.Domain.Entities.Cart

<div class="bookSummary">
 你的購物車:@Model.ComputeTotalValue() 
 <span>@Html.ActionLink("結(jié)算", "Checkout", "Cart", new { retunUrl = Request.Url.PathAndQuery }, null)</span>
</div>

對(duì)應(yīng)的布局頁_Layout.cshtml 修改的地方為:

_Layout.cshtml

<!DOCTYPE html>

<html>
<head>
 <meta name="viewport" content="width=device-width" />
 <title>@ViewBag.Title</title>
 <link href="~/Contents/Site.css" rel="stylesheet" />
</head>
<body>
 <div id="header">
 @{ Html.RenderAction("Summary", "Cart");}
 <div class="title">圖書商城</div>
 </div>
 <div id="sideBar">
 @{ Html.RenderAction("Sidebar", "Nav"); }
 </div>
 <div id="content">
 @RenderBody()
 </div>
</body>
</html>

添加了新的東西,css 也要進(jìn)行修改:

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

二、訂單結(jié)算

購物完畢就是結(jié)算頁面了,這里的訂單結(jié)算并不涉及支付接口的調(diào)用,只是使用郵件的形式進(jìn)行通知而已。

這里,我設(shè)計(jì)結(jié)算的時(shí)候需要要求用戶輸入一些信息,如姓名、地址和郵箱等信息,在點(diǎn)擊確定時(shí)我再將這些輸入的信息與購物清單的信息從系統(tǒng)的郵箱發(fā)到你所輸入的郵箱當(dāng)中。一個(gè)比較直觀的圖:

1.在 Entities 中添加一個(gè)域模型 Contact.cs 表示聯(lián)系人的信息。

/// <summary>
 /// 聯(lián)系信息
 /// </summary>
 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 添加一個(gè)用于結(jié)算的 Action:

/// <summary>
 /// 結(jié)算
 /// </summary>
 /// <returns></returns>
 public ViewResult Checkout()
 {
  return View(new Contact());
 }

Checkout.cshtml 中的:

@model Wen.BooksStore.Domain.Entities.Contact

<div>
 @using (Html.BeginForm())
 {
 <div class="error">@Html.ValidationSummary()</div>
 <div>姓名: @Html.TextBoxFor(x => x.Name)</div>
 <div>地址: @Html.TextBoxFor(x => x.Address)</div>
 <div>郵箱: @Html.TextBoxFor(x => x.Email)</div>
 <div><input type="submit" value="提交" /></div>
 }

</div>

這里使用的是模型校驗(yàn),_Layout.cshtml 布局頁需要引入js:

<script src="~/Scripts/jquery-1.10.2.js"></script>
<script src="~/Scripts/jquery.validate.js"></script>
<script src="~/Scripts/jquery.validate.unobtrusive.js"></script>


<!DOCTYPE html>

<html>
<head>
 <meta name="viewport" content="width=device-width" />
 <title>@ViewBag.Title</title>
 <link href="~/Contents/Site.css" rel="stylesheet" />
 <script src="~/Scripts/jquery-1.10.2.js"></script>
 <script src="~/Scripts/jquery.validate.js"></script>
 <script src="~/Scripts/jquery.validate.unobtrusive.js"></script>
</head>
<body>
 <div id="header">
 @{ Html.RenderAction("Summary", "Cart");}
 <div class="title">圖書商城</div>
 </div>
 <div id="sideBar">
 @{ Html.RenderAction("Sidebar", "Nav"); }
 </div>
 <div id="content">
 @RenderBody()
 </div>
</body>
</html>

嘗試運(yùn)行,會(huì)出現(xiàn)以下頁面,如果信息不填的話會(huì)出現(xiàn)相關(guān)的錯(cuò)誤提示:

2.接下來,要進(jìn)入“提交”后的流程了。

現(xiàn)在還需要一個(gè)組件用于處理訂單,創(chuàng)建一個(gè)用于訂單處理的接口,和一個(gè)該接口的實(shí)現(xiàn),再通過 Ninject 進(jìn)行兩者的綁定:

/// <summary>
 /// 訂單處理
 /// </summary>
 public interface IOrderProcessor
 {
 /// <summary>
 /// 處理訂單
 /// </summary>
 /// <param name="cart"></param>
 /// <param name="contact"></param>
 void ProcessOrder(Cart cart, Contact contact);
 }

建立一個(gè)實(shí)現(xiàn)該接口用于處理訂單的實(shí)體類,這里并不是調(diào)用支付接口,而是簡單通過 BCL 中的進(jìn)行郵件的發(fā)送。

EmailOrderProcessor.cs:

/// <summary>
 /// 郵件訂單處理器
 /// </summary>
 public class EmailOrderProcessor : IOrderProcessor
 {
 /// <summary>
 /// 發(fā)送人
 /// </summary>
 public static class Sender
 {
  /// <summary>
  /// 賬號(hào)
  /// </summary>
  public static string Account = "你的@qq.com";

  /// <summary>
  /// 密碼
  /// </summary>
  public static string Password = "xxx";
 }

 /// <summary>
 /// 處理訂單
 /// </summary>
 /// <param name="cart"></param>
 /// <param name="contact"></param>
 public void ProcessOrder(Cart cart, Contact contact)
 {
  if (string.IsNullOrEmpty(contact.Email))
  {
  throw new Exception("Email 不能為空!");
  }

  var sb = new StringBuilder();
  foreach (var item in cart.GetCartItems)
  {
  sb.AppendLine($"《{item.Book.Name}》:{item.Book.Price} * {item.Quantity} = {item.Book.Price * item.Quantity}");
  }

  sb.AppendLine($"總額:{cart.GetCartItems.Sum(x => x.Quantity * x.Book.Price)}");
  sb.AppendLine();
  sb.AppendLine($"聯(lián)系人:{contact.Name} {contact.Address}");

  //設(shè)置發(fā)件人,發(fā)件人需要與設(shè)置的郵件發(fā)送服務(wù)器的郵箱一致
  var fromAddr = new MailAddress(Sender.Account);
  var message = new MailMessage { From = fromAddr };

  //設(shè)置收件人,可添加多個(gè),添加方法與下面的一樣
  message.To.Add(contact.Email);
  //設(shè)置抄送人
  message.CC.Add(Sender.Account);
  //設(shè)置郵件標(biāo)題
  message.Subject = "您的訂單正在出庫...";
  //設(shè)置郵件內(nèi)容
  message.Body = sb.ToString();
  //設(shè)置郵件發(fā)送服務(wù)器,服務(wù)器根據(jù)你使用的郵箱而不同,可以到相應(yīng)的 郵箱管理后臺(tái)查看,下面是QQ的

  var client = new SmtpClient("smtp.qq.com", 25)
  {
  Credentials = new NetworkCredential(Sender.Account, Sender.Password),
  EnableSsl = true
  };

  //設(shè)置發(fā)送人的郵箱賬號(hào)和密碼
  //啟用ssl,也就是安全發(fā)送
  //發(fā)送郵件
  client.Send(message);
 }

CartController 也需要稍作調(diào)整:

還要在 CartController 中額外添加一個(gè)帶[HttPost] 特性的名為 Checkout 方法:

/// <summary>
 /// 結(jié)算
 /// </summary>
 /// <param name="contact"></param>
 /// <returns></returns>
 [HttpPost]
 public ViewResult Checkout(Contact contact)
 {
  if (!ModelState.IsValid)
  return View(contact);

  var cart = GetCart();
  _orderProcessor.ProcessOrder(cart, contact);
  cart.Clear();
  return View("Thanks");
 }

當(dāng)校驗(yàn)成功時(shí),會(huì)調(diào)用接口發(fā)一條信息,并且清空已有的購物車,然后跳轉(zhuǎn)到指定的一個(gè)新視圖頁:

新建 Thanks.cshtml,內(nèi)容如下:

Thanks

別忘了添加綁定哦,使用 DI 容器將兩者進(jìn)行綁定:

啟動(dòng)頁面,試試效果吧:

看來,好像成功了哦:

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

相關(guān)文章

  • asp.net獲取URL和IP地址的方法匯總

    asp.net獲取URL和IP地址的方法匯總

    asp.net獲取URL和IP地址的方法匯總,需要的朋友可以參考一下
    2013-03-03
  • asp.net Gridview數(shù)據(jù)列中實(shí)現(xiàn)鼠標(biāo)懸浮變色

    asp.net Gridview數(shù)據(jù)列中實(shí)現(xiàn)鼠標(biāo)懸浮變色

    Gridview一般朋友們都比較常用,因?yàn)樗梢苑奖憧旖莸膶?shí)現(xiàn)我們所需的很多功能,代碼也比較簡潔。平時(shí)的項(xiàng)目中這個(gè)控件我也比較常用,其中有個(gè)功能用到的頻率也比較多。所以記錄下備忘。
    2010-06-06
  • ASP.NET MVC中圖表控件的使用方法

    ASP.NET MVC中圖表控件的使用方法

    這篇文章主要介紹了ASP.NET MVC中圖表控件的使用方法,需要的朋友可以參考下
    2015-10-10
  • Asp.net 連接MySQL的實(shí)現(xiàn)代碼[]

    Asp.net 連接MySQL的實(shí)現(xiàn)代碼[]

    ASP.NET連接MySQL需要一個(gè)組件(.net本身不提供訪問MySQL的驅(qū)動(dòng))MySQL.Data.Dll,此為官方提供(純C#開發(fā),開源噢),有多個(gè)版本選擇,采用的數(shù)據(jù)訪問模式為ADO.NET,跟asp.net訪問sqlserver很像,非常簡單。
    2009-08-08
  • ASP.NET MVC5網(wǎng)站開發(fā)概述(一)

    ASP.NET MVC5網(wǎng)站開發(fā)概述(一)

    這篇文章主要內(nèi)容是ASP.NET MVC5網(wǎng)站開發(fā)實(shí)踐的整體概述,分析了開發(fā)環(huán)境、使用的技術(shù)以及項(xiàng)目的整體結(jié)構(gòu),感興趣的小伙伴們可以參考一下
    2015-09-09
  • ASP.NET2.0使用Enter Key作為默認(rèn)提交問題分析(附源碼)

    ASP.NET2.0使用Enter Key作為默認(rèn)提交問題分析(附源碼)

    這篇文章主要介紹了ASP.NET2.0使用Enter Key作為默認(rèn)提交,結(jié)合實(shí)例形式分析了ASP.NET2.0使用Enter Key默認(rèn)提交的注意事項(xiàng)與相關(guān)實(shí)現(xiàn)技巧,并附上源碼供讀者參考,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-11-11
  • ASP.NET 多次提交的解決辦法2

    ASP.NET 多次提交的解決辦法2

    對(duì)“添加”、“提交”、“保存”、“更新”等按鈕需要對(duì)數(shù)據(jù)庫進(jìn)行寫操作的按鈕,一定要在頁面初始化時(shí)加載腳本,防止多次重復(fù)點(diǎn)擊
    2008-12-12
  • Visual Studio 2015和 .NET Core安裝教程

    Visual Studio 2015和 .NET Core安裝教程

    這篇文章主要為大家詳細(xì)介紹了Visual Studio Community 2015和 .NET Core安裝圖文教程,感興趣的小伙伴們可以參考一下
    2016-07-07
  • ASP.NET網(wǎng)頁打印(只打印相關(guān)內(nèi)容/自寫功能)

    ASP.NET網(wǎng)頁打印(只打印相關(guān)內(nèi)容/自寫功能)

    朋友要求在前段時(shí)間完成的新聞的網(wǎng)站上加上一個(gè)功能,就是在每篇新聞瀏覽的頁面, 加一個(gè)打印銨鈕。讓用戶一點(diǎn)打印,能把整篇文章打印
    2013-01-01
  • ASP.NET WebService中使用ASP.NET_SessionId的問題說明

    ASP.NET WebService中使用ASP.NET_SessionId的問題說明

    proxy.CookieContainer存儲(chǔ)了客戶端的 ASP.NET_SessionId。這樣以后每次通過webservice 方法調(diào)用時(shí),都會(huì)將ASP.NET_SessionId傳遞到服務(wù)器端。
    2011-09-09

最新評(píng)論