zoukankan      html  css  js  c++  java
  • asp.net mvc 中的模型绑定

    在asp.net MVC 应用程序, 表单提交的数据通过模型绑定将数据从View传递到控制器中。使用模型绑定显然比Request.Form["Price"] ,Decimal.Parse(Request.Form["Price"] )还需要手动类型转换要要方便很多。

    模型绑定有两种,隐式绑定和显式绑定。

    模型状态Modelstate是模型绑定的副产品,两者都可以调用ModelState.IsValid()方法 来验证模型绑定是否成功,或者添加自定义的ModelState.AddModelError("property","ErrorMessage") 模型绑定错误信息。只要有错误,就不执行更改数据库操作。

    隐式绑定和显式绑定的主要区别是:1、隐式绑定使用的是一个绑定的参数对象去填充数据库。而显式绑定 改变数据库中某个字段。2、隐式绑定需要设置 要改变实体的状态,显式绑定在TryUpdateModel后自动将该实体设置为Modified。3、执行绑定后,隐式绑定原数据库的实体的值相当于丢失,需要参数对象来重新指定,而隐式绑定 就是在该实体上执行更改。

    1、隐式模型绑定。先将表单值转化为CLR 类型,然后以表单字段name名称,value值参数传递到Action中。为了防止过度提交,使用Bind(Include)属性接受白名单,Bind(Exclude="")属性拒绝黑名单。

    // POST: Movie/Create
    // 为了防止“过多发布”攻击,请启用要绑定到的特定属性,有关
    // 详细信息,请参阅 http://go.microsoft.com/fwlink/?LinkId=317598。
    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Create([Bind(Include = "ID,Title,ReleaseDate,Genre,Price")] Movie movie)
    {
    if (ModelState.IsValid)
    {
    db.Movies.Add(movie);  //将实体的跟踪状态设置为 EntityState.Added;如果是在编辑操作中, 需要手动设置 EntityState.Modified;
    db.SaveChanges();
    return RedirectToAction("Index");
    }

    return View(movie);
    }

    2、显式绑定  使用TryUpdateModel 和UpdateModel 显式绑定,它自动将数据库上下文对象的跟踪的实体状态设置为EnrityState.Modified。还可以通过设定参数来指定绑定的字段,两者的区别 是如果 绑定失败,前者不会抛出一个异常,后者会引发异常。

    [HttpPost]
    [ActionName("Edit")]
    [ValidateAntiForgeryToken]
    public ActionResult EditPost(int? id)
    {
    if (id == null)
    {
    return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
    }

    var studentToUpdate = db.Students.Find(id);
    if (TryUpdateModel(studentToUpdate, "", new string[] { "LastName", "FirstMidName", "EnrollmentDate" }))
    {
    try
    {
    //已不需要下面的语句,来设置数据库上下文跟踪实体的状态了,已自动设置跟踪状态的EntityState.Modified标记。
    // db.Entry(studentToUpdate).State = EntityState.Modified;
    db.SaveChanges();
    return RedirectToAction("Index");
    }
    catch(DataException /* dex*/)
    {
    //Log the error (uncomment dex variable name and add a line here to write a log.
    ModelState.AddModelError("", "不能保存更改,重试一次,如果问题仍然存在,请与系统管理员联系");
    }
    }

    return View(studentToUpdate);

    }

     三、两者的区别的实际的例子:

    TryUpdateModel或者UpdateModel 与[Bind(Include ="","") model] 的差别的是 Bind白名单 使用 模型绑定的参数model去替换数据库中的白名单字段,使用的是一个新建的参数model对象,如果白名单里面没有某个属性,就为空。因此,如果有构造方法中指定了创建时间,他会使用参数model中的默认创建的值去更新。

     而TryUpdateModel(model,new string [] {"properties"})) 先在数据库中找到这个模型,然后,实体状态自动设置为 modified,只更新这个模型的指定属性。如果不包括某些属性的话,就不会更新。因此,如果有构造方法中指定了创建时间,他也不会去更新。

    如果 一个模型在构造方法中指明了一个属性的默认值 ,但在模型绑定中未指明是绑定的字段,视图中也无输入字段.

    1、如果使用隐式绑定[Bind() model]则会在数据库中自动生成 构造方法中初始化的值,且在更改数据库的一瞬间自动生成默认值,特别是时间。

    2、如果使用显式绑定TryUpdateModel()或UpdateModel(),不会更改在构造方法中指定的初始化值。

    如:

    模型:

    public class ReviewIndexItem
    {
    public ReviewIndexItem()
    {
    ReviewIndexItemID = Guid.NewGuid().ToString();
    ReviewIndexUseItems = new List<ReviewIndexUseItem>();
    ReviewIndexItemCreateTime = DateTime.Now;
    IsUsed = false;public string ReviewIndexItemID { get; set; }

    [Display(Name = "修改时间")]
    public DateTime ReviewIndexItemCreateTime { get; set; }

    [Display(Name="是否使用")]
    public bool IsUsed { get; set; }

    }

    控制器:

    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Create([Bind(Include = "ReviewIndexItemID,ReviewIndexItemNumber,ReviewIndexItemName,ReviewIndexItemDescription,ReviewIndexItemHighestScore,ReviewIndexItemLowestScore")] ReviewIndexItem reviewIndexItem)
    {
    if (ModelState.IsValid)   //如果编码重复,请在视图中返回错误信息。
    {
    ValidateReviewIndexItemNumberDumplicate(reviewIndexItem);

    }
    if (ModelState.IsValid)
    {

    db.ReviewIndexItems.Add(reviewIndexItem);
    db.SaveChanges();
    return RedirectToAction("Index");
    }

    return View(reviewIndexItem);
    }

    private void ValidateReviewIndexItemNumberDumplicate(ReviewIndexItem reviewIndexItem)
    {
    if (reviewIndexItem.ReviewIndexItemNumber != null)
    {
    var dumplicateNumberIndexItem = db.ReviewIndexItems.Where(indexItem => indexItem.ReviewIndexItemNumber == reviewIndexItem.ReviewIndexItemNumber).AsNoTracking().FirstOrDefault();
    if (dumplicateNumberIndexItem != null && dumplicateNumberIndexItem.ReviewIndexItemID != reviewIndexItem.ReviewIndexItemID)
    {
    ModelState.AddModelError("ReviewIndexItemNumber", "评审指标编码重复,请重新编码");

    }
    }
    }

  • 相关阅读:
    async/await
    js继承
    js处理上下文代码的2个阶段
    js相关地址
    vue自定义指令钩子函数
    vue 组件
    vue methods和computed,v-show和v-if
    vue 生命周期
    DOM操作——怎样添加、移除、移动、复制、创建和查找节点
    js 传递参数
  • 原文地址:https://www.cnblogs.com/liuyuanhao/p/4942223.html
Copyright © 2011-2022 走看看