码迷,mamicode.com
首页 > 其他好文 > 详细

第9章 SportsStorePeta 完成购物车

时间:2015-08-01 23:21:48      阅读:162      评论:0      收藏:0      [点我收藏+]

标签:

一、使用模型绑定

    模型绑定:通过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

 

第9章 SportsStorePeta 完成购物车

标签:

原文地址:http://www.cnblogs.com/wjs5943283/p/4693096.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!