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

posted @ 2011-03-24 20:48  敏捷学院  阅读(926)  评论(0编辑  收藏  举报