SportsStore是《精通ASP.NET MVC3框架(第三版)》中演示的MVC项目,在该项目中涵盖了MVC的众多方面,包括:使用DI容器、URL优化、导航、分页、购物车、订单、产品管理、图像上传......是不错的MVC实践项目,但该项目不是放在多层框架下开发的,离真实项目还有一段距离。本系列将尝试在多层框架下实现SportsStore项目,并用自己的方式实现一些功能。

本篇为系列第七篇,包括:

■ 9、实现订单提交

9、实现订单提交

首先在购物车显示页面Cart/Index.cshtml中,添加结账按钮:

  1. @model MySportsStore.WebUI.Models.CartIndexViewModel
  2.  
  3. @{
  4. ViewBag.Title = "Index";
  5. Layout = "~/Views/Shared/_Layout.cshtml";
  6. }
  7.  
  8. <table width="50%" align="left">
  9. <thead>
  10. <tr>
  11. <th align="left">产品名称</th>
  12. <th align="center">数量</th>
  13. <th align="right">单价</th>
  14. <th align="right">小计</th>
  15. <th></th>
  16. </tr>
  17. </thead>
  18. <tbody>
  19. @foreach (var line in Model.Cart.Lines)
  20. {
  21. <tr>
  22. <td align="left">@line.Product.Name</td>
  23. <td align="center">@line.Quantity</td>
  24. <td align="right">@line.Product.Price.ToString("c")</td>
  25. <td align="right">@((line.Quantity * line.Product.Price).ToString("c"))</td>
  26. <td>
  27. @using (Html.BeginForm("RemoveFromCart", "Cart"))
  28. {
  29. @Html.Hidden("Id", line.Product.Id)
  30. @Html.HiddenFor(x => x.ReturnUrl)
  31. <input class="actionButtons" type="submit" value="移除"/>
  32. }
  33. </td>
  34. </tr>
  35. }
  36. </tbody>
  37. <tfoot>
  38. <tr>
  39. <td colspan="3" align="right">总计:</td>
  40. <td align="right">@Model.Cart.ComputeTotalValue().ToString("c")</td>
  41. </tr>
  42. </tfoot>
  43. </table>
  44. <p align="left" class="actionButtons" style="width: 100%;clear: both">
  45. <a href="@Model.ReturnUrl">继续购物</a>
  46. @Html.ActionLink("结账","CheckOut")
  47. </p>

点击结账,跳转到一个视图页面,填写必要的联系方式等信息,其对应的模型为:

  1. using System.ComponentModel.DataAnnotations;
  2.  
  3. namespace MySportsStore.Model
  4. {
  5. public class ShippingDetail
  6. {
  7. [Required(ErrorMessage = "必填")]
  8. [Display(Name = "姓名")]
  9. public string Name { get; set; }
  10.  
  11. [Required(ErrorMessage = "必填")]
  12. [Display(Name = "地址")]
  13. public string Line { get; set; }
  14. }
  15. }

订单提交页Cart/CheckOUt.cshtml:

  1. @model MySportsStore.Model.ShippingDetail
  2.  
  3. @{
  4. ViewBag.Title = "CheckOut";
  5. Layout = "~/Views/Shared/_Layout.cshtml";
  6. }
  7.  
  8. <h2>填写地址等信息</h2>
  9.  
  10. @using (Html.BeginForm())
  11. {
  12. @Html.LabelFor(m => m.Name)
  13. @Html.EditorFor(m => m.Name)
  14. @Html.ValidationMessageFor(m => m.Name)
  15. <br/><br/>
  16. @Html.LabelFor(m => m.Line)
  17. @Html.EditorFor(m => m.Line)
  18. @Html.ValidationMessageFor(m => m.Line)
  19.  
  20. <p align="center">
  21. <input class="actionButtons" type="submit" value="提交订单"/>
  22. </p>
  23. }

运行:

在为Cart控制器添加处理订单的方法之前,我们首先定义一个处理订单的接口:

  1. using MySportsStore.Model;
  2. using MySportsStore.WebUI.Models;
  3.  
  4. namespace MySportsStore.WebUI.Abstract
  5. {
  6. public interface IOrderProcessor
  7. {
  8. void ProcessOrder(Cart cart, ShippingDetail shippingDetail);
  9.  
  10. }
  11. }

假设,我们希望在接到订单时发邮件给管理员,创建一个实现IOrderProcessor的类:

  1. using System.Net;
  2. using System.Net.Mail;
  3. using System.Text;
  4. using MySportsStore.WebUI.Abstract;
  5.  
  6. namespace MySportsStore.WebUI.Concrete
  7. {
  8. public class EmailOrderProcessor : IOrderProcessor
  9. {
  10. public void ProcessOrder(Models.Cart cart, Model.ShippingDetail shippingDetail)
  11. {
  12. MailMessage mailMsg = new MailMessage();
  13. mailMsg.From = new MailAddress("qdjjx9441@sina.com");
  14. mailMsg.To.Add(new MailAddress("764190362@qq.com"));
  15. mailMsg.Subject = "新订单";
  16.  
  17. //邮件内容主体
  18. StringBuilder body = new StringBuilder();
  19. body.AppendLine("接收到一个新订单:");
  20. body.AppendLine("<br />");
  21. body.AppendLine("订购商品包括:");
  22. body.AppendLine("<br />");
  23. foreach (var line in cart.Lines)
  24. {
  25. var subTotal = line.Product.Price * line.Quantity;
  26. body.AppendFormat("{0}*{1}(小计:{2:c})", line.Quantity, line.Product.Name, subTotal);
  27. body.AppendLine("<br />");
  28. }
  29. body.AppendFormat("总计:{0:c}", cart.ComputeTotalValue());
  30. body.AppendLine("<br />");
  31. body.AppendLine("收货人信息:");
  32. body.AppendLine(shippingDetail.Name);
  33. body.AppendLine(shippingDetail.Line);
  34. body.AppendLine("<br />");
  35.  
  36. mailMsg.Body = body.ToString();
  37. mailMsg.IsBodyHtml = true;
  38. SmtpClient smtpClient = new SmtpClient("smtp.sina.com");
  39. smtpClient.Credentials = new NetworkCredential("some username", "some password");
  40.  
  41. smtpClient.Send(mailMsg);
  42. }
  43. }
  44. }

把接口IOrderProcessor和实现类EmailOrderProcessor交给Ninject来实现,以便依赖注入:

  1. private void AddBindings()
  2. {
  3. ninjectKernel.Bind<IProductService>().To<ProductService>();
  4. ninjectKernel.Bind<IOrderProcessor>().To<EmailOrderProcessor>();
  5. }

现在可以在Cart控制器中添加处理订单的逻辑:

  1. using System.Linq;
  2. using System.Web.Mvc;
  3. using MySportsStore.IBLL;
  4. using MySportsStore.Model;
  5. using MySportsStore.WebUI.Abstract;
  6. using MySportsStore.WebUI.Models;
  7. using Ninject;
  8.  
  9. namespace MySportsStore.WebUI.Controllers
  10. {
  11. public class CartController : BaseController
  12. {
  13. [Inject]
  14. public IProductService ProductService { get; set; }
  15.  
  16. [Inject]
  17. public IOrderProcessor OrderProcessor { get; set; }
  18.  
  19. public CartController()
  20. {
  21. this.AddDisposableObject(ProductService);
  22. this.AddDisposableObject(OrderProcessor);
  23. }
  24.  
  25. public ViewResult CheckOut()
  26. {
  27. return View(new ShippingDetail());
  28. }
  29.  
  30. [HttpPost]
  31. public ViewResult CheckOut(Cart cart, ShippingDetail shippingDetail)
  32. {
  33. if (cart.Lines.Count() == 0)
  34. {
  35. ModelState.AddModelError("","购物车为空");
  36. }
  37. if (ModelState.IsValid)
  38. {
  39. OrderProcessor.ProcessOrder(cart, shippingDetail);
  40. cart.Clear();
  41. return View("Completed");
  42. }
  43. else
  44. {
  45. return View(shippingDetail);
  46. }
  47. }
  48. ......
  49.  
  50. }
  51. }

订单提交成功后,显示Cart/Completed.cshtml视图:

  1. @{
  2. ViewBag.Title = "Completed";
  3. Layout = "~/Views/Shared/_Layout.cshtml";
  4. }
  5.  
  6. <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,实现订单提交的更多相关文章

  1. MVC项目实践,在三层架构下实现SportsStore,从类图看三层架构

    在"MVC项目实践,在三层架构下实现SportsStore-02,DbSession层.BLL层"一文的评论中,博友浪花一朵朵建议用类图来理解本项目的三层架构.于是就有了本篇: I ...

  2. MVC项目实践,在三层架构下实现SportsStore-02,DbSession层、BLL层

    SportsStore是<精通ASP.NET MVC3框架(第三版)>中演示的MVC项目,在该项目中涵盖了MVC的众多方面,包括:使用DI容器.URL优化.导航.分页.购物车.订单.产品管 ...

  3. MVC项目实践,在三层架构下实现SportsStore-01,EF Code First建模、DAL层等

    SportsStore是<精通ASP.NET MVC3框架(第三版)>中演示的MVC项目,在该项目中涵盖了MVC的众多方面,包括:使用DI容器.URL优化.导航.分页.购物车.订单.产品管 ...

  4. MVC项目实践,在三层架构下实现SportsStore-03,Ninject控制器工厂等

    SportsStore是<精通ASP.NET MVC3框架(第三版)>中演示的MVC项目,在该项目中涵盖了MVC的众多方面,包括:使用DI容器.URL优化.导航.分页.购物车.订单.产品管 ...

  5. MVC项目实践,在三层架构下实现SportsStore-04,实现分页

    SportsStore是<精通ASP.NET MVC3框架(第三版)>中演示的MVC项目,在该项目中涵盖了MVC的众多方面,包括:使用DI容器.URL优化.导航.分页.购物车.订单.产品管 ...

  6. MVC项目实践,在三层架构下实现SportsStore-05,实现导航

    SportsStore是<精通ASP.NET MVC3框架(第三版)>中演示的MVC项目,在该项目中涵盖了MVC的众多方面,包括:使用DI容器.URL优化.导航.分页.购物车.订单.产品管 ...

  7. MVC项目实践,在三层架构下实现SportsStore-06,实现购物车

    SportsStore是<精通ASP.NET MVC3框架(第三版)>中演示的MVC项目,在该项目中涵盖了MVC的众多方面,包括:使用DI容器.URL优化.导航.分页.购物车.订单.产品管 ...

  8. MVC项目实践,在三层架构下实现SportsStore-08,部署到IIS服务器

    SportsStore是<精通ASP.NET MVC3框架(第三版)>中演示的MVC项目,在该项目中涵盖了MVC的众多方面,包括:使用DI容器.URL优化.导航.分页.购物车.订单.产品管 ...

  9. MVC项目实践,在三层架构下实现SportsStore-09,ASP.NET MVC调用ASP.NET Web API的查询服务

    ASP.NET Web API和WCF都体现了REST软件架构风格.在REST中,把一切数据视为资源,所以也是一种面向资源的架构风格.所有的资源都可以通过URI来唯一标识,通过对资源的HTTP操作(G ...

随机推荐

  1. 如何使用CREATE INDEX语句对表增加索引?

    创建和删除索引索引的创建可以在CREATE TABLE语句中进行,也可以单独用CREATE INDEX或ALTER TABLE来给表增加索引.删除索引可以利用ALTER TABLE或DROP INDE ...

  2. fastjson格式化bean的简易属性过滤器

    fastjson的bean属性过滤器 有的时候,我们在接口开发时,一个完整的bean会包含很多属性,但是前端接口只需要其中的某几个属性时,应该在对json的返回要进行精简.下面直接看代码 packag ...

  3. 【iHMI43 4.3寸液晶模块】demo竖屏例程(版本1.01)发布

    ============================== 技术论坛:http://www.eeschool.org 博客地址:http://xiaomagee.cnblogs.com 官方网店:h ...

  4. ElasticSearch实战-日志监控平台

    1.概述 在项目业务倍增的情况下,查询效率受到影响,这里我们经过讨论,引进了分布式搜索套件——ElasticSearch,通过分布式搜索来解决当下业务上存在的问题.下面给大家列出今天分析的目录: El ...

  5. 移动Web应用开发入门指南——交互篇

    交互篇 从PC到移动端,视觉和交互是用户能直接感受到的差异.在视觉篇中已经提到,移动设备的物理属性一部分影响到视觉,另外一些部分将影响到交互.那么,移动设备影响交互的物理属性都有哪些变化呢?对于这个问 ...

  6. JDBC链接数据库版本三,使用C3P0,使用jar文件两个

    JdbcUtil类: package com.xiaohui.jdbc.util; import java.sql.Connection; import java.sql.PreparedStatem ...

  7. GDC 2016 神秘海域4中使用Substance制作Texture

    TEXTURING UNCHARTED 4: A MATTER OF SUBSTANCE 原文链接 http://www.dualshockers.com/2016/03/16/amazing-unc ...

  8. PHP调用java的class

    PHP调用java的class   转:http://hi.baidu.com/lei0827/blog/item/28439a4e923234ced1c86a18.html PHP调用java的cl ...

  9. xenserver+starwind架构布署

    主机 CPU 和主板均需支持 INTER-VT/ AMD-VT ,主板默认可能没开  进BISO开启  下载最新的 xenserver ,授权注册一下 轻松得到授权文件 (鄙视一下VMWARE,看人家 ...

  10. try...except 错误记录添加logging