zoukankan      html  css  js  c++  java
  • ASP.NET MVC系列:Model

    1. Model任务

      Model负责通过数据库、AD(Active Directory)、Web Service及其他方式获取数据,以及将用户输入的数据保存到数据库、AD、Web Service等中。

      Model只专注于有效地提供数据访问机制、数据格式验证、业务逻辑验证等。

    2. 定义Model Metadata

      Metadata用于定义数据模型的相关属性,如:显示名称、数据长度及数据格式验证等。利用System.ComponentModel.DataAnnotations中的DataAnnotations机制对ASP.NET MVC数据模型进行辅助定义。

      System.ComponentModel.DataAnnotations命名空间的验证属性包括:StringLength、Required、RegularExpression及Range等。

      示例:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    
    using System.ComponentModel;
    using System.ComponentModel.DataAnnotations;
    
    namespace Libing.Portal.Web.Models
    {
        public class Product
        {
            public int ProductID { get; set; }
    
            [DisplayName("产品名称")]
            [Required(ErrorMessage = "产品名称不能为空")]
            [StringLength(100, ErrorMessage = "产品名称最大长度100个字符")]
            public string ProductName { get; set; }
    
            [Required]
            [RegularExpression(@"^d+$", ErrorMessage = "库存数量只能为数字")]
            [Range(0, 100, ErrorMessage = "库存数量0至100之间")]
            public int UnitsInStock { get; set; }
        }
    }

    3. 自定义Metadata验证属性

      定义Metadata验证属性:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    
    using System.ComponentModel.DataAnnotations;
    
    namespace Libing.Portal.Web.Models.Attributes
    {
        /// <summary>
        /// 验证正整数
        /// </summary>
        public class PositiveIntegerAttribute : RegularExpressionAttribute
        {
            public PositiveIntegerAttribute() :
                base(@"^d+$") { }
        }
    }

      使用自定义Metadata验证属性:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    
    using System.ComponentModel;
    using System.ComponentModel.DataAnnotations;
    
    using Libing.Portal.Web.Models.Attributes;
    
    namespace Libing.Portal.Web.Models
    {
        public class Product
        {
            [Required]
            [PositiveInteger(ErrorMessage = "库存数量只能为正整数")]
            [Range(0, 100, ErrorMessage = "库存数量0至100之间")]
            public int UnitsInStock { get; set; }
        }
    }

    4. 模型绑定

      ASP.NET MVC通过模型绑定(Model Binding)机制来解析客户端传送过来的数据,解析的工作由DefaultModelBinder类进行处理。若要自定义ModelBinder类行为,需实现IModelBinder接口。

    4.1 简单模型绑定

      Action的参数在Action被执行时会通过DefaultModelBinder从form或QueryString传送过来的数据进行处理,即将传送过来的字符串型的数据转换成对应的.Net类,并将其输入Action。

    public ActionResult Index(string UserName)
    {
        ViewBag.UserName = UserName;
        return View();
    }

    4.2 复杂模型绑定

      在ASP.NET MVC中,可以通过DefaultModelBinder类将form数据对应到复杂的.NET类,即模型。该模型可能是一个List<T>类或一个含有多个属性的自定义类。

    public ActionResult Index(Product product)
    {
        ViewBag.ProductName = product.ProductName;
        return View();
    }

      从客户端传送过来的form数据会通过DefaultModelBinder类自动创建Product类对象,将form字段通过.NET的Reflection机制一一对应到对象的同名属性中。

    4.3 模型绑定数据验证

      ASP.NET MVC在处理模型绑定时,会处理Model的数据验证。模型绑定的数据验证失败,则Controller的ModelState.IsValid验证值为false。

    [HttpPost]
    public ActionResult Create(Product product)
    {
        if (ModelState.IsValid)
        {
            return RedirectToAction("Details", new { id = product.ProductID });
        }
    
        return View();
    }

      可以使用ModelState.AddModelError()方法在Controller中判断更加复杂的业务逻辑,并自定义错误信息至ModelState。

    [HttpPost]
    public ActionResult Create(Product product)
    {
        if (ModelState.IsValid)
        {
            if (product.UnitsInStock <=10)
            {
                ModelState.AddModelError("UnitsInStock", "UnitsInStock必须大于10");
                return View();
            }
    
            return RedirectToAction("Details", new { id = product.ProductID });
        }
    
        return View();
    }

    4.4 使用Bind属性限制可被更新的Model属性

      复杂模型绑定的验证,在默认情况下,不管Model中有多少字段,只要客户端form有数据传送过来就会自动进行绑定。在ASP.NET MVC中可以通过使用Bind属性限制可被更新的Model属性。

    4.4.1 绑定多个字段中的部分字段

      通过Bind属性来定义Model中需要绑定哪些字段。

      示例:不包括的自动绑定的属性

    [HttpPost]
    public ActionResult Create([Bind(Exclude = "ProductID")] Product product)
    {
        if (ModelState.IsValid)
        {
            if (product.UnitsInStock <= 10)
            {
                ModelState.AddModelError("UnitsInStock", "UnitsInStock必须大于10");
                return View();
            }
    
            return RedirectToAction("Details", new { id = product.ProductID });
        }
    
        return View();
    }

      示例:多个不包括的自动绑定的属性

      多个字段需要排除,使用逗号(,)分隔。

    [HttpPost]
    public ActionResult Create([Bind(Exclude = "ProductID,CreateDate")] Product product)
    {
        if (ModelState.IsValid)
        {
            if (product.UnitsInStock <= 10)
            {
                ModelState.AddModelError("UnitsInStock", "UnitsInStock必须大于10");
                return View();
            }
    
            return RedirectToAction("Details", new { id = product.ProductID });
        }
    
        return View();
    }

      示例:使用Include指定需要绑定的字段

    [HttpPost]
    public ActionResult Create([Bind(Include = "ProductName,UnitsInStock")] Product product)
    {
        if (ModelState.IsValid)
        {
            if (product.UnitsInStock <= 10)
            {
                ModelState.AddModelError("UnitsInStock", "UnitsInStock必须大于10");
                return View();
            }
    
            return RedirectToAction("Details", new { id = product.ProductID });
        }
    
        return View();
    }

      如果不希望在每个Action的参数中都应用Bind属性,可以在Model定义中指定。

      示例:在Model中设置Bind属性

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    
    using System.Web.Mvc;
    
    namespace Libing.Portal.Web.Models
    {
        [Bind(Include = "ProductName,UnitsInStock")]
        public class Product
        {
            public int ProductID { get; set; }
    
            public string ProductName { get; set; }
    
            public int UnitsInStock { get; set; }
    
            public DateTime CreateDate { get; set; }
        }
    }

    4.4.2 UpdateModel()方法与TryUpdateModel()方法

      当绑定引发异常时,使用UpdateModel()方法会直接抛出异常。使用TryUpdateModel()方法,则会在验证成功时返回true,失败或发生异常时返回false。

      示例:UpdateModel()

    [HttpPost]
    public ActionResult Create(Product product)
    {
        UpdateModel(product);
    
        return RedirectToAction("Details", new { id = product.ProductID });
    }

      示例:TryUpdateModel()

    [HttpPost]
    public ActionResult Create(Product product)
    {
        if (TryUpdateModel(product))
        {
            return RedirectToAction("Details", new { id = product.ProductID });
        }
    
        return View();
    }

    5. ViewBag与ViewModel

    5.1 使用ViewBag

      Controller基类提供了ViewBag,可用于将数据项从Controller传递到View中。

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Mvc;
    
    using Libing.Portal.Web.Models;
    
    namespace Libing.Portal.Web.Controllers
    {
        public class ProductController : Controller
        {
            private PortalContext context = new PortalContext();
    
            public ActionResult Edit(int id)
            {
                Product product = context.Products.Find(id);
                ViewBag.Categories = new SelectList(context.Categories, "CategoryID", "CategoryName", product.CategoryID);
    
                return View(product);
            }
    
            protected override void Dispose(bool disposing)
            {
                context.Dispose();
                base.Dispose(disposing);
            }
        }
    }
    @Html.DropDownList("CategoryID", ViewBag.Categories as SelectList)

    5.2 使用ViewModel模式

      ViewModel模式创建强类型的类,对特定View情形优化,并向View模板提供所需要的动态值或内容。Controller将这些ViewModel传递到View模板中显示。

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    
    using System.Web.Mvc;
    
    namespace Libing.Portal.Web.Models.ViewModels
    {
        public class ProductViewModel
        {
            public Product Product { get; set; }
    
            public SelectList Categories { get; set; }
        }
    }
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Mvc;
    
    using Libing.Portal.Web.Models;
    using Libing.Portal.Web.Models.ViewModels;
    
    namespace Libing.Portal.Web.Controllers
    {
        public class ProductController : Controller
        {
            private PortalContext context = new PortalContext();
    
            public ActionResult Edit(int id)
            {
                Product product = context.Products.Find(id);
    
                ProductViewModel productViewModel = new ProductViewModel();
                productViewModel.Product = product;
                productViewModel.Categories = new SelectList(context.Categories, "CategoryID", "CategoryName", product.CategoryID);
    
                return View(productViewModel);
            }
    
            protected override void Dispose(bool disposing)
            {
                context.Dispose();
                base.Dispose(disposing);
            }
        }
    }
    @model Libing.Portal.Web.Models.ViewModels.ProductViewModel
    @Html.DropDownList("CategoryID", Model.Categories)
  • 相关阅读:
    checkbox全选
    table隔行变色与table单元格根据条件更改字体颜色
    document.ready和window.onload
    JS实现定时弹出广告
    CSS overflow属性与display属性
    OpenCV 安装步骤
    C#类的继承多态(虚方法,隐藏方法、抽象类和抽象方法)
    C#中虚方法,抽象方法和隐藏方法
    C#的重载与重写
    C#中可空类型
  • 原文地址:https://www.cnblogs.com/libingql/p/4638111.html
Copyright © 2011-2022 走看看