这篇博客是借助一个自己写的工程来理解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. Unity3D行为树插件Behave学习笔记

    Behave1.4行为树插件 下载地址:http://pan.baidu.com/s/1i4uuX0L 安装插件和使用 我们先来看看插件的安装和基本使用方法,新建一个Unity3D项目,这里我使用的是 ...

  2. TypeScript学习笔记(七):模块

    JavaScript中的模块 在学习TypeScript的模块之前我们先看看在JavaScript中的模块是如何实现的. 模块的好处 首先我们要了解使用模块的好处都有什么? 模块化.可重用: 封装变量 ...

  3. Autofac介绍

    原帖:http://www.cnblogs.com/xupng/archive/2011/07/12/2104766.html Autofac为何物?它是.NET世界里现存的几种IOC框架其中之一,传 ...

  4. java中关于类的封装与继承,this、super关键字的使用

    原创作品,可以转载,但是请标注出处地址http://www.cnblogs.com/V1haoge/p/5454849.html. this关键字: this代表当前对象,它有以下几种用途: 1.本类 ...

  5. sql,mybatis,javascript分页功能的实现

    用三种不同的方法实现多数据的分页功能.原生sql和mybatis的操作需要每次点击不同页数时都发送http请求,进行一次数据库查询,如果放在前端页面写js语句则不需要每次都请求一次,下面是三种不同的方 ...

  6. 函数定义从零开始学C++之从C到C++(一):const与#define、结构体对齐、函数重载name mangling、new/delete 等

    今天一直在学习函数定义之类的问题,下午正好有机会和大家共享一下. 一.bool 类型 逻辑型也称布尔型,其取值为true(逻辑真)和false(逻辑假),存储字节数在不同编译系统中可能有所不同,VC+ ...

  7. HDU 5536 Chip Factory 字典树

    Chip Factory Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid= ...

  8. [Jest] Track project code coverage with Jest

    Jest comes pre-packaged with the ability to track code coverage for the modules you're testing, but ...

  9. show engine innodb status解读

    xiaoboluo768   注:以下内容为根据<高性能mysql第三版>和<mysql技术内幕innodb存储引擎>的innodb status部分的个人理解,如果有错误,还 ...

  10. 描述cookie,sessionstroage,localstrage的区别

    HTML5 提供了两种在客户端存储数据的新方法(Web Storage): localStorage - 没有时间限制的数据存储 sessionStorage - 针对一个 session 的数据存储 ...