2012
07/10
1:00
你的位置:首页 > ASP.net课程 > 第八话 Asp.Net MVC 3.0【MVC项目实战の四】

第八话 Asp.Net MVC 3.0【MVC项目实战の四】

发布时间:2012-07-10 01:00:11

原标题:第八话 Asp.Net MVC 3.0【MVC项目实战の四】

跟手第七话搞完的导航必胜客菜单我们继续来完善我们的项目,然后不啰嗦直接搞购物车图片。首先我们需要一个购物车图片的实体。

定义购物车图片实体

我们需要一个购物车图片实体来的高达模型域(Domain),归因于购物车图片是结合我们应用先后未安装的 拓展业务领域。接下我们要创建购物车图片实体领域(Domain),在们的域高达模型(Domian)项目"SportsStore.Domain"的Entities文件下创建我们的购物车图片实体域高达模型。正象图1.

图1.我们的Cart.cs(购物车图片的实体域高达模型)的代码具体正象:

View Code
using System;using System.Collections.Generic;using System.Linq;using System.Text;namespace SportsStore.Domain.Entities{    public class Cart    {        private List<CartLine> lineConllection = new List<CartLine>();        //添加购物车图片        public void AddItem(Product product, int quantity)         {            CartLine line = this.lineConllection                                .Where(h => h.Product.ProductID == product.ProductID)                                .FirstOrDefault();            if (line == null)            {                this.lineConllection.Add(new CartLine { Product = product, Quantity = quantity });            }            else             {                line.Quantity += quantity;            }                   }        //删除        public void RemoveLine(Product product)         {            this.lineConllection.RemoveAll(h => h.Product.ProductID == product.ProductID);        }        //计算        public decimal ComputeTotalValue()         {            return this.lineConllection.Sum(h => h.Product.Price * h.Quantity);        }        //清空购物车图片        public void Clear()         {            this.lineConllection.Clear();        }        public IEnumerable<CartLine> Lines         {            get { return this.lineConllection; }        }        public class CartLine        {            public Product Product { get; set; }            public int Quantity { get; set; }        }    }}

我们的前台页面需要一个"添加到购物车图片"的按钮,为了方便期间,还牢记我们事先在展示货物信息的自考成绩啥时候出来把展示货物信息的那部分有了一个局部视图搞的,所以我们在展示货物信息的页面就来添加这个按钮。

我们的其二局部试图页面就在我们的web项目/Views/Shared/ProductSummary.cshtml页面,修改ProductSummary.cshtml页面正象:

@model SportsStore.Domain.Entities.Product@{    ViewBag.Title = "ProductSummary";}<div ><h3>@Model.Name</h3>@Model.Description@using (Html.BeginForm("AddToCart","Cart")){    @Html.HiddenFor(h=>h.ProductID)    @Html.Hidden("returnUrl",this.Request.Url.PathAndQuery)    <input type="submit" value="+ Add to cart" />}<h4>@Model.Price.ToString("C")</h4></div>

注:上面代码红色加粗的代码就是我们添加进来的按钮,当我们的表单提交时,就会触发Cart温度控制器里的AddToCart Action(方法)来执行。下来我们就要实现购物车图片的温度控制器(Controller)包括,整,删,改。查;下来在我们Web项目的意思的Controllers办公用品文件夹价格下创建我们的CartController(温度控制器)。具体代码正象:

View Code
using System;using System.Collections.Generic;using System.Linq;using System.Web;using System.Web.Mvc;using SportsStore.Domain.Abstract;using SportsStore.Domain.Entities;using SportsStore.WebUI.Models;namespace SportsStore.WebUI.Controllers{    public class CartController : Controller    {        private IProductRepository repository;        public CartController(IProductRepository repo)         {            this.repository = repo;        }        //添加购物车图片        public RedirectToRouteResult AddToCart(int productId, string returnUrl)        {            Product product = this.repository.Products.FirstOrDefault(h => h.ProductID == productId);            if (product != null)            {                this.GetCart().AddItem(product, 1);            }            return this.RedirectToAction("Index", new { returnUrl });        }        //移除货物        public RedirectToRouteResult RemoverFromCart(int productId, string returnUrl)         {            Product product = this.repository.Products.FirstOrDefault(h => h.ProductID == productId);            if (productId != null)            {                this.GetCart().RemoveLine(product);            }            return this.RedirectToAction("Index", new { returnUrl });        }        private Cart GetCart()         {            Cart cart = (Cart)Session["Cart"];            if (cart == null)            {                cart = new Cart();                this.Session["Cart"] = cart;            }            return cart;        }    }}

有一个特性是会话(Session)状态,他允许我们的金十数据关联会话(session)。这一扶志适合我们的Cart类,我们希望每个用户都有自己的购物车图片,而且请求购物车图片的时间要长久,金十数据与会话(session)到期后要删除会话状态(session),这象征我们不需要管理我们或存储我们的购物车图片对象。添加一个会话(Session)状态。我们只关注会话(Session)对象。

然后我们需要炫耀购物车图片的内容,我们在CartController温度控制器里的AddToCart Action(方法)和RemoverFromCart Action(方法)都调用了RedirectToAction()方法。这个就重新定向了我们的URL连接到Index页面,我们需要传递两条跳消息到视图炫耀我们购物车图片的内容:购物车图片对象和URL连接,这也就是我们创建一个简单高达模型的目的意思。在我们的Web项目的意思Models办公用品文件夹价格下创建CartIndexViewModel类。具体代码正象:

using System;using System.Collections.Generic;using System.Linq;using System.Web;using SportsStore.Domain.Entities;namespace SportsStore.WebUI.Models{    public class CartIndexViewModel    {        public Cart Cart { get; set; }        public string ReturnUrl { get; set; }    }}

既然我们的高达模型已经O了,然后我就就可以实现CartControllr的Index,修改CartController具体代码正象:

using System;using System.Collections.Generic;using System.Linq;using System.Web;using System.Web.Mvc;using SportsStore.Domain.Abstract;using SportsStore.Domain.Entities;using SportsStore.WebUI.Models;namespace SportsStore.WebUI.Controllers{    public class CartController : Controller    {        private IProductRepository repository;        public CartController(IProductRepository repo)         {            this.repository = repo;        }        //添加购物车图片        public RedirectToRouteResult AddToCart(int productId, string returnUrl)        {            Product product = this.repository.Products.FirstOrDefault(h => h.ProductID == productId);            if (product != null)            {                this.GetCart().AddItem(product, 1);            }            return this.RedirectToAction("Index", new { returnUrl });        }        //移除货物        public RedirectToRouteResult RemoverFromCart(int productId, string returnUrl)         {            Product product = this.repository.Products.FirstOrDefault(h => h.ProductID == productId);            if (productId != null)            {                this.GetCart().RemoveLine(product);            }            return this.RedirectToAction("Index", new { returnUrl });        }        private Cart GetCart()         {            Cart cart = (Cart)Session["Cart"];            if (cart == null)            {                cart = new Cart();                this.Session["Cart"] = cart;            }            return cart;        }        public ViewResult Index(string returnUrl)        {            return this.View(new CartIndexViewModel            {                Cart = this.GetCart(),                ReturnUrl = returnUrl            });        }    }}

然后就是我们创建炫耀购物车图片内容的视图,右键我们的Index Action(方法)选择添加视图。选择创夏建强类型视图,并且选择CartIndexViewModel高达模型类,具体正象图2.

图2.我们希望购物车图片希望购物车图片中的炫耀物品的风格和其他页面一致,所以们在这里套用了_Layout.cshtml模版,创建行官网Index.cshtml修改正象:

@model SportsStore.WebUI.Models.CartIndexViewModel@{    ViewBag.Title = "Index";}<h2>Your Cart</h2><table width="90%" align="center">    <thead>    <tr>    <th align="center">Qunantity</th>    <th align="left">Item</th>    <th align="right">Price</th>    <th align="right">Subtotal</th>    </tr>    </thead>    <tbody>    @foreach (var line in Model.Cart.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">Total:</td>    <td align="right">@Model.Cart.ComputeTotalValue().ToString("C")</td>    </tr>    </tfoot></table><p align="center" ><a href="#" shopping</a></p>

这个视图看上去和事先相比,可能性就稍稍复杂一点。列举了购物的行和新添加的行的HTML表单,随着每一行的总成本结合购物车图片的总成本。我们现在一定有一个基本的购物车图片了。当我们在货物页面添加货物到购物车图片。我们的购物车图片基本就会算出货物的总价格,正象图3-图4.

图3.

图4.然后我们需要做更多的东西,比如说用户可以删掉购物车图片里不想要的货物。还有购物车图片的结算等等。

使用高达模型绑定:Asp.Net MVC框架使用一种称为高达模型绑定的机制将来自HTTP请求创建为C#对象。这样就能够将它们作为参数传递给Controller(温度控制器)的Action方法。这也是MVC处理Form表单的原理。譬如MVC框架寻找Action(方法)的参数作为目标的定义,使用高达模型绑定从Input元素获取值,并会将这些值转化为Action方法里面参数对应的类型以及相同的参数称。我们喜欢使用会话状态(Session)特征在购物车图片中的温度控制器(controller)来存储和管理我们的购物车图片对象。我们将创建一个自定义的绑定来获取包含在Session里面的Cart对象。MVC框架硅谷高创会建Cart对象并作为参数传递给CartController的Action方法。然后我们将创建一个自定义的高达模型绑定器,在我们web项目的意思里新建一个办公用品文件夹价格(Binders)在该文件里创建一个类文件,叫CartModelBinder,它的代码具体正象:

using System;using System.Collections.Generic;using System.Linq;using System.Web;using System.Web.Mvc;using SportsStore.Domain.Entities;namespace SportsStore.WebUI.Binders{    public class CartModelBinder : IModelBinder    {        private const string sessionKey = "Cart";        public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)        {            //从session中取出购物车图片信息            Cart cart = (Cart)controllerContext.HttpContext.Session[sessionKey];            //如果从session中取出购物车图片为空创建一个购物车图片            if (cart == null)            {                cart = new Cart();                controllerContext.HttpContext.Session[sessionKey] = cart;            }            //返回购物车图片对象            return cart;        }    }}

IModeBinder接口里面定义一个方法:BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext).提供的两个参数使我们创建域高达模型对象成为可能性。ControllerContext providers能够访问Controller类的所有信息,包括了来自避雷器的详细请求信息;ModelBindingContext提供我们要创建高达模型对象的信息和工具来简化我们的操纵。

其实我们只需要关注ControllerContext类,归因于我们需要用他里面的Session这个东东。

我们需要告诉MVC框架,它可以使用我们的CartModelBinder类来创建购物车图片类的实例,所以我们需要修改Global.asax,具体操纵正象:

using System;using System.Collections.Generic;using System.Linq;using System.Web;using System.Web.Mvc;using System.Web.Routing;using SportsStore.WebUI.Infrastructure;using SportsStore.WebUI.Binders;using SportsStore.Domain.Entities;namespace SportsStore.WebUI{    // 注意: 有关启用 IIS6 或 IIS7 经典模式的说明。    // 请访问 http://go.microsoft.com/?LinkId=9394801    public class MvcApplication : System.Web.HttpApplication    {        public static void RegisterGlobalFilters(GlobalFilterCollection filters)        {            filters.Add(new HandleErrorAttribute());        }        public static void RegisterRoutes(RouteCollection routes)        {            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");            routes.MapRoute(               null,               "",        //只匹配空的URL                new { controller = "Product", action = "List", Category = (string)null, page = 1 }             );            routes.MapRoute(null,                "Page{page}",   //匹配像 /Page2,/page123,除了/PageXYZ                 new { controller = "Product", action = "List", category = (string)null },                new { page = @"\d+" });  //约束:页面数值必须是数字            routes.MapRoute(null,                "{category}",   //匹配职位类别                new { controller = "Product", action = "List", page = 1 });            routes.MapRoute(null,                 "{category}/Page{page}",  //配置 职位类别和分页                new { controller = "Product", action = "List" },                new { page = @"\d+" });   //约束:页面数值必须是数字            routes.MapRoute(null, "{controller}/{action}");            //添加一条路由            routes.MapRoute(                null,                "Page{page}",                new { controller = "Product", action = "List" }                );            routes.MapRoute(                "Default", // 路由称                "{controller}/{action}/{id}", // 带有参数的 URL                new { controller = "Product", action = "List", id = UrlParameter.Optional } // 参数默认值            );        }        protected void Application_Start()        {            AreaRegistration.RegisterAllAreas();            RegisterGlobalFilters(GlobalFilters.Filters);            RegisterRoutes(RouteTable.Routes);            //注册路由            ControllerBuilder.Current.SetControllerFactory(new NinjectControllerFactory());            //注册CartModelBinder类            ModelBinders.Binders.Add(typeof(Cart), new CartModelBinder());        }    }}

注:上面红色加粗的那句代码就是注册CartModelBinder类。我们现在可以修改我们的CartController类使用我们的高达模型绑定来代替事先的GetCart()方法,所以我们需要修改CartController正象:

using System;using System.Collections.Generic;using System.Linq;using System.Web;using System.Web.Mvc;using SportsStore.Domain.Abstract;using SportsStore.Domain.Entities;using SportsStore.WebUI.Models;namespace SportsStore.WebUI.Controllers{    public class CartController : Controller    {        private IProductRepository repository;        public CartController(IProductRepository repo)         {            this.repository = repo;        }        //添加购物车图片        public RedirectToRouteResult AddToCart(Cart cart, int productId, string returnUrl)        {            Product product = this.repository.Products.FirstOrDefault(h => h.ProductID == productId);            if (product != null)            {                cart.AddItem(product, 1);            }            return this.RedirectToAction("Index", new { returnUrl });        }        //移除货物        public RedirectToRouteResult RemoveFromCart(Cart cart, int productId, string returnUrl)         {            Product product = this.repository.Products.FirstOrDefault(h => h.ProductID == productId);            if (product != null)            {                cart.RemoveLine(product);            }            return this.RedirectToAction("Index", new { cart = cart, returnUrl = returnUrl });        }        private Cart GetCart()         {            Cart cart = (Cart)Session["Cart"];            if (cart == null)            {                cart = new Cart();                this.Session["Cart"] = cart;            }            return cart;        }        public ViewResult Index(Cart cart, string returnUrl)        {            return this.View(new CartIndexViewModel            {                Cart = cart,                ReturnUrl = returnUrl            });        }    }}

AddToCart方法被调用时,它开始寻找Action方法的参数,它将会在误用的绑定列表里面寻找,试图找到一个能够创建每一个参数类型的实例。我们自定义的绑定会被用来创建Cart对象,并且MVC是通过Session功能来实现的。在我们自定义的绑定和默认绑定之间,mvc能够创建必备参数的集合来调用action方法。正是如此才允许我们重塑Controller以至我们不知道在请求被接收时Cart对象是怎样被始建的。

使用自定义高达模型绑定有一下几个好处:

  1. 我们将创建购物车图片的逻辑从Controller里面分离出来,这样就允许我们可以改变存储Cart对象的方式而不必去更改Controller。
  2. 任何Controller想使用Cart对象,只需要在其Action方法里面声明一个Cart参数即可.
  3. 良好的但愿测试

然后,完善我们的购物车图片。给我们的购物车图片完善2个功能:1.允许用户删除购物货物项 2.在页面顶端增加一个炫耀购物车图片详情(迷你购物车图片)

首先我们允许用户删除购物车图片内自己不想要或者不喜欢的货物,我们要做的就是在购物车图片的每行货物后暴露给用户一个删除按钮,这样就方便用户删除掉自己不喜欢的东西。修改我们web项目的意思Views/Cart/Index.cshtml页面内容正象:

@model SportsStore.WebUI.Models.CartIndexViewModel@{    ViewBag.Title = "Cart Index";}<h2>Your Cart</h2><table width="90%" align="center">    <thead>    <tr>    <th align="center">Qunantity</th>    <th align="left">Item</th>    <th align="right">Price</th>    <th align="right">Subtotal</th>    </tr>    </thead>    <tbody>    @foreach (var line in Model.Cart.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.HiddenFor(h=>h.ReturnUrl)            <input  type="submit" value="Remove" />        }        </td>        </tr>    }    </tbody>    <tfoot>    <tr>    <td colspan="3">Total:</td>    <td align="right">@Model.Cart.ComputeTotalValue().ToString("C")</td>    </tr>    </tfoot></table><p align="center" ><a href="#" shopping</a></p>

搞玩删除按钮,运行一下我们的web应用先后未安装,结果正象图5所示。

图5.可以看出我们的删除购物车图片的货物项也已经是OK了,然后完善我们的第二项功能。在页面顶端增加一个炫耀购物车图片详情(迷你购物车图片)在我们CartController类里添加这个功能的Action(执行方法),具体代码正象:

using System;using System.Collections.Generic;using System.Linq;using System.Web;using System.Web.Mvc;using SportsStore.Domain.Abstract;using SportsStore.Domain.Entities;using SportsStore.WebUI.Models;namespace SportsStore.WebUI.Controllers{    public class CartController : Controller    {        private IProductRepository repository;        public CartController(IProductRepository repo)         {            this.repository = repo;        }        //添加购物车图片        public RedirectToRouteResult AddToCart(Cart cart, int productId, string returnUrl)        {            Product product = this.repository.Products.FirstOrDefault(h => h.ProductID == productId);            if (product != null)            {                cart.AddItem(product, 1);            }            return this.RedirectToAction("Index", new { returnUrl });        }        //移除货物        public RedirectToRouteResult RemoveFromCart(Cart cart, int productId, string returnUrl)         {            Product product = this.repository.Products.FirstOrDefault(h => h.ProductID == productId);            if (product != null)            {                cart.RemoveLine(product);            }            return this.RedirectToAction("Index", new { cart = cart, returnUrl = returnUrl });        }        private Cart GetCart()         {            Cart cart = (Cart)Session["Cart"];            if (cart == null)            {                cart = new Cart();                this.Session["Cart"] = cart;            }            return cart;        }        public ViewResult Index(Cart cart, string returnUrl)        {            return this.View(new CartIndexViewModel            {                Cart = cart,                ReturnUrl = returnUrl            });        }        //简易的购物车图片        public ViewResult Summary(Cart cart)         {            return this.View(cart);        }    }}

上面代码红色加粗的部分就是简易购物车图片的执行方法(Action),这个方法相当简单就是获取当前购物车图片的对象呈现出来渲染页面,我们需要简易的局部视图来搞定他。在Symmary这个Action上右键,选择添加视图,正象图5所示.

图5.这里还是选择的强类型视图。创建行官网Summary局部视图后。修改他的代码正象所示:

@model SportsStore.Domain.Entities.Cart@{    this.Layout = null;}<div id="cart"><span ><b>Your cart:</b>@Model.Lines.Sum(h=>h.Quantity) item(s),@Model.ComputeTotalValue().ToString("c")</span>@Html.ActionLink("Checkout", "Index", "Cart", new { returnUrl = this.Request.Url.PathAndQuery }, null)</div>

搞完这个顶端的形近字简易购物车图片,我们一定定义了返回这个局部视图的方法,而且我们需要在每个页面都呈现它,所以就要在我们的模版(_Layout.cshtml)里给它分派联名地方,具体修改我们的模版正象:

<!DOCTYPE html><html><head>    <title>@ViewBag.Title</title>    <link href="#" rel="stylesheet" type="text/css" />    <script src='/images/loading.gif' data-original="@Url.Content("~/Scripts/jquery-1.5.1.min.js")" type="text/javascript"></script></head><body><div id="header">@{Html.RenderAction("Summary", "Cart");}<div >SPOPTS STORE</div></div><div id="categories">@{Html.RenderAction("Menu", "Nav");}</div>    <div id="content">    @RenderBody()    </div></body></html>

注:上面红色加粗部分就是给我们的简易购物车图片争取到的联名呈现的地方,注意这里Html.RenderAction();后面的分号不能去掉。如记不清写分号会编译出错。那现在运行一下我们的先后看看我们建议的购物车图片有无达到预期的目的意思,运行正象图6所示。

图6.说明我们的也已经实现了顶部的简易购物车图片。购物里的东西需要提交支付才会生成订单,所以然后也就是我们这个简易项目的意思最后一个阶段订单部分了,今天关于购物车图片就大致分享到这里,后续继续完善我们的项目。文章写的急三火四,要是那里有描述不清楚或者写错的地方,还请路过的前辈们朋友多多批评指导,大家共同学习。

原标题:第八话 Asp.Net MVC 3.0【MVC项目实战の四】

基本词:ASP.NET

转载请保留本文网址: http://www.www.d5897.com/a/35248.html
*特别声明:以上内容来自于网络收集,著作权申请流程权属原作者所有,请联系我们: admin#www.d5897.com (#包换@)。
Baidu