MVC 模型绑定
在WebForm,获取提交表单的值一般都是Request.Form["Title"]这样的方式。在MVC中,提供了模型绑定机制。让后台获取表单或Url中的参数变得更加简单。
一、基本模型绑定
你可以直接在参数中用字符串,整型变量,实体或者是List<实体>的方式获取表单提交的参数。
参数中的这些东西都是与表单中的Html控件的name属性一一对应的。
public ActionResult PersonAdd(int Id)
{
return View();
}
例如以上代码,它能够匹配Url中的Id参数。如以下两种方法Id都能够匹配到1
http://localhost/Home/PersonAdd/1
http://localhost/Home/PersonAdd?Id=1
在例如如下代码:
public ActionResult PersonAdd(string Name)
{
return View();
}
它能够匹配到表单中提交的张三:
<input type="text" name="Name" value="张三" />
也能够匹配到Get请求的路径参数:
http://localhost/Home/PersonAdd?Name=张三
如果是用实体,则会检查该实体的属性名与表单中name属性中对应的标签的值。
例如有如下实体:
public class Person_Model
{
public int Id { get; set; } public string Name { get; set; }
}
在Controller中的参数填写如下:

[HttpPost]
public ActionResult PersonAdd(Person_Model model)
{
if (ModelState.IsValid) //此处仅作演示,不考虑安全性
{
//插入数据库省略
return Redirect("/Home/PersonManager");
}
return View();
}

这样的话,模型绑定器会自动检查该实体的属性与Name一一对应的标签并绑定。如下表单的值将被绑定到model实体的属性中。
<input type="hidden" name="Id" value="1" />
<input type="text" name="Name" value="张三" />
二、显式模型绑定
UpdateModel与TryUpdateModel都用于显示模型绑定。如果绑定期间出现错误或者模型是无效的。
UpdateModel将抛出一个异常。因此UpdateModel要用try catch语句块包起来,而TryUpdateModel不会抛出异常,而是返回一个布尔类型的值,true表示绑定成功,false表示绑定失败。如:

[HttpPost]
public ActionResult PersonAdd()
{
Person_Model model = new Person_Model();
try
{
UpdateModel(model);
//插入数据库
return Redirect("/Home/PersonManager");
}
catch
{
return View(model);
}
}

TruUpdateModel:

[HttpPost]
public ActionResult PersonAdd()
{
Person_Model model = new Person_Model();
if (TryUpdateModel(model))
{
//插入数据库
return Redirect("/Home/PersonManager");
}
else
{
return View(model);
}
}

另外,模型绑定还有一个模型状态,模型绑定器一斤模型中的每一个值在模型状态中都有相应的一条记录。可以随时查看绑定状态。如:

[HttpPost]
public ActionResult PersonAdd()
{
Person_Model model = new Person_Model();
TryUpdateModel(model);
if (ModelState.IsValid)
{
//if(ModelState.IsValidField("Name"))
//插入数据库
return Redirect("/Home/PersonManager");
}
else
{
return View(model);
}
}

三、安全问题:重复提交
假设有如下实体:

public class Comment
{
public int Id { get; set; }
//评论者姓名
public string Name { get; set; }
//评论内容
public string Content { get; set; }
//是否已审核
public bool Approved { get; set; }
}

在Controller中:

public ActionResult CommentAdd(Comment com)
{
if (ModelState.IsValid)
{
//添加数据库
return Redirect("/Home/CommentManager");
}
else
{
return View(com);
}
}

在以上代码中,如果有恶意用户在表单数据中添加"Approved=true"来干预表单的提交,那么该评论将是默认就通过审核的。这时候我们可以使用Bind特性来防御重复提交攻击。
白名单:
[Bind(Include="Name,Content")] //白名单,只绑定这两个属性
[Bind(Exclude="Id,Approved")] //黑名单,不绑定这两个属性
Bind特性可以应用于参数左侧也可以应用于实体Model类的顶部,应用于实体Modle的顶部则是对所有该实体绑定有效,而应用于参数左侧则只是对该action中的请求有效。
如:

public ActionResult CommentAdd([Bind(Exclude="Approved")]Comment com)
{
if (ModelState.IsValid)
{
//添加数据库
return Redirect("/Home/CommentManager");
}
else
{
return View(com);
}
}

另外,UpdateModel与TryUpdateModel也有一个重载版本来接收一个绑定列表:
UpdateModel(com, "", new string[] { "Id", "Name", "Content" });
最后,还有一种就是视图模型,即另外在定义一个模型来专供视图使用,仅仅包括需要绑定的属性。
另外,如果两个类有相同的Name属性,要同时绑定,区分HTML可以这样写:
<p>客户名称: <input type="text" name="customer.Name" style="width: 300px" /></p>
<p>销售员名称: <input type="text" name="salesman.Name" style="width: 300px" /></p>
三、模型绑定原理
在ASP.NET MVC中,用户请求道服务器的数据将被包装为Model数据对象,这个数据对象通常也被View用来提供显示的数据。在ASP.NET MVC中,提供了非常灵活的Model绑定机制,通过IModelBinder借口,定义了绑定Model数据的约定,并提供了一个接口的默认实现DefaultModelBinder。在大多数情况下,仅仅通过DefaultModelBinder就可以完成Model的绑定。
如果需要的话,也可以自定义一个IModelBinder的实现,完成特定类型的Model绑定。
public interface IModelBinder
{
object BindModel(ControllerContext controllerContext,ModelBindContext bindingContext);
}
1、绑定Model
默认情况下,ASP.NET MVC使用DefaultModelBinder来绑定Model的数据。在传递Action参数的时候,ASP.NET MVC按照如下顺序查找匹配的数据:
- form表单中的数据;
- RouteData中的数据;
- QueryString中的数据;
2、简单参数和复杂参数
如果Action方法的参数类型是值类型和字符串类型,那么DefaultModelBinder将寻找与Action参数名称匹配的参数,如果没有对应的参数,那么Action的参数将试图赋予空引用。因此,对于简单类型的参数来说,参数的类型应该是可空的。
多数情况下,我们会通过一个Model对象来处理复杂的参数,DefaultModelBinder会遍历Model对象的属性来绑定参数。
如果不希望DefaultModelBinder对某个参数进行绑定,可以通过BindAttribute进行说明,其中定义了三个属性:
- Include表示需要绑定的属性,各个属性之间以逗号进行分隔。
- Exclude表示不需要绑定的属性,各个属性之前以逗号分隔。
- Prefix表示请求参数的前缀。
这些标签可以定义在Model上,说明在参数绑定过程中需要绑定的属性或者不需要绑定的属性,如:

[Bind(Include = "Name,Birthday")]
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
public DateTime Birthday{ get; set; }
}

在UpdateModel方法中,指定包含的属性和不包含的属性。
UpdateModel(
person, //Model
"person", //Prefix
new[] { "Id","Name" }, //Include
new [] { "Birthday" } //Exclude
);
MVC 模型绑定的更多相关文章
- ASP.NET MVC模型绑定的6个建议(转载)
ASP.NET MVC模型绑定的6个建议 发表于2011-08-03 10:25| 来源博客园| 31 条评论| 作者冠军 validationasp.netmvc.netasp 摘要:ASP.NET ...
- ASP.NET Core MVC 模型绑定用法及原理
前言 查询了一下关于 MVC 中的模型绑定,大部分都是关于如何使用的,以及模型绑定过程中的一些用法和概念,很少有关于模型绑定的内部机制实现的文章,本文就来讲解一下在 ASP.NET Core MVC ...
- ASP.NET没有魔法——ASP.NET MVC 模型绑定
在My Blog中已经有了文章管理功能,可以发布和修改文章,但是对于文章内容来说,这里缺少最重要的排版功能,如果没有排版的博客很大程度上是无法阅读的,由于文章是通过浏览器查看的,所以文章的排版其实与网 ...
- ASP.NET没有魔法——ASP.NET MVC 模型绑定解析(下篇)
上一篇<ASP.NET没有魔法——ASP.NET MVC 模型绑定解析(上篇)>文章介绍了ASP.NET MVC模型绑定的相关组件和概念,本章将介绍Controller在执行时是如何通过这 ...
- asp.net Mvc 模型绑定项目过多会导致页面运行时间卡
asp.net Mvc 模型绑定项目过多会导致页面运行时间卡的问题. 解决方式就是采用ModelView方式进行精简,已减少模型绑定及验证的时间.
- [转] ASP.NET MVC 模型绑定的功能和问题
摘要:本文将与你深入探究 ASP.NET MVC 模型绑定子系统的核心部分,展示模型绑定框架的每一层并提供扩展模型绑定逻辑以满足应用程序需求的各种方法. 同时,你还会看到一些经常被忽视的模型绑定技术, ...
- .net core mvc 模型绑定 之 json and urlencoded
.net core mvc 模型绑定, FromQuery,对应 url 中的 urlencoded string ("?key1=value1&key2=value2") ...
- ASP.NET MVC——模型绑定
这篇文章我们来讲讲模型绑定(Model Binding),其实在初步了解ASP.NET MVC之后,大家可能都会产生一个疑问,为什么URL片段最后会转换为例如int型或者其他类型的参数呢?这里就不得不 ...
- ASP.NET没有魔法——ASP.NET MVC 模型绑定解析(上篇)
前面文章介绍了ASP.NET MVC中的模型绑定和验证功能,本着ASP.NET MVC没有魔法的精神,本章内容将从代码的角度对ASP.NET MVC如何完成模型的绑定和验证进行分析,已了解其原理. 本 ...
随机推荐
- POJ 2986 A Triangle and a Circle
题意:给定一个三角形,以及一个圆的圆心坐标和半径,求圆和三角形的相交面积. 思路: 用三角剖分,三角形上每个线段都变成这个线段与圆心的三角形,然后算出每个三角形与圆的相交面积,然后根据有向面积的正负累 ...
- 03_Elasticsearch如何安装以及相关插件的介绍
03_Elasticsearch如何安装以及相关插件的介绍 elasticsearch -d (-d参数是为了让服务后台运行) Elasticsearch 目录结构: 文件夹 作用 /bin 运行El ...
- structs2使用小结2
回顾之前做过类似structs2的知识点总结 Structs2历史.处理流程及与1.0版本的区别 Structs2配置文件.拦截器.校验等 EL表达式在JS中使用 ${}El表达式不能直接在单独JS文 ...
- cf486C Palindrome Transformation
C. Palindrome Transformation time limit per test 1 second memory limit per test 256 megabytes input ...
- ECharts JavaScript图表库 ECharts
ECharts开源来自百度商业前端数据可视化团队,基于html5 Canvas,是一个纯Javascript图表库,提供直观,生动,可交互,可个性化定制的数据可视化图表.创新的拖拽重计算.数据视图.值 ...
- Yii2 分页类的扩展和listview引用
Yii2 本身提供了不错分页选项供用户设置,但是实际项目中我们往往需要复杂一些的分页样式,例如下图所示的效果,上下翻页可用和不可用均用图标来替换.
- windows任务栏消失
windows任务栏消失,快捷键打开任务管理器,新建任务explorer.exe
- IOS UIImage 模糊
#import <UIKit/UIKit.h> #import <Accelerate/Accelerate.h> #import <QuartzCore/QuartzC ...
- 使用SqlCacheDependency依赖项让数据库变化后缓存失效
SqlCacheDependency可以使缓存在数据库或者数据库某张表或者字段变化后让指定缓存失效.对于一些需要及时显示的信息比较有用. 需要.net2.0以后设sql server2005及以后版本 ...
- 计算机图形学学习方法和相关书籍,做游戏,GIS,虚拟现实,三维引擎的都能够看看.
本书參照<<图形学扫盲>> 整理的,原文内容引子: http://www.cppblog.com/lai3d/archive/2008/12/30/70796.html 前言: ...