ASP.NET MVC SportStore 购物网示例(5)

创建一个自定义的Model绑定

在WebUI根目录添加 CartModelBinder类

 

public class CartModelBinder : IModelBinder
 
 
{
 
 
private const string cartSessionKey = "_cart";
 
 
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
 
 
{
 
 
if (bindingContext.Model != null)
 
 
throw new InvalidOperationException("Cannot update instances");
 
 
// reurn the cart form session[](create it first if necessary)
 
 
Cart cart = (Cart)controllerContext.HttpContext.Session[cartSessionKey];
 
 
if (cart == null)
 
 
{
 
 
cart = new Cart();
 
 
controllerContext.HttpContext.Session[cartSessionKey] = cart;
 
 
}
 
 
return cart;
 
 
}
 
 
}
 
 
通知MVC使用:
 
 
protected void Application_Start()
 
 
{
 
 
AreaRegistration.RegisterAllAreas();
 
 
RegisterRoutes(RouteTable.Routes);
 
 
ControllerBuilder.Current.SetControllerFactory(new WindsorControllerFactory());
 
 
ModelBinders.Binders.Add(typeof(Cart), new CartModelBinder());
 
 
}

创建 CartController

创建CartController的单元测试

[TestFixture]
 
 
public class CartControllerTest
 
 
{
 
 
[Test]
 
 
public void Can_Add_Product_To_Cart()
 
 
{
 
 
var mockProductsRepos = new Moq.Mock<IProductsRepository>();
 
 
var products = new List<Product>
 
 
{
 
 
new Product{ProductID = 14,Name="Much Ado About Nothig"},
 
 
new Product{ProductID = 27,Name="The Comedy of error"}
 
 
};
 
 
mockProductsRepos.Setup(x => x.Products).Returns(products.AsQueryable());
 
 
var cart = new Cart();
 
 
var controller = new CartController(mockProductsRepos.Object);
 
 
RedirectToRouteResult result =
 
 
controller.AddToCart(cart, 27, "someReturnUrl");
 
 
Assert.AreEqual(1, cart.Lines.Count);
 
 
Assert.AreEqual("The comedy of Errors", cart.Lines[0].Product.Name);
 
 
Assert.AreEqual(1, cart.Lines[0].Quantity);
 
 
// Check that the visitor was redirected to the cart display screen
 
 
Assert.AreEqual("Index", result.RouteValues["action"]);
 
 
Assert.AreEqual("someReturnUrl", result.RouteValues["returnUrl"]);
 
 
}
 
 
}

F5运行测试。单击 Add to Cart 按钮。

clip_image002[4]

测试CartController的Index Action

[Test]
 
 
public void Index_Action_Renders_Default_View_Width_Cart_and_ReturnUrl()
 
 
{
 
 
// Set up the controller
 
 
Cart cart = new Cart();
 
 
CartController controller = new CartController(null);
 
 
// Invoke action method
 
 
ViewResult result = controller.Index(cart, "myReturnUrl");
 
 
// Verify results
 
 
Assert.IsEmpty(result.ViewName); // Renders default view
 
 
Assert.AreSame(cart, result.ViewData.Model);
 
 
Assert.AreEqual("myReturnUrl", result.ViewData["returnUrl"]);
 
 
Assert.AreEqual("Cart", result.ViewData["CurrentCategory"]);
 
 
}

为Index添加 View

clip_image003[4]

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<DomainModel.Entities.Cart>" %>
 
 
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
 
 
SportsStore : Your Cart
 
 
</asp:Content>
 
 
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
 
 
<h2>
 
 
Your cart</h2>
 
 
<table width="90%" align="center">
 
 
<thead>
 
 
<tr>
 
 
<th align="center">
 
 
Quantity
 
 
</th>
 
 
<th align="left">
 
 
Item
 
 
</th>
 
 
<th align="right">
 
 
Price
 
 
</th>
 
 
<th align="right">
 
 
Subtotal
 
 
</th>
 
 
</tr>
 
 
</thead>
 
 
<tbody>
 
 
<% foreach (var line in Model.Lines)
 
 
{%>
 
 
<tr>
 
 
<td align="center">
 
 
<%= line.Quantity %>
 
 
</td>
 
 
<td align="left">
 
 
<%= line.Product.Name %>
 
 
</td>
 
 
<td align="right">
 
 
<%= line.Product.Price.ToString("c") %>
 
 
</td>
 
 
<td align="right">
 
 
<%= (line.Quantity*line.Product.Price).ToString("c") %>
 
 
</td>
 
 
</tr>
 
 
<% } %>
 
 
</tbody>
 
 
<tfoot>
 
 
<tr>
 
 
<td colspan="3" align="right">
 
 
Total:
 
 
</td>
 
 
<td align="right">
 
 
<%= Model.ComputeTotalValue().ToString("c") %>
 
 
</td>
 
 
</tr>
 
 
</tfoot>
 
 
</table>
 
 
<p align="center" class="actionButtons">
 
 
<a href="<%= Html.Encode(ViewData["returnUrl"]) %>">Continue shopping</a>
 
 
</p>
 
 
</asp:Content>

添加样式:

H2 { margin-top: 0.3em }
; font-weight: bold; }
 
 
TFOOT TD { border-top: 1px dotted gray
 
 
.actionButtons A {
 
 
font: .8em Arial; color: White; margin: 0 .5em 0 .5em;
 
 
text-decoration: none; padding: .15em 1.5em .2em 1.5em;
 
 
background-color: #353535; border: 1px solid black;
 
 
}

F5测试运行。

clip_image005[4]


从购物车中移除商品

为Cart/Index.aspx添加 移除 按钮。

<% foreach (var line in Model.Lines)
 
 
{%>
 
 
<tr>
 
 
<td align="center">
 
 
<%= line.Quantity %>
 
 
</td>
 
 
<td align="left">
 
 
<%= line.Product.Name %>
 
 
</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.Hidden("returnUrl", ViewData["returnUrl"]) %>
 
 
<input type="submit" value="Remove" />
 
 
<% } %>
 
 
</td>
 
 
</tr>
 
 
<% } %>

clip_image007[4]

Displaying a Cart Summary in the Title Bar

为CartController添加如下方法:

public ViewResult Summary(Cart cart)

{

return View(cart);

}

为Summary创建View

clip_image008[4]

代码如下:

<% if (Model.Lines.Count > 0)
 
 
{ %>
 
 
<div id="cart">
 
 
<span class="caption"><b>Your cart:</b>
 
 
<%= Model.Lines.Sum(x => x.Quantity) %>
 
 
item(s),
 
 
<%= Model.ComputeTotalValue().ToString("c") %>
 
 
</span>
 
 
<%= Html.ActionLink("Check out", "Index", "Cart",
 
 
new { returnUrl = Request.Url.PathAndQuery }, null)%>
 
 
</div>
 
 
<% } %>
 
 
修改Site.master
 
 
<div id="header">
 
 
<% if (!(ViewContext.Controller is WebUI.Controllers.CartController))
 
 
Html.RenderAction("Summary", "Cart"); %>
 
 
<div class="title">
 
 
体育用品商场</div>
 
 
</div>

添加样式:

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;}
 
 
DIV#cart SPAN.summary { color: White; }

F5 测试运行。

clip_image010[4]

提交结果

创建ShippingDetails领域模型

public class ShippingDetails : IDataErrorInfo
 
 
{
 
 
public string Name { get; set; }
 
 
public string Line1 { get; set; }
 
 
public string Line2 { get; set; }
 
 
public string Line3 { get; set; }
 
 
public string City { get; set; }
 
 
public string State { get; set; }
 
 
public string Zip { get; set; }
 
 
public string Country { get; set; }
 
 
public bool GiftWrap { get; set; }
 
 
public string this[string columnName] // Validation rules
 
 
{
 
 
get
 
 
{
 
 
if ((columnName == "Name") && string.IsNullOrEmpty(Name))
 
 
return "Please enter a name";
 
 
if ((columnName == "Line1") && string.IsNullOrEmpty(Line1))
 
 
return "Please enter the first address line";
 
 
if ((columnName == "City") && string.IsNullOrEmpty(City))
 
 
return "Please enter a city name";
 
 
if ((columnName == "State") && string.IsNullOrEmpty(State))
 
 
return "Please enter a state name";
 
 
if ((columnName == "Country") && string.IsNullOrEmpty(Country))
 
 
return "Please enter a country name";
 
 
return null;
 
 
}
 
 
}
 
 
public string Error { get { return null; } } // Not required
 
 
}

在CartTest中测试Shipping Details类

[Test]
 
 
public void Cart_Shipping_Details_Start_Empty()
 
 
{
 
 
Cart cart = new Cart();
 
 
ShippingDetails d = cart.ShippingDetails;
 
 
Assert.IsNull(d.Name);
 
 
Assert.IsNull(d.Line1); Assert.IsNull(d.Line2); Assert.IsNull(d.Line3);
 
 
Assert.IsNull(d.City); Assert.IsNull(d.State); Assert.IsNull(d.Country);
 
 
Assert.IsNull(d.Zip);
 
 
}
 
 
[Test]
 
 
public void Cart_Not_GiftWrapped_By_Default()
 
 
{
 
 
Cart cart = new Cart();
 
 
Assert.IsFalse(cart.ShippingDetails.GiftWrap);
 
 
}
 
 
编译错误,在实体Cart类中添加如下代码 :
 
 
private ShippingDetails shippingDetails = new ShippingDetails();
 
 
public ShippingDetails ShippingDetails { get { return shippingDetails; } }

添加

Check Out Now 按钮

在Vew/Cart/Index.aspx中添加

<%= Html.ActionLink("Check out now", "CheckOut") %>

查看客户的详细购物资料

在CartController中添加CheckOut Action:

[AcceptVerbs(HttpVerbs.Get)]

public ViewResult CheckOut(Cart cart)

{

return View(cart.ShippingDetails);

}

为CheckOut创建View。

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
 
 
<h2>
 
 
Check out now</h2>
 
 
Please enter your details, and we'll ship your goods right away!
 
 
<% using (Html.BeginForm())
 
 
{ %>
 
 
<h3>
 
 
Ship to</h3>
 
 
<div>
 
 
Name:
 
 
<%= Html.TextBox("Name") %></div>
 
 
<h3>
 
 
Address</h3>
 
 
<div>
 
 
Line 1:
 
 
<%= Html.TextBox("Line1") %></div>
 
 
<div>
 
 
Line 2:
 
 
<%= Html.TextBox("Line2") %></div>
 
 
<div>
 
 
Line 3:
 
 
<%= Html.TextBox("Line3") %></div>
 
 
<div>
 
 
City:
 
 
<%= Html.TextBox("City") %></div>
 
 
<div>
 
 
State:
 
 
<%= Html.TextBox("State") %></div>
 
 
<div>
 
 
Zip:
 
 
<%= Html.TextBox("Zip") %></div>
 
 
<div>
 
 
Country:
 
 
<%= Html.TextBox("Country") %></div>
 
 
<h3>
 
 
Options</h3>
 
 
<%= Html.CheckBox("GiftWrap") %>
 
 
Gift wrap these items
 
 
<p align="center">
 
 
<input type="submit" value="Complete order" /></p>
 
 
<% } %>
 
 
</asp:Content>

F5 运行测试

clip_image012

转载请注明出处! Author: im@xingquan.org

转载于:https://www.cnblogs.com/xingquan/archive/2011/03/24/1994294.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值