模型绑定
一、 理解模型绑定
1、 模型绑定:把值(来源路由或视图)附加给action方法的参数上面
2、 参数的过程,参数的类型包含值类型和引用类型(模型、对象)
3、 原理:调用action方法时,会查看该方法是否有参数,如果有会去查找对应的方法参数名称相同的绑定器,如果没有自定义该绑定器,会调用默认的绑定器
二、 手工使用模型绑定
1、 绑定简单类型
1)、参数:全部使用string或者类型?id如int?id
三、 处理绑定错误
四、 使用模型绑定接受文件上传
五、 自定义模型绑定系统
六、 综合案例
七、 重点:在MVC中实现购物车
八、 难点:自定义模型绑定系统
结合第四章内容,实现购物车功能
一、在“LinqBLL/ProductBll.cs”编辑查询方法
如图所示
代码示例:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using LinqService; //引用 namespace LinqBLL { public class ProductBll { public List<Product> GetProduct() { using (SportsStoreEntities se = new SportsStoreEntities()) { var products = se.Product; //数据库里面表名称 return products.ToList(); } } //通过分类名获取体育产品列表 public List<Product> GetProductByCateName(string cate,int stIndex,int count) { using(SportsStoreEntities se=new SportsStoreEntities()) { if (string.IsNullOrEmpty(cate)) //查找所有 { var products=se.Product.OrderBy(x=>x.ProductID).Skip(stIndex).Take(count); return products.ToList(); } else //查找对应分类数据 { var books = from a in se.Product where a.Category.Contains(cate) select a; return books.OrderBy(x=>x.ProductID).Skip(stIndex).Take(count).ToList(); } } } //获取所有记录数 public int GetRecordCount(string cate) { using (SportsStoreEntities se = new SportsStoreEntities()) { if (string.IsNullOrEmpty(cate)) //查找所有 { return se.Product.Count(); } else //查找对应分类数据 { var books = from a in se.Product where a.Category.Contains(cate) select a; return books.Count(); } } } //获取分类名称集 public IEnumerable<string> GetCategories() { var se = new SportsStoreEntities(); var s = from a in se.Product select new { a.Category }; //Distinct:去掉重复分类名,OrderBy:升序 return s.Select(x => x.Category).Distinct().OrderBy(x => x); } //删除方法 public bool Delete(int id) { bool b = true; using (var st = new SportsStoreEntities()) { try { var product = st.Product.SingleOrDefault(a => a.ProductID == id); st.Product.Remove(product); st.SaveChanges(); } catch { b = false; } return b; } } //信息详细 public Product GetModel(int id) { using (SportsStoreEntities st = new SportsStoreEntities()) { Product model = st.Product.SingleOrDefault(a => a.ProductID == id); return model; } } //信息查询 public Product GetProductById(int id) { using (var st = new SportsStoreEntities()) { Product pro = st.Product.SingleOrDefault(a => a.ProductID == id); return pro; } } } }
二、在“Models”文件添加一个类名为“Cart.cs”,编辑“添加购物车、删除购物车中的产品、清楚购物车的产品、计算购物车中求和、获取购物车所有的产品”方法
如图所示(上部分):
如图所示(下部分):
代码示例:
using System; using System.Collections.Generic; using System.Linq; using System.Web; using LinqService; using LinqBLL; namespace MvcProduct.Models { public class Cart { //定义列表存储购物车数据 private Dictionary<string, CartLine> dic = new Dictionary<string,CartLine>(); //添加购物车 public void AddCart(string itemId, int quantity) { CartLine cart=null; if (dic.TryGetValue(itemId, out cart)) { cart.Quantity += quantity; } else { Product pro= new ProductBll().GetProductById(Convert.ToInt32(itemId)); cart = new CartLine { Products = pro, Quantity = 1 }; dic.Add(itemId, cart); } } //删除购物车中的产品 public void Remove(string itemId) { dic.Remove(itemId); } //清楚购物车的产品 public void Clear() { dic.Clear(); } //计算购物车中求和 public decimal Total { get { return dic.Values.Sum(e => e.Products.Price * e.Quantity); } } //获取购物车所有的产品 public IEnumerable<CartLine> CartItem { get { return dic.Values; } } } //包含产品的数量 public class CartLine { public Product Products { get; set; } public int Quantity { get; set; } //数量 } }
三、继续在“Models”文件添加一个类名为"CartModelBinder.cs"编辑存储方法”
如图所示:
代码示例
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; namespace MvcProduct.Models { public class CartModelBinder:IModelBinder { private const string sessionKey = "Cart"; public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) { Cart cart = (Cart)controllerContext.HttpContext.Session[sessionKey]; if (cart == null) { cart = new Cart(); controllerContext.HttpContext.Session[sessionKey] = cart; } return cart; } } }
四、完成后,到"Global.asax"路由器里面"Application_Start()"方法"注册购物车"(注意引用命名空间)
1、如图所示(引用命名空间):
2、如图所示(注册):
代码示例
using System; using System.Collections.Generic; using System.Data.Entity; using System.Data.Entity.Infrastructure; using System.Linq; using System.Web; using System.Web.Mvc; using System.Web.Routing; using MvcProduct.Models; namespace MvcProduct { // 注意: 有关启用 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( "cate", // 路由名称 "{controller}/{action}/{cate}", // 带有参数的 URL new { controller = "Home", action = "Index", cate = UrlParameter.Optional }, // 参数默认值 new[] { "MvcProduct.Controllers" } ); routes.MapRoute( "Default", // 路由名称 "{controller}/{action}/{id}", // 带有参数的 URL new { controller = "Home", action = "Index", id = UrlParameter.Optional }, // 参数默认值 new[] { "MvcProduct.Controllers" } ); } protected void Application_Start() { AreaRegistration.RegisterAllAreas(); // 默认情况下对 Entity Framework 使用 LocalDB Database.DefaultConnectionFactory = new SqlConnectionFactory(@"Data Source=(localdb)v11.0; Integrated Security=True; MultipleActiveResultSets=True"); RegisterGlobalFilters(GlobalFilters.Filters); RegisterRoutes(RouteTable.Routes); //注册购物车模型绑定类 ModelBinders.Binders.Add(typeof(Cart), new CartModelBinder()); } } }
五、在”Controllers“文件添加一个控件名为”CartController.cs“并调用添加方法
如图所示:
代码示例:
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using MvcProduct.Models; namespace MvcProduct.Controllers { public class CartController : Controller { // // GET: /Cart/ public ActionResult Index() { return View(); } //添加到购物车 [HttpPost] public ActionResult AddToCart(Cart cart, string Id, string returnUrl) { cart.AddCart(Id, 1); return RedirectToAction("Index", new { returnUrl }); } } }
六、编辑完成后,在”Index“添加视图,选择强类型并编辑前台代码
1、如图所示
2、如图所示(前台代码):
代码示例:
@model IEnumerable<MvcProduct.Models.CartLine> @{ ViewBag.Title = "Index"; } <h2>我的购物车</h2> <table> <tr> <td>图片</td> <th>体育名称</th> <th>价格</th> <th>数量</th> <th>小计</th> <th>删除</th> </tr> @foreach (var item in Model) { <tr> <td><img src="@item.Products.Image" alt="" /></td> <td>@item.Products.Name</td> <td>@item.Products.Price.ToString("F2")</td> <td>@item.Quantity</td> <td>@((item.Products.Price*item.Quantity).ToString("F2"))</td> <td> @Html.ActionLink("删除", "Delete", new { id=item.Products.ProductID }) </td> </tr> } <tfoot> <tr> <td colspan="3" align="right">总计:</td> <td>@ViewBag.Total</td> </tr> </tfoot> </table> <p style="text-align:center" class="actionButtons"> <a href="/Home/List">继续购物</a> @Html.ActionLink("马上结账", "Checkout") </p>
七、完成后,回到“Controllers/CartControllers”编辑删除方法和把编辑对象方法
1、如图所示(对象):
2、如图所示(删除方法):
代码示例:
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using MvcProduct.Models; namespace MvcProduct.Controllers { public class CartController : Controller { // // GET: /Cart/ public ActionResult Index(Cart cart) { //总数格式 ViewBag.Total = cart.Total.ToString("F2"); return View(cart.CartItem); } //添加到购物车 [HttpPost] public ActionResult AddToCart(Cart cart, string Id, string returnUrl) { cart.AddCart(Id, 1); return RedirectToAction("Index", new { returnUrl }); } //删除购物车 public ActionResult Delete(Cart cart, string id) { cart.Remove(id); return RedirectToAction("Index"); } } }
八、到”Views/Home/List.cshtml“修改”购物车“代码
如图所示:
代码示例:
@model MvcProduct.Models.ProducrsListViewModel @{ ViewBag.Title = "List"; } <h2>体育产品</h2> @foreach (var p in Model.Producrs) { <div class="warp clearfix"> <div id="left"> <img alt="@p.Name" src="../../@p.Image" width="135" height="155" border="0" /> </div> <div class="item"> <h3>@p.nDescription</h3><br /> @p.Category <h4>@string.Format("{0:F}",p.Price)</h4><br /> @using (Html.BeginForm("AddToCart","Cart")) { @Html.Hidden("Id",p.ProductID) @Html.Hidden("returnUrl",Request.Url.PathAndQuery) <input type="submit" value="加入购物车" /> } </div> </div> <hr style="border-style:inset"/> } <div class="pager"> @Html.PageLinks(Model.PagingInfo, x => Url.Action("List", new {page=x,cate=Model.CurrentCategory })) </div>
注意:到“Global.asax”注释掉”路由器之前里面RegisterRoutes“方法代码,否则会报错
如图所示:
代码示例:
using System; using System.Collections.Generic; using System.Data.Entity; using System.Data.Entity.Infrastructure; using System.Linq; using System.Web; using System.Web.Mvc; using System.Web.Routing; using MvcProduct.Models; namespace MvcProduct { // 注意: 有关启用 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( // "cate", // 路由名称 // "{controller}/{action}/{cate}", // 带有参数的 URL // new { controller = "Home", action = "Index", cate = UrlParameter.Optional }, // 参数默认值 // new[] { "MvcProduct.Controllers" } //); routes.MapRoute( "Default", // 路由名称 "{controller}/{action}/{id}", // 带有参数的 URL new { controller = "Home", action = "Index", id = UrlParameter.Optional }, // 参数默认值 new[] { "MvcProduct.Controllers" } ); } protected void Application_Start() { AreaRegistration.RegisterAllAreas(); // 默认情况下对 Entity Framework 使用 LocalDB Database.DefaultConnectionFactory = new SqlConnectionFactory(@"Data Source=(localdb)v11.0; Integrated Security=True; MultipleActiveResultSets=True"); RegisterGlobalFilters(GlobalFilters.Filters); RegisterRoutes(RouteTable.Routes); //注册购物车模型绑定类 ModelBinders.Binders.Add(typeof(Cart), new CartModelBinder()); } } }
运行效果: