MVC專案實踐,在三層架構下實現SportsStore-07,實現訂單提交

Darren Ji發表於2014-06-28

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>

jiezhang

點選結賬,跳轉到一個檢視頁面,填寫必要的聯絡方式等資訊,其對應的模型為:

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

執行:

tijiao

在為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>

執行,點選提交顯示:

huigu

管理員收到郵件:

order


至此,訂單處理結束。

原始碼在這裡

 

“MVC專案實踐,在三層架構下實現SportsStore”系列包括:

MVC專案實踐,在三層架構下實現SportsStore,從類圖看三層架構

MVC專案實踐,在三層架構下實現SportsStore-01,EF Code First建模、DAL層等

MVC專案實踐,在三層架構下實現SportsStore-02,DbSession層、BLL層

MVC專案實踐,在三層架構下實現SportsStore-03,Ninject控制器工廠等

MVC專案實踐,在三層架構下實現SportsStore-04,實現分頁

MVC專案實踐,在三層架構下實現SportsStore-05,實現導航

MVC專案實踐,在三層架構下實現SportsStore-06,實現購物車

MVC專案實踐,在三層架構下實現SportsStore-07,實現訂單提交

MVC專案實踐,在三層架構下實現SportsStore-08,部署到IIS伺服器

MVC專案實踐,在三層架構下實現SportsStore-09,ASP.NET MVC呼叫ASP.NET Web API的查詢服務

MVC專案實踐,在三層架構下實現SportsStore-10,連線字串的加密和解密

MVC專案實踐,在三層架構下實現SportsStore-11,使用Knockout實現增刪改查

相關文章