zoukankan      html  css  js  c++  java
  • ASP.NET MVC Model之二模型绑定

    Asp.net mvc中的模型绑定,或许大家经常用,但是具体说他是怎么一回事,可能还是会有些陌生,那么,本文就带你理解模型绑定。为了理解模型绑定,本文会先给出其定义,然后对通过比,来得出使用模型绑定的方便。最后简单的模拟一下自定义模型绑定,让大家对模型绑定有进一步的认识。

     一、模型绑定的概念


    mvc framework中有一种技术,他就是模型绑定:
    使用 被浏览器发送的http请求里面数据 来创建.net对象的过程。接下来就让我们来看看模型绑定的好处。

     二、模型绑定好处 

    第二部分,我们通过不使用模型绑定和使用模型绑定的两种效果的对比,得出模型绑定的优势。那么接下来先让我们来模拟一个没有模型绑定的环境。

    2.1没有模型绑定的环境

      让我们先来模拟一个没有模型绑定的环境,主要是让用户填写的信息传达到Controller中,然后经过加工后显示到View上(通常情况下我们是得到model后直接把model作为一个模型实体,提交到数据库了,为了简单起见,我只是把得到的模型信息显示出来)。先利用vs2010新建一个mvc3项目,在models文件夹中新建一个Person类,代码如下:
    
    
    复制代码
    using System.Web.Mvc;
    using System.ComponentModel.DataAnnotations;
        public class Person
        {
            [Display(Name="编号")]
            public String Id { get; set; }
            [Display(Name = "姓:")]
            public string FirstName { get; set; }
            [Display(Name = "名:")]
            public string LastName { get; set; }
      }
    复制代码

    然后在views文件夹里面添加一个Example0视图,视图的代码如下: 
    复制代码
     <form method="post"/>
        <table cellpadding="5" cellspacing="0" width="50%">
            <tr>
                <td align="right" nowrap="nowrap" width="15%">
                    编号 :</td>
                <td>
            <input name="Id" type="text" /></td>
            </tr>
            <tr>
                <td align="right" nowrap="nowrap" width="15%">
                    姓 :</td>
             <td>
            <input name="FirstName" type="text" /></td>
            </tr>
            <tr>
                <td align="right" nowrap="nowrap" width="15%">名 :</td>
                <td><input name="LastName" type="text"/></td>
            </tr>
            <tr>
                <td align="left" colspan="2" nowrap="nowrap" width="15%">
            <input id="Submit1" type="submit" value="提交" /></td>
            </tr>
            <tr>
                <td align="left" colspan="2">
                <strong>
                @ViewBag.StatusMessage
                </strong>
                </td>
            </tr>
        </table>
    复制代码
     然后在Controllers文件夹里面新建一个HomeController,添加如下代码: 
    复制代码
            public ActionResult Example0()
            {
                Person p = new Person();
                if (Request.Form.Count > 0)
                {
                    p.Id = Request.Form["Id"];
                    p.FirstName = Request.Form["FirstName"];
                    p.LastName = Request.Form["LastName"];
                    TryUpdateModel(p);
                    ViewBag.StatusMessage = "欢迎您!" + p.FirstName + p.LastName + "您的编号是" + p.Id + "!";
                }
                return View();
            }
    复制代码
     然后配置路由,使上面的Example0页面为起始项,运行并填入数据,结果为: 

      

    点击提交按钮。显示如下结果:

     从Controller的代码来看,我们主要是使用Request.Form.Count 来判断是否接收到了值,然后再一一的遍历我们想要得到的值,最后也算得到了。下面让我们来看一下使用模型绑定的效果:

     2.2使用模型绑定 

    然后在Views/Home文件夹添加一个Example2.cshtml。代码如下:
    复制代码
     <form method="post">
        <table cellpadding="5" cellspacing="0" width="50%">
            <tr>
                <td align="right" nowrap="nowrap" width="15%">
                    编号 :</td>
                <td>
            <input name="Id" type="text" /></td>
            </tr>
            <tr>
                <td align="right" nowrap="nowrap" width="15%">
                    姓 :</td>
             <td>
            <input name="FirstName" type="text" /></td>
            </tr>
            <tr>
                <td align="right" nowrap="nowrap" width="15%">名 :</td>
                <td><input name="LastName" type="text"/></td>
            </tr>
            <tr>
                <td align="left" colspan="2" nowrap="nowrap" width="15%">
            <input id="Submit1" type="submit" value="提交" /></td>
            </tr>
            <tr>
                <td align="left" colspan="2">
                <strong>
                @ViewBag.StatusMessage
                </strong>
                </td>
            </tr>
        </table>
    复制代码
    最后在HomeController添加两个方法:
    复制代码
            public ActionResult Example2()
            {
                return View();
            }
    
            [HttpPost]
            public ActionResult Example2(Person person)
            {
                ViewBag.StatusMessage = "欢迎您!" + person.FirstName + person.LastName + "您的编号是" + person.Id + "!";
                return View();
            }
    复制代码
    使Example2作为起始项或输入指定的URL,然后在文本框里面输入内容,如下图

     

    在Example2方法中设置断点,以观察person的属性值,然后点击按钮提交:

      

    发现person的各个属性已经获得了url中传过来的值,如下图:

     

    2.3模型绑定的效果

    通过上面的两种方式的实现,都是将URL中的传递的数据包装成了对象,然后把model的信息显示到View上面,明显使用模型绑定会省去很多代码,特别是在有多个属性时,这种效果更加明显,但是要注意的是前台的标签的name要和我们的model的属性的名字要一致,否则无法完成绑定。


    2.4模型绑定的延伸

    在我们给出的模型绑定的概念中,是把URL的请求数据创建成.net对象都算是模型绑定,我们叫上面的函数参数是一个类,叫绑定到类。如果是单纯的把其绑定到基础类型,是不是也符合定义呢?那么就让我们来看看绑定到基础类型。

    2.4.1绑定到基础类型 

    我们先看一个将http请求中的Id绑定到函数的string Id上。在HomeController中新建两个Index方法,其中带参数的加上 [HttpPost]标签,代码如下:
    
    复制代码
            public ActionResult index()
            {
                return View();
            }
            [HttpPost]
            public ActionResult index(int id)
            {
                ViewBag.Info = "编号是" + id;
                return View();
            }
    复制代码
    对应的Index视图的代码:
    <form action="Index" method="post"/>
    学号:<input name="id" id =”id” type="text"/>
    <input id="Submit1" type="submit" value="提交" />
    <strong>@ViewBag.Info</strong>
    当直接点提交按钮后,发现程序报错,如图
    

    从提示类看错误的原因是因为HttpPost的方法接受了一个为空值的Id,所以与int id不能匹配,解决的办法是使用默认值public ActionResult index(int id=0)
    这样用的另外一个好处是,如果是View中的标签的name属性一不小心写错了,如把<input name="id1" id="id1" type="text"/>,那么该方法同样使用默认值,也就是说即使没有找到与之相匹配的key,也可以使用默认值,虽然没有到达预期的效果,但不至于报错。
    提交按钮,会输出:编号是0. 

    2.4.2绑定到类的指定属性 

    在绑定到类时,或许有的时间我们不想绑定id,那么我们就可以在方法的参数前加一个限制: 
    public ActionResult Example2([Bind(Include="FirstName,LastName")]Person person)
    其他代码不变,调试结果:

      

    发现Id属性值为null,Include相对的还有一个Exclude,结果如下:
     


    还有一招更狠的是,假设某个字段为预留字段,在所有的控制器的所有方法都不想被绑定,也防止有些恶意用户为我们预留字段添加数据,那么可以在model中的类前面加上
     [Bind(Exclude="ReservedProperty")]
    public class Person {
    以上的模型绑定都是使用了默认的绑定,除了上面的两种可以绑定到的类型,还可以绑定到各种类型,如字典,泛型,以及复杂类型(上一篇中的Address属性),在此不一一的列举。但是要记住是“属性名”要相一致。看到这里,估计你也很想知道,绑定的原理。那就让我们来看第三部分。 

    三、把自定义的模型使用在指定的参数上 

    如果想学会一件事,最好的方法就是实践一下了,同样,为了弄清模型绑定的原理,我们就自定义一个模型绑定。之前我们提过,上面的模型绑定都是使用的默认绑定,那么我们肯定想知道一下,即使是默认的绑定,那么是怎么显示调用的?因为如果知道了显式的调用方式,那么自定义的就可以按照其调用方法调用了。下面让我们看一下显示使用默认模型绑定:

    3.1显式使用默认模型绑定 

    在看显式使用默认绑定之前,我们先看一下默认绑定DefaultModelBinder,可以按F12,发现其实现了IModelBinder接口。该接口有一个方法:
    复制代码
     // 摘要:
            //     使用指定的控制器上下文和绑定上下文将模型绑定到一个值。
            //
            // 参数:
            //   controllerContext:
            //     控制器上下文。
            //
            //   bindingContext:
            //     绑定上下文。
            //
            // 返回结果:
            //     绑定值。
            object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext);
    复制代码
    该方法的返回值即为绑定值。我们先不管那么多,先看一下显式的调用默认模型绑定看是怎么调用的。其实在每一个参数前多省略了一个[ModelBinder(typeof(DefaultModelBinder))],或者说使用了和他一样的效果。不相信的话,你可以把上面的代码放到参数类型的前面,像这样: 
    public ActionResult Example2([ModelBinder(typeof(DefaultModelBinder))]Person person) 
    运行结果,看看是不是和不使用的效果一样。

     

    知道了显式的使用默认模型绑定,那么我们是不是可以自定义一个模型绑定也来实现一下呢?
    

    3.2 使用自定义绑定 

      和默认模型绑定一样,我们也来实现接口IModelBinder,然后实现其方法BindModel,从参数和返回值的说明来看,ModelBindingContext可能会有些陌生,先放一下,一会单独说明,回想一下模型绑定,就是使用URL请求数据来创建.net对象,想创建说明样的对象肯定是我们说了算,请求的参数来自ControllerContext,创建的对象来自于我们的心中,不过也就是返回值的类型了。
    所以不影响我们自定义模型绑定,我现在想实现一个把接收到的请求数据转化成一个Person类,那么是不是就可以实现一个
    简单的自定义绑定,为了区分默认的绑定类的效果还是自定义的效果,我在Person的Id属性前面加个S,还等什么呢,开始贴代码: 

    public class CustomModelBinder:IModelBinder
    {
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
    Person person = new Person();
    person.Id =”S”+controllerContext.HttpContext.Request["Id"].ToString();
    person.FirstName = controllerContext.HttpContext.Request["FirstName"].ToString();
    person.LastName = controllerContext.HttpContext.Request["LastName"].ToString();
    return person;
    }
    }

    为了使用自定义的类,我们就在views/Home中添加一个Example3然后在HomeController中添加如下代码:

    public ActionResult Example3()
    {
    return View();
    }

    [HttpPost]
    public ActionResult Example3([ModelBinder(typeof(CustomModelBinder))]Person person)//
    {
    ViewBag.StatusMessage = "欢迎您!" + person.FirstName + person.LastName + "您的编号是" + person.Id + "!";
    return View();
    }

    然后把起始页改为Example3.运行,填入如下数据,点击提交按钮。

      

    显示如下结果:

      

    说明刚刚的自定义绑定已经起作用了,或许默认绑定的过程远比我们想想的复杂的多,但是至少通过一个自定义绑定,让我们从思想上有了简单的认识。最后我们来看一下上面提到有点陌生的那个类ModelBindingContext ,在自定义的绑定内部设断点,然后填如上面的数据,提交,来看一下bingContext对象,他的ModelName就是我们想要绑定的参数,所以称为绑定上下文。
    其他的具体实现由于其原理比较复杂,不在此文说明。
    

    四、参考文献 

  • 相关阅读:
    PAT A1094 The Largest Generation (25 分)——树的bfs遍历
    PAT A1055 The World's Richest (25 分)——排序
    PAT A1052 Linked List Sorting (25 分)——链表,排序
    PAT A1076 Forwards on Weibo (30 分)——图的bfs
    辅导员
    辅导员面试
    C程序设计
    Excel VBA 基本概念
    Excel函数
    导入excel表的数据到数据库ssh
  • 原文地址:https://www.cnblogs.com/sjqq/p/7359203.html
Copyright © 2011-2022 走看看