MVC项目实践,在三层架构下实现SportsStore-07,实现订单提交

2022-11-29,,,,

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”系列包括:

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实现增删改查

MVC项目实践,在三层架构下实现SportsStore-07,实现订单提交的相关教程结束。

《MVC项目实践,在三层架构下实现SportsStore-07,实现订单提交.doc》

下载本文的Word格式文档,以方便收藏与打印。