SportsStore是《精通ASP.NET MVC3框架(第三版)》中演示的MVC專案,在該專案中涵蓋了MVC的眾多方面,包括:使用DI容器、URL優化、導航、分頁、購物車、訂單、產品管理、影象上傳......是不錯的MVC實踐專案,但該專案不是放在多層框架下開發的,離真實專案還有一段距離。本系列將嘗試在多層框架下實現SportsStore專案,並用自己的方式實現一些功能。
本篇為系列第七篇,包括:
■ 9、實現訂單提交
9、實現訂單提交
首先在購物車顯示頁面Cart/Index.cshtml中,新增結賬按鈕:
@model MySportsStore.WebUI.Models.CartIndexViewModel @{ ViewBag.Title = "Index"; Layout = "~/Views/Shared/_Layout.cshtml"; } <table width="50%" align="left"> <thead> <tr> <th align="left">產品名稱</th> <th align="center">數量</th> <th align="right">單價</th> <th align="right">小計</th> <th></th> </tr> </thead> <tbody> @foreach (var line in Model.Cart.Lines) { <tr> <td align="left">@line.Product.Name</td> <td align="center">@line.Quantity</td> <td align="right">@line.Product.Price.ToString("c")</td> <td align="right">@((line.Quantity * line.Product.Price).ToString("c"))</td> <td> @using (Html.BeginForm("RemoveFromCart", "Cart")) { @Html.Hidden("Id", line.Product.Id) @Html.HiddenFor(x => x.ReturnUrl) <input class="actionButtons" type="submit" value="移除"/> } </td> </tr> } </tbody> <tfoot> <tr> <td colspan="3" align="right">總計:</td> <td align="right">@Model.Cart.ComputeTotalValue().ToString("c")</td> </tr> </tfoot> </table> <p align="left" class="actionButtons" style="width: 100%;clear: both"> <a href="@Model.ReturnUrl">繼續購物</a> @Html.ActionLink("結賬","CheckOut") </p>
點選結賬,跳轉到一個檢視頁面,填寫必要的聯絡方式等資訊,其對應的模型為:
using System.ComponentModel.DataAnnotations; namespace MySportsStore.Model { public class ShippingDetail { [Required(ErrorMessage = "必填")] [Display(Name = "姓名")] public string Name { get; set; } [Required(ErrorMessage = "必填")] [Display(Name = "地址")] public string Line { get; set; } } }
訂單提交頁Cart/CheckOUt.cshtml:
@model MySportsStore.Model.ShippingDetail @{ ViewBag.Title = "CheckOut"; Layout = "~/Views/Shared/_Layout.cshtml"; } <h2>填寫地址等資訊</h2> @using (Html.BeginForm()) { @Html.LabelFor(m => m.Name) @Html.EditorFor(m => m.Name) @Html.ValidationMessageFor(m => m.Name) <br/><br/> @Html.LabelFor(m => m.Line) @Html.EditorFor(m => m.Line) @Html.ValidationMessageFor(m => m.Line) <p align="center"> <input class="actionButtons" type="submit" value="提交訂單"/> </p> }
執行:
在為Cart控制器新增處理訂單的方法之前,我們首先定義一個處理訂單的介面:
using MySportsStore.Model; using MySportsStore.WebUI.Models; namespace MySportsStore.WebUI.Abstract { public interface IOrderProcessor { void ProcessOrder(Cart cart, ShippingDetail shippingDetail); } }
假設,我們希望在接到訂單時發郵件給管理員,建立一個實現IOrderProcessor的類:
using System.Net; using System.Net.Mail; using System.Text; using MySportsStore.WebUI.Abstract; namespace MySportsStore.WebUI.Concrete { public class EmailOrderProcessor : IOrderProcessor { public void ProcessOrder(Models.Cart cart, Model.ShippingDetail shippingDetail) { MailMessage mailMsg = new MailMessage(); mailMsg.From = new MailAddress("qdjjx9441@sina.com"); mailMsg.To.Add(new MailAddress("764190362@qq.com")); mailMsg.Subject = "新訂單"; //郵件內容主體 StringBuilder body = new StringBuilder(); body.AppendLine("接收到一個新訂單:"); body.AppendLine("<br />"); body.AppendLine("訂購商品包括:"); body.AppendLine("<br />"); foreach (var line in cart.Lines) { var subTotal = line.Product.Price * line.Quantity; body.AppendFormat("{0}*{1}(小計:{2:c})", line.Quantity, line.Product.Name, subTotal); body.AppendLine("<br />"); } body.AppendFormat("總計:{0:c}", cart.ComputeTotalValue()); body.AppendLine("<br />"); body.AppendLine("收貨人資訊:"); body.AppendLine(shippingDetail.Name); body.AppendLine(shippingDetail.Line); body.AppendLine("<br />"); mailMsg.Body = body.ToString(); mailMsg.IsBodyHtml = true; SmtpClient smtpClient = new SmtpClient("smtp.sina.com"); smtpClient.Credentials = new NetworkCredential("some username", "some password"); smtpClient.Send(mailMsg); } } }
把介面IOrderProcessor和實現類EmailOrderProcessor交給Ninject來實現,以便依賴注入:
private void AddBindings() { ninjectKernel.Bind<IProductService>().To<ProductService>(); ninjectKernel.Bind<IOrderProcessor>().To<EmailOrderProcessor>(); }
現在可以在Cart控制器中新增處理訂單的邏輯:
using System.Linq; using System.Web.Mvc; using MySportsStore.IBLL; using MySportsStore.Model; using MySportsStore.WebUI.Abstract; using MySportsStore.WebUI.Models; using Ninject; namespace MySportsStore.WebUI.Controllers { public class CartController : BaseController { [Inject] public IProductService ProductService { get; set; } [Inject] public IOrderProcessor OrderProcessor { get; set; } public CartController() { this.AddDisposableObject(ProductService); this.AddDisposableObject(OrderProcessor); } public ViewResult CheckOut() { return View(new ShippingDetail()); } [HttpPost] public ViewResult CheckOut(Cart cart, ShippingDetail shippingDetail) { if (cart.Lines.Count() == 0) { ModelState.AddModelError("","購物車為空"); } if (ModelState.IsValid) { OrderProcessor.ProcessOrder(cart, shippingDetail); cart.Clear(); return View("Completed"); } else { return View(shippingDetail); } } ...... } }
訂單提交成功後,顯示Cart/Completed.cshtml檢視:
@{ ViewBag.Title = "Completed"; Layout = "~/Views/Shared/_Layout.cshtml"; } <h2>謝謝惠顧~~</h2>
執行,點選提交顯示:
管理員收到郵件:
至此,訂單處理結束。
原始碼在這裡。
“MVC專案實踐,在三層架構下實現SportsStore”系列包括: