你的位置:首页 > ASP.net教程

[ASP.net教程]第9章 SportsStorePeta 完成购物车


一、使用模型绑定

    模型绑定:通过HTTP请求来创建一些C#对象,目的把它们做为参数值传递给动作方法。

  创建自定义模型绑定器 (通过实现IModelBinder接口。)

using System;using System.Collections.Generic;using System.Linq;using System.Web;using System.Web.Mvc;using SportsStorePeta.Domain.Entities;namespace SportsStorePeta.WebUI.Binders{  public class CartModelBinder :IModelBinder  {    private const string seesionKey = "Cart";    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)    {      //通过会话获取Cart      Cart cart = (Cart) controllerContext.HttpContext.Session[seesionKey];      //若会话中没有Cart,则创建      if (cart == null)      {        cart=new Cart();        controllerContext.HttpContext.Session[seesionKey] = cart;      }      //返回cart      return cart;    }  }}

  注册CartModelBinder类:

  //注册自定义模型绑定器  ModelBinders.Binders.Add(typeof(Cart),new CartModelBinder());

  更新CartController:

using System;using System.Collections.Generic;using System.Linq;using System.Web;using System.Web.Mvc;using SportsStorePeta.Domain.Abstract;using SportsStorePeta.Domain.Entities;using SportsStorePeta.WebUI.Models;namespace SportsStorePeta.WebUI.Controllers{  public class CartController : Controller  {    private IProductRepository _repository;    public CartController(IProductRepository repo)    {      _repository = repo;    }    public ViewResult Index(Cart cart,string returnUrl)    {      return View(new CartIndexViewModel { Cart = cart, ReturnUrl = returnUrl });    }    public RedirectToRouteResult AddToCart(Cart cart, int productId, string returnUrl)    {      Product product = _repository.Products.FirstOrDefault(p => p.ProductId == productId);      if (product != null)      {        cart.AddItem(product, 1);      }      return RedirectToAction("Index", new {returnUrl});    }    public RedirectToRouteResult RemoveFromCart(Cart cart, int productId, string returnUrl)    {       Product product = _repository.Products.FirstOrDefault(p => p.ProductId == productId);      if (product != null)      {        cart.RemoveLine(product);      }      return RedirectToAction("Index", new { returnUrl });    }  }}

 

二、完成购物车

  1.删除购物车物品

    引入删除按钮

  <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("ProductId",line.Product.ProductId)          @Html.HiddenFor(x=>x.ReturnUrl)          <input class="actionButtons" type="submit" value="删除"/>        }</td>    </tr>  }  </tbody>

  2.添加购物车摘要

    添加Summary方法 

    public PartialViewResult Summary(Cart cart)    {      return PartialView(cart);    }

    添加Summary分部视图

@model SportsStorePeta.Domain.Entities.Cart<div id="cart">  <span class="caption">    <b>购物车</b>    @Model.Lines.Sum(x => x.Quantity) 件物品,    @Model.ComputeTotalValue().ToString("C")  </span>  @Html.ActionLink("结算","Index","Cart",new{returnUrl=Request.Url.PathAndQuery},null)</div>

    将购物车摘要分部视图添加到布局

<!DOCTYPE html><html><head>  <meta charset="utf-8" />  <meta name="viewport" content="width=device-width" />  <title>@ViewBag.Title</title>  <link href="http://www.cnblogs.com//Content/Site.css" type="text/css" rel="stylesheet"/></head><body><div id="header">  @{Html.RenderAction("Summary","Cart");}  <div class="title">体育用品</div></div><div id="categories">  @{    Html.RenderAction("Menu","Nav");  }</div><div id="content">  @RenderBody()</div></body></html>

  添加CSS

div#cart {  float: right;margin: .8em;color: silver;  background-color: #555;padding: .5em .5em .5em 1em;}div#cart a {  text-decoration: none;padding: .4em 1em .4em 1em;line-height: 2.1em;  margin-left: .5em;background-color: #333;color: white;border: 1px solid black;}

三、递交订单

  1.扩充域模型ShippingDetails类(添加引用System.ComponentModel.DataAnnotations)    

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.ComponentModel.DataAnnotations;namespace SportsStorePeta.Domain.Entities{  public class ShippingDetails  {    [Required(ErrorMessage = "请输入姓名")]    public string Name { get; set; }    [Required(ErrorMessage = "请输入地址")]    public string Line1 { get; set; }    public string Line2 { get; set; }    public string Line3 { get; set; }    [Required(ErrorMessage = "请输入城市名称")]    public string City { get; set; }    [Required(ErrorMessage = "请输入省份名称")]    public string State { get; set; }    public string Zip { get; set; }    [Required(ErrorMessage = "请输入国家名称")]    public string Country { get; set; }    public bool GiftWrap { get; set; }  }}

  2.添加结算过程

    添加结算按钮 

<p align="center" class="actionButtons">  <a href="@Model.ReturnUrl">继续购物</a>  @Html.ActionLink("结算","Checkout")</p>

    Checkout动作方法

    public ViewResult Checkout()    {      return View(new ShippingDetails());    }

    Checkout视图

@model SportsStorePeta.Domain.Entities.ShippingDetails@{  ViewBag.Title = "结算";}<h2>现在结算</h2>请填写联系单:@using (Html.BeginForm()){  <h3>收货信息:</h3>  <div>收货人:@Html.EditorFor(x => x.Name)</div>  <h3>地址:</h3>  <div>详细地址1:@Html.EditorFor(x => x.Line1)</div>  <div>详细地址2:@Html.EditorFor(x => x.Line2)</div>  <div>详细地址3:@Html.EditorFor(x => x.Line3)</div>  <div>城市:@Html.EditorFor(x => x.City)</div>  <div>省:@Html.EditorFor(x => x.State)</div>  <div>邮编:@Html.EditorFor(x => x.Zip)</div>  <div>国家:@Html.EditorFor(x => x.Country)</div>  <label>@Html.EditorFor(x => x.GiftWrap)礼盒包装</label>  <p align="center">    <input class="actionButtons" type="submit" value="完成订单"/>  </p>   } 

 3.实现订单处理器

   定义接口

using System;using System.Collections.Generic;using System.Linq;using System.Text;using SportsStorePeta.Domain.Entities;namespace SportsStorePeta.Domain.Abstract{ public interface IOrderProcessor {   void ProcessOrder(Cart cart, ShippingDetails shippingDetails); }}

   实现接口:

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Net.Mail;using System.Net;using SportsStorePeta.Domain.Abstract;using SportsStorePeta.Domain.Entities;namespace SportsStorePeta.Domain.Concrete{  public class EmailSettings  {    public string MailToAddress = "123456789@qq.com";    public string MailFromAddress = "123456779@163.com";    public bool UseSsl = true;    public string Username = "123456779";    public string Password = "123123123123";    public string ServerName = "smtp.163.com";    public int ServerPort = 25;    public bool WriteAsFile = false;    public string FileLocation = @"c:\sports_store_emails";  }  public class EmailOrderProcessor :IOrderProcessor  {    private EmailSettings _emailSettings;    public EmailOrderProcessor(EmailSettings settings)    {      _emailSettings = settings;    }    public void ProcessOrder(Cart cart, ShippingDetails shippingDetails)    {      using (var smtpClient = new SmtpClient())      {        smtpClient.EnableSsl = _emailSettings.UseSsl;        smtpClient.Host = _emailSettings.ServerName;        smtpClient.Port = _emailSettings.ServerPort;        smtpClient.UseDefaultCredentials = false;        smtpClient.Credentials = new NetworkCredential(_emailSettings.Username, _emailSettings.Password);        if (_emailSettings.WriteAsFile)        {          smtpClient.DeliveryMethod = SmtpDeliveryMethod.SpecifiedPickupDirectory;          smtpClient.PickupDirectoryLocation = _emailSettings.FileLocation;          smtpClient.EnableSsl = false;        }        StringBuilder body = new StringBuilder().Append("收到新订单").Append("----").Append("物品为:");        foreach (var line in cart.Lines)        {          var subtotal = line.Product.Price * line.Quantity;          body.AppendFormat("{0}X{1}(金额:{2:c}", line.Quantity, line.Product.Name, subtotal);        }        body.AppendFormat("总价:{0:c}", cart.ComputeTotalValue())          .AppendLine("---")          .AppendLine("邮寄给:")          .AppendLine(shippingDetails.Name)          .AppendLine(shippingDetails.Line1)          .AppendLine(shippingDetails.Line2 ?? "")          .AppendLine(shippingDetails.Line3 ?? "")          .AppendLine(shippingDetails.City)          .AppendLine(shippingDetails.State ?? "")          .AppendLine(shippingDetails.Country)          .AppendLine(shippingDetails.Zip)          .AppendLine("---")          .AppendFormat("{0}礼品包装:", shippingDetails.GiftWrap ? "需要" : "不要");        MailMessage mailMessage = new MailMessage(_emailSettings.MailFromAddress, _emailSettings.MailToAddress,          "新的订单", body.ToString());        if (_emailSettings.WriteAsFile)        {          mailMessage.BodyEncoding = Encoding.UTF8;        }        smtpClient.Send(mailMessage);      }    }  }}

  4.注册实现

private void AddBindings()    {      //Ninject绑定      //1.添加模拟IproductRepository实现      //Mock<IProductRepository> mock=new Mock<IProductRepository>();      //mock.Setup(m => m.Products).Returns(      //  new List<Product>      //  {      //    new Product {Name = "Football", Price = 35},      //    new Product {Name = "Surf board", Price = 179},      //    new Product {Name = "Running shoes", Price = 87}      //  }.AsQueryable());      //永久绑定      // _ninjectKernel.Bind<IProductRepository>().ToConstant(mock.Object);      _ninjectKernel.Bind<IProductRepository>().To<PpProductRepository>();      //添加支付绑定      EmailSettings emailSettings = new EmailSettings()      {        WriteAsFile = Boolean.Parse(ConfigurationManager.AppSettings["Email.writeAsFile"] ?? "false")      };      _ninjectKernel.Bind<IOrderProcessor>().To<EmailOrderProcessor>().WithConstructorArgument("settings",emailSettings );    }

<appSettings>  <add key="webpages:Version" value="2.0.0.0" />  <add key="webpages:Enabled" value="false" />  <add key="PreserveLoginUrl" value="true" />  <add key="ClientValidationEnabled" value="true" />  <add key="UnobtrusiveJavaScriptEnabled" value="true" />  <add key="Email.writeAsFile" value="true"/> </appSettings>

  5.完成购物车控制器

using System;using System.Collections.Generic;using System.Linq;using System.Web;using System.Web.Mvc;using SportsStorePeta.Domain.Abstract;using SportsStorePeta.Domain.Entities;using SportsStorePeta.WebUI.Models;namespace SportsStorePeta.WebUI.Controllers{  public class CartController : Controller  {    private IProductRepository _repository;    private IOrderProcessor _orderProcessor;    public CartController(IProductRepository repo,IOrderProcessor orderProcessor)    {      _repository = repo;      _orderProcessor = orderProcessor;    }    public ViewResult Index(Cart cart,string returnUrl)    {      return View(new CartIndexViewModel { Cart = cart, ReturnUrl = returnUrl });    }    public RedirectToRouteResult AddToCart(Cart cart, int productId, string returnUrl)    {      Product product = _repository.Products.FirstOrDefault(p => p.ProductId == productId);      if (product != null)      {        cart.AddItem(product, 1);      }      return RedirectToAction("Index", new {returnUrl});    }    public RedirectToRouteResult RemoveFromCart(Cart cart, int productId, string returnUrl)    {       Product product = _repository.Products.FirstOrDefault(p => p.ProductId == productId);      if (product != null)      {        cart.RemoveLine(product);      }      return RedirectToAction("Index", new { returnUrl });    }    public PartialViewResult Summary(Cart cart)    {      return PartialView(cart);    }    public ViewResult Checkout()    {      return View(new ShippingDetails());    }     [HttpPost]    public ViewResult Checkout(Cart cart, ShippingDetails shippingDetails)    {      if (!cart.Lines.Any())      {       ModelState.AddModelError("","您的购物车是空的!");       }      if (ModelState.IsValid)      {        _orderProcessor.ProcessOrder(cart,shippingDetails);        cart.Clear();        return View("Completed");      }      else      {        return View(shippingDetails);      }    }    }}

  6.显示验证错误

@model SportsStorePeta.Domain.Entities.ShippingDetails@{  ViewBag.Title = "结算";}<h2>现在结算</h2>请填写联系单:@using (Html.BeginForm()){   @Html.ValidationSummary()  <h3>收货信息:</h3>  <div>收货人:@Html.EditorFor(x => x.Name)</div>  <h3>地址:</h3>  <div>详细地址1:@Html.EditorFor(x => x.Line1)</div>  <div>详细地址2:@Html.EditorFor(x => x.Line2)</div>  <div>详细地址3:@Html.EditorFor(x => x.Line3)</div>  <div>城市:@Html.EditorFor(x => x.City)</div>  <div>省:@Html.EditorFor(x => x.State)</div>  <div>邮编:@Html.EditorFor(x => x.Zip)</div>  <div>国家:@Html.EditorFor(x => x.Country)</div>  <label>@Html.EditorFor(x => x.GiftWrap)礼盒包装</label>  <p align="center">    <input class="actionButtons" type="submit" value="完成订单"/>  </p>   }

  7.显示致谢页面Completed.cshtml视图 

@{  ViewBag.Title = "订单已提交";}<h2>谢谢您的惠顾,祝您生活愉快 ^_^</h2>我们将第一时间将物品送到您的手中。