这篇博客是借助一个自己写的工程来理解model binder的过程.


MVC通过路由系统,根据url找到对应的Action,然后再执行action,在执行action的时候,根据action的参数和数据来源比对,生成各个参数的值,这就是model binder.

IActionInvoker


MVC中这个核心处理逻辑都在ControllerActionInvoker里,用reflector看,能看能到这个类继承了IActionInvoker接口

     public interface IActionInvoker
{
bool InvokeAction(ControllerContext controllerContext, string actionName);
}

所以咱们可以根据代码模拟写出自己的CustomActionInvoker

以下是我自己写的ActionInvoker类

     public class CustomActionInvoker : IActionInvoker
{ public bool InvokeAction(ControllerContext controllerContext, string actionName)
{
bool flag = false;
try
{
//get controller type
Type controllerType = controllerContext.Controller.GetType();
//get controller descriptor
ControllerDescriptor controllerDescriptor =
new ReflectedControllerDescriptor(controllerType);
//get action descriptor
ActionDescriptor actionDescriptor =
controllerDescriptor.FindAction(controllerContext, actionName);
Dictionary<string, object> parameters = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
//get parameter-value entity
foreach (ParameterDescriptor parameterDescriptor in actionDescriptor.GetParameters())
{
Type parameterType = parameterDescriptor.ParameterType;
//get model binder
IModelBinder modelBinder = new CustomModelBinder();
IValueProvider valueProvider = controllerContext.Controller.ValueProvider;
string str = parameterDescriptor.BindingInfo.Prefix ?? parameterDescriptor.ParameterName;
ModelBindingContext bindingContext = new ModelBindingContext();
bindingContext.FallbackToEmptyPrefix = parameterDescriptor.BindingInfo.Prefix == null;
bindingContext.ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(null, parameterType);
bindingContext.ModelName = str;
bindingContext.ModelState = controllerContext.Controller.ViewData.ModelState;
bindingContext.ValueProvider = valueProvider;
parameters.Add(parameterDescriptor.ParameterName,
modelBinder.BindModel(controllerContext, bindingContext));
}
ActionResult result = (ActionResult)actionDescriptor.Execute(controllerContext, parameters);
result.ExecuteResult(controllerContext);
flag = true;
}
catch (Exception ex)
{
//log
}
return flag;
}
}

以下详细解释下执行过程

*Descriptor


执行过程中涉及到三个Descriptor,ControllerDescriptor,ActionDescriptor,ParameterDescriptor

ControllerDescriptor主要作用是根据action name获取到ActionDescriptor,代码中使用的是MVC自带的ReflectedControllerDescriptor,从名字就可以看出来,主要是靠反射获取到action.

ActionDescriptor,主要作用是获取parameterDescriptor,然后execute action.

parameterDescriptor,描述的是action的参数信息,包括name、type等

ModelBinder


最核心的方法. 将传递的数据和参数一一对应,笔者是自己写的CustomModelBinder,MVC默认用的是DefaultModelBinder 都实现了接口IModelBinder

     public interface IModelBinder
{
object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext);
}

其中CustomModelBinder的代码如下

     public class CustomModelBinder : IModelBinder
{ public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
return this.GetModel(controllerContext, bindingContext.ModelType, bindingContext.ValueProvider, bindingContext.ModelName);
} public object GetModel(ControllerContext controllerContext, Type modelType, IValueProvider valueProvider, string key)
{
if (!valueProvider.ContainsPrefix(key))
{
return null;
}
return valueProvider.GetValue(key).ConvertTo(modelType);
}
}

注:我只是实现了简单的基本类型

中间有最核心的方法

valueProvider.GetValue(key).ConvertTo(modelType)

ValueProvider


MVC默认提供了几种ValueProvider,每种都有对应的ValueProviderFactory,每种ValueProvider都对应着自己的数据源

     ValueProviderFactoryCollection factorys = new ValueProviderFactoryCollection();
factorys.Add(new ChildActionValueProviderFactory());
factorys.Add(new FormValueProviderFactory());
factorys.Add(new JsonValueProviderFactory());
factorys.Add(new RouteDataValueProviderFactory());
factorys.Add(new QueryStringValueProviderFactory());
factorys.Add(new HttpFileCollectionValueProviderFactory());

注册ActionInvoker


上述过程讲完之后,还缺一个怎么应用上自己写的ActionInvoker,在Controller里提供了虚方法CreateActionInvoker

         protected override IActionInvoker CreateActionInvoker()
{
return new CustomActionInvoker();
}

到此,整个过程已讲完。

MVC Model Binder的更多相关文章

  1. MVC Model Binder 规则

    http://www.cnblogs.com/mszhangxuefei/archive/2012/05/15/mvcnotes_30.html 使用默认的Model Binder(Using the ...

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

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

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

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

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

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

  5. ASP.NET MVC中默认Model Binder绑定Action参数为List、Dictionary等集合的实例

    在实际的ASP.NET mvc项目开发中,有时会遇到一个参数是一个List.Dictionary等集合类型的情况,默认的情况ASP.NET MVC框架是怎么为我们绑定ASP.NET MVC的Actio ...

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

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

  7. ASP.NET MVC Model绑定(二)

    ASP.NET MVC Model绑定(二) 前言 上篇对于Model绑定的简单演示想必大家对Model绑定的使用方式有一点的了解,那大家有没有想过Model绑定器是在什么时候执行的?又或是执行的过程 ...

  8. ModelBinder——ASP.NET MVC Model绑定的核心

    ModelBinder——ASP.NET MVC Model绑定的核心 Model的绑定体现在从当前请求提取相应的数据绑定到目标Action方法的参数.通过前面的介绍我们知道Action方法的参数通过 ...

  9. ASP.NET MVC2之Model Binder

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

随机推荐

  1. 创建类模式(二):抽象工厂(Abstract Factory)

    定义 为创建一组相关或相互依赖的对象提供一个接口,而且无需指定他们的具体类. 抽象工厂模式是所有形态的工厂模式中最为抽象和最具一般性的一种形态.抽象工厂模式是指当有多个抽象角色时,使用的一种工厂模式. ...

  2. disque概要

    做项目过程接触到disque,记录一下. disque是redis之父开源的基于内存的分布式作业队列,用c语言实现的非阻塞网络服务器. disque的设计目标:Its goal is to captu ...

  3. OOP设计模式[JAVA]——03职责链模式

    职责链模式 Responsibility of Chain 在职责链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链.请求在这个链上传递,直到链上的某一个对象决定处理此请求.发出这个请求 ...

  4. 记录一下在WinXP上搭建Apache的httpd+PHP+MySQL+Wordpress的过程

    实验室有台旧电脑,想用它一台服务器. 不知为何,U盘启动盘死活不能启动,所以放弃了安装Linux的念头,直接在原来的XP上弄一个服务器,毕竟用的人也不多,也就局域网的这几个人, 本来主要是搭建一个FT ...

  5. phpcms v9和discuz X3.1实现同步登陆退出论坛(已实现)

    网络上文章很多,按步骤配置好了之后phpcms可以同步登录dz,但是dz登录后状态却无法同步到phpcms,网络上找了很多资料都大同小异,头大.只能自己调试了,废话不多说了.       以下网络上抄 ...

  6. delphi 为应用程序添加提示

    type  TForm1 = class(TForm)    Button1: TButton;    Panel1: TPanel;    Edit1: TEdit;    procedure Fo ...

  7. 用VS2010开发Android应用的配置方法

    在开发你的第一个Android应用程序之前,你应该先检查一下是否安装了Android SDK,以及是否创建好了Android模拟器(AVD),如果有不清楚的地方,请先看百度这篇文章“Android是什 ...

  8. MySQL Cluster基础知识简介以及基本参数介绍

    PS:这些资料都是以前整理的,有些有可能是在网上copy别人的,但是时间长了,记不得出处了,sorry! 在MySQL Cluster环境的配置文件config.ini里面,每一类节点都有两个(或以上 ...

  9. [AngularJS] Test an Angular Component with $componentController

    Traditionally you had to create DOM elements to test a directive but by shifting our focus to compon ...

  10. debian防火墙firestarter

    Firestarter是一个非常好用的防火墙图形化配置工具,作者和开发者是芬兰人. 首先肯定的说Firestarter防火墙是一款非常优秀的基于GUI图形用户界面下的,完全免费的自由软件,它为中小型L ...