标签:
一、使用模型绑定
模型绑定:通过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
标签:
原文地址:http://www.cnblogs.com/wjs5943283/p/4693096.html