Asp.net MVC的Model Binder工作流程以及扩展方法(1)2014-03-19 08:02 by JustRun, 523 阅读, 4 评论, 收藏编辑

在Asp.net MVC中, Model Binder是生命周期中的一个非常重要的部分。搞清楚Model Binder的流程,能够帮助理解Model Binder的背后发生了什么。同时该系列文章会列举MVC中Model Binder的扩展点,以及如何使用这些扩展点。

阅读目录:

一. MVC中的Model Binder的工作流程

二. 继承IModelBinder, 实现CustomeBinder

三. 使用Custom Model Binder的弊端

四. 总结

一, MVC中的Model Binder的工作流程

在MVC中, 当一个请求发送到服务器,先是要经过Route匹配, 找到对应的Controller和Action, 然后才是构建Action中的参数,也就是Model Binder的过程
这个可以从MVC的源码, ControllerActionInvoker中看出来。

在调用方法GetParameterValue获取参数的函数中, 会根据参数的描述信息,也就是ParameterDescriptor来获取对应的IModelBinder, 使用对应的IModelBinder来获取参数的值。在没有特殊为该参数指定ModelBinder的情况下, MVC使用默认的Model绑定类DefaultModelBinder.

所以我们扩展的第一处地方是,为参数绑定指定使用我们自定义的Model Binder, 自定义的Model Binder需要继承IModelBinder.

二, 继承IModelBinder, 实现CustomeBinder

2.1. MVC代码中的Session依赖问题

MVC的代码中,常常能够看到这样的代码:

public ActionResult Index()
{
var user = Session["UserAccuont"] as UserAccount; //从Session中获取当前登录用户的信息
//send email
var email = user.Email;
return new EmptyResult();
}

上面代码,需要从session中取得当前登录用户的信息。从session中取值导致了Index方法和Session耦合,也没办法进行单元测试。这个时候我们可以定义一个CustomeBinder来解决这个问题,解除Index方法对于Session的依赖。

2.2 自定义UserAccountModelBinder

我们定义的UserAccountModelBinder继承IModelBinder,实现了BindModel方法。该方法会从Session中取得UserAccount信息来构建Action方法中所需要的参数。

public class UserAccountModelBinder : IModelBinder
{
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
if (controllerContext.HttpContext.Session["UserAccuont"] != null)
{
return controllerContext.HttpContext.Session["UserAccuont"];
}
return null;
}
}

2.3 注册UserAccountModelBinder

在Global.asax.cs文件的Application_Start中, 注册UserAccountModelBinder。

protected void Application_Start()
{
//注册UserAccountModelBinder, 指定UserAccount类型的参数,将会由UserAccountModelBinder来处理。 ModelBinders.Binders.Add(typeof(UserAccount), new UserAccountModelBinder()); ………. }

2.4 修改Index()方法

现在由于UserAccountModelBinder能够处理从Session中取UserAccount参数,所以我们的Index方法可以改造成这样:

public ActionResult Index(UserAccount user)
{
//var user = Session["UserAccuont"] as UserAccount; //从Session中获取当前登录用户的信息
//send email
var email = user.Email;
return new EmptyResult();
}

和最初代码不同之处是,我们的从session中取得user值的代码,不需要在Index方法中。而是由UserAccountModelBinder自动处理了。

2.5 背后的流程

现在来理一理,custome model binder的工作方法和流程。

request –> route解析 –> ControllerActionInvoker找ModelBinder处理参数 –> 根据参数类型寻找绑定的custome model binder, 也就是这里的UserAccountModelBinder –> UserAccountModelBinder 从Session中为Action的参数赋值。

三, 使用Custom Model Binder的弊端

上面的UserAccountModelBinder 的确解决了我们的Session依赖问题,但是这种以类型注册binder的方式,会带来潜在的风险:

由于所有使用UserAccount为参数的Action方法,都会由UserAccountModelBinder来处理,也就是从session中取值。如果这个时候,我们的UserAccount的Create和Edit页面,提交UserAccount会发生什么? 是的,都会被UserAccountModelBinder处理,无法得到提交表单的值。

所以要慎用Custom Model Binder, 比较适合的例子是使用Custom Model Binder来绑定的参数,它的数据源只会来源于一处。上面的UserAccount在应用中,数据源就可能来自两处,Session和表单提交,所以是不适合Custom Model binder. 一个变通的办法是,再定义个类型SessionUserAccount.

四, 总结

使用Custom Model Binder能帮助我们解决一部分绑定问题,但是弊端是以类型绑定会导致应用的范围太广,带来意料不到的问题。

下一篇中,我们将使用CustomModelBinderAttribute来解决同样的问题,如果Custom Model Binder是全火力覆盖,那么CustomModelBinderAttribute就是定点清除。

 

Asp.net MVC的Model Binder工作流程以及扩展方法(1)的更多相关文章

  1. Asp.net MVC的Model Binder工作流程以及扩展方法(2) - Binder Attribute

    上篇文章中分析了Custom Binder的弊端: 由于Custom Binder是和具体的类型相关,比如指定类型A由我们的Custom Binder解析,那么导致系统运行中的所有Action的访问参 ...

  2. Asp.net MVC的Model Binder工作流程以及扩展方法(1) - Custom Model Binder

    在Asp.net MVC中, Model Binder是生命周期中的一个非常重要的部分.搞清楚Model Binder的流程,能够帮助理解Model Binder的背后发生了什么.同时该系列文章会列举 ...

  3. Asp.net MVC的Model Binder工作流程以及扩展方法(3) - DefaultModelBinder

    Default Binder是MVC中的清道夫,把守着Model Binder中的最后一道防线.如果我们没有使用Custom Model Binder等特殊处理,那么Model的绑定都是有Defaul ...

  4. 【ASP.NET MVC 学习笔记】- 14 HtmlHlper的扩展方法

    本文参考:http://www.cnblogs.com/willick/p/3428413.html 1.在 MVC 中用于生成 Html 元素的辅助类是 System.Web.Mvc 命名空间下的  ...

  5. ASP.NET MVC2之Model Binder

    Model Binder在Asp.net MVC中非常简单.简单的说就是你控制器中的Action方法需要参数数据:而这些参数数据包含在HTTP请求中,包括表单上的Value和URL中的参 数等.而Mo ...

  6. 简述C#中IO的应用 RabbitMQ安装笔记 一次线上问题引发的对于C#中相等判断的思考 ef和mysql使用(一) ASP.NET/MVC/Core的HTTP请求流程

    简述C#中IO的应用   在.NET Framework 中. System.IO 命名空间主要包含基于文件(和基于内存)的输入输出(I/O)服务的相关基础类库.和其他命名空间一样. System.I ...

  7. ASP.NET MVC 之Model的呈现

    ASP.NET MVC 之Model的呈现(仅此一文系列三) 本文目的 我们来看一个小例子,在一个ASP.NET MVC项目中创建一个控制器Home,只有一个Index: public class H ...

  8. ASP.NET MVC学前篇之请求流程

    ASP.NET MVC学前篇之请求流程 请求流程描述 对于请求的流程,文章的重点是讲HttpApplication和HttpModule之间的关系,以及一个简单的示例实现.(HttpModule又是M ...

  9. [转]ASP.NET MVC 2: Model Validation

    本文转自:http://weblogs.asp.net/scottgu/archive/2010/01/15/asp-net-mvc-2-model-validation.aspx?CommentPo ...

随机推荐

  1. 十天学Linux内核之第九天---向内核添加代码

    原文:十天学Linux内核之第九天---向内核添加代码 睡了个好觉,很晚才起,好久没有这么舒服过了,今天的任务不重,所以压力不大,呵呵,现在的天气真的好冷,不过实验室有空调,我还是喜欢待在这里,有一种 ...

  2. 关于JavaScript中的事件代理

    今天面试某家公司Web前端开发岗位,前面的问题回答的都还算凑活,并且又问了一下昨天面试时做的一道数组去重问题的解题思路(关于数组去重问题,可以观赏我前几天写的:http://www.cnblogs.c ...

  3. C#精华(文章3版本)笔记

    C#精华(文章3版本) 跳转至: 导航. 搜索 文件夹 1 C#概述 2 数据类型 3 运算符和控制流 4 方法和參数 5 类 6 继承 7 接口 8 值类型(struct) 9 合式类型 10 异常 ...

  4. HDU-4862-Jump

    比今年第二个问题,第一个田间学校更多.在游戏中可以做不做,卡在K一旦有.阅读解决一个问题后,才做.内置图所示k这的确是很聪明倍. 代码: #include<cstdio> #include ...

  5. bash shell:重定向标准错误输出

    如何重定向标准错误输出到标准输出?如何把标准错误输出输出到一个文件? Bash提供了I/O重定向工具,有3个缺省的文件(标准输出流): stdin - 用来获取输入,比如键盘.文件重定向 stdout ...

  6. Linux_下安装MySQL

    linux下mysql 最新版安装图解教程 1.查看当前安装的linux版本 命令:lsb_release -a 如下图所示 通过上图中的数据可以看出安装的版本为RedHat5.4,所以我们需要下载R ...

  7. AJAX及其跨域的主要解决方法

    AJAX = Asynchronous JavaScript andXML(异步的 JavaScript 和 XML).通过在后台与服务器进行少量数据交换,使网页实现异步更新.要明白异步交互可以通过同 ...

  8. OpenVPN多处理之-最新架构

    好久没有更新这个系列了,由于我之前也说过,前段时间实在太忙了,并且早在一个月前就预示着本月将更加忙!事实也确实如此!最终在国庆前夕完毕了既定的计划,心里也最终能够长出一口气了.近期在忙什么呢?事实上就 ...

  9. 【设计模式】Abstract Factory模式

    抽象工厂模式是工厂方法模式的进一步强化.当工厂函数仅仅须要产生一种类型的产品(全部产品都继承自同一抽象基类)时,使用工厂方法模式就可以. 可是.当用户程序须要创建多种类型的产品,而这些产品又有一定的内 ...

  10. vs2012连接sql2008(错误类型:Could not load file or assembly)

    发生错误: Sql Server2008数据库中有一个数据库. 我想ORM-Entity FrameWork技术,在自己主动了一个项目,建立一个实体类! 解决的方法: 出现上面的情况.是由于缺少了这两 ...