本文转载自haiziguo

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="" cellspacing="" 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="" nowrap="nowrap" width="15%">
<input id="Submit1" type="submit" value="提交" /></td>
</tr>
<tr>
<td align="left" colspan="">
<strong>
@ViewBag.StatusMessage
</strong>
</td>
</tr>
</table>
 然后在Controllers文件夹里面新建一个HomeController,添加如下代码: 
public ActionResult Example0()
{
Person p = new Person();
if (Request.Form.Count > )
{
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="" cellspacing="" 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="" nowrap="nowrap" width="15%">
<input id="Submit1" type="submit" value="提交" /></td>
</tr>
<tr>
<td align="left" colspan="">
<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就是我们想要绑定的参数,所以称为绑定上下文。
其他的具体实现由于其原理比较复杂,不在此文说明。

四、参考文献

1.http://dotnetslackers.com/articles/aspnet/Understanding-ASP-NET-MVC-Model-Binding.aspx
2.《pro asp.net mvc3 framework》

五、总结

  本文从开始列出了模型绑定的定义,然后通过对比了使用模型绑定的两种效果,并从两种比较简单的模型绑定对象说明了默认绑定用法,让大家对模型绑定有了一个简单的认识,最后实现了自定义绑定。由于本人菜鸟一枚,E文也比较差劲,如果有不对的地方,请大牛们指正!谢谢阅读!

《ASP.NET MVC4 WEB编程》学习笔记------Model模型绑定的更多相关文章

  1. Asp.net MVC4高级编程学习笔记-视图学习第一课20171009

    首先解释下:本文只是对Asp.net MVC4高级编程这本书学习记录的学习笔记,书本内容感觉挺简单的,但学习容易忘记,因此在边看的同时边作下了笔记,可能其它朋友看的话没有情境和逻辑顺序还请谅解! 一. ...

  2. Asp.net MVC4高级编程学习笔记-模型学习第四课基架与模型绑定20171027

    MVC模型 一.构建基架. MVC中的基架可以为应用程序提供CURD各种功能生成所需要的样板代码.在添加控制器的时候可以选择相应的模板以及实体对象来生成相应的模板代码. 首先定义一个模型类如下所示: ...

  3. Asp.net MVC4高级编程学习笔记-视图学习第三课Razor页面布局20171010

    Razor页面布局 1)  在布局模板页中使用@RenderBody标记来渲染主要内容.比如很多web页面说头部和尾部相同,中间内容部分使用@RenderBody来显示不同的页面内容. 2)  在布局 ...

  4. Asp.net MVC4高级编程学习笔记-模型学习第五课MVC表单和HTML辅助方法20171101

    MVC表单和HTML辅助方法 一.表单的使用. 表单中的action与method特性.Action表示表单要提交往那里,因此这里就有一个URL.这个URL可以是相对或绝对地址.表单默认的method ...

  5. ASP.NET MVC Web API 学习笔记---第一个Web API程序

    http://www.cnblogs.com/qingyuan/archive/2012/10/12/2720824.html GetListAll /api/Contact GetListBySex ...

  6. ASP.NET Core Web开发学习笔记-1介绍篇

    ASP.NET Core Web开发学习笔记-1介绍篇 给大家说声报歉,从2012年个人情感破裂的那一天,本人的51CTO,CnBlogs,Csdn,QQ,Weboo就再也没有更新过.踏实的生活(曾辞 ...

  7. 《ASP.NET MVC4 WEB编程》学习笔记------Web API

    本文截取自情缘 1. Web API简单说明 近来很多大型的平台都公开了Web API.比如百度地图 Web API,做过地图相关的人都熟悉.公开服务这种方式可以使它易于与各种各样的设备和客户端平台集 ...

  8. 【转载】ASP.NET MVC Web API 学习笔记---第一个Web API程序

    1. Web API简单说明 近来很多大型的平台都公开了Web API.比如百度地图 Web API,做过地图相关的人都熟悉.公开服务这种方式可以使它易于与各种各样的设备和客户端平台集成功能,以及通过 ...

  9. ASP.NET MVC Web API 学习笔记---Web API概述及程序示例

    1. Web API简单说明 近来很多大型的平台都公开了Web API.比如百度地图 Web API,做过地图相关的人都熟悉.公开服务这种方式可以使它易于与各种各样的设备和客户端平台集成功能,以及通过 ...

随机推荐

  1. nginx 的源码安装

    安装nginx之前要做的准备工作有:安装如下库 (1)gzip模块需要 zlib 库 (2)rewrite模块需要 pcre 库 (3)ssl 功能需要openssl库 还有一种简单的方法就是 yum ...

  2. Log4Net使用详解

    1.Log4Net环境的搭建与基本配置 (1)Log4Net框架介绍     Log4net 是 Apache 下一个开放源码的项目,它是Log4j 的一个克隆版.我们可以控制日志信息的输出目的地.L ...

  3. Java编程思想学习(五) 复用类

    1.继承与组合 复用类的方法有两种:继承与组合.继承就不多说了,组合就是直接在类中new一个对象. 数组也是对象,使用数组也是组合的一种. 2.初始化基类 当创建一个导出类的对象时,该对象包含一个基类 ...

  4. POJ-1273 Drainage Ditches 最大流Dinic

    Drainage Ditches Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 65146 Accepted: 25112 De ...

  5. 总结css之内联图片的优缺点

    会不会有这样一种感觉?IT技术开发知识面很广也很深,总会有你不懂得问题出现.一个接着一个新的问题,一个接着一个新的挑战. 今天,解读[内联图片],什么是内联图片,使用内联图片的优缺点是什么?这个问题是 ...

  6. 静态内部类和Lazy<T>优雅实现单例

    public class Singleton { private Singleton() { } public static Singleton GetInstance() { return Conc ...

  7. centos 配置固定ip

    centos下网络配置方法(网关.dns.ip地址配置) 来源:互联网 作者:佚名 时间:07-13 00:32:07 [大 中 小] 本文介绍了centos网络配置的方法,centos网络配置主要包 ...

  8. JS参考书籍

    参考书籍 初级读物:<JavaScript高级程序设计>:一本非常完整的经典入门书籍,被誉为JavaScript圣经之一,详解的非常详细,最新版第三版已经发布了,建议购买. 中级读物:&l ...

  9. Unity Shader Billboard

    记录来源于ShaderLab开发实战详解 Shader "Tut/Project/Billboard_1" { Properties { _MainTex ("Base ...

  10. web.xml文件中的web-app元素 部署

    [转载]web.xml文件中的web-app元素 (2012-05-24 13:35:57) 转载▼ 标签: 转载 分类: java 挺全 的 呵呵呵 转了 原文地址:web.xml文件中的web-a ...