• 第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="/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>
    我们将第一时间将物品送到您的手中。

     源码:http://yunpan.cn/cds74dVnXuteQ 访问密码 7dbb

     

  • 相关阅读:
    Django 2.0官方文档中文 渣翻 总索引(个人学习,欢迎指正)
    Deep Learning 之 最优化方法
    2018校招笔试真题汇总
    Java Swing 图形界面开发(目录)
    【目录】Spring 源码学习
    【剑指Offer学习】【所有面试题汇总】
    SSM框架学习思维导图
    关于P2P架构的网络游戏
    Styling FX Buttons with CSS
    JavaFx2.0中CSS的应用
  • 原文地址:https://www.cnblogs.com/wjs5943283/p/4693096.html
Copyright © 2020-2023  润新知