MVC Model Binder
这篇博客是借助一个自己写的工程来理解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的更多相关文章
- MVC Model Binder 规则
http://www.cnblogs.com/mszhangxuefei/archive/2012/05/15/mvcnotes_30.html 使用默认的Model Binder(Using the ...
- Asp.net MVC的Model Binder工作流程以及扩展方法(2) - Binder Attribute
上篇文章中分析了Custom Binder的弊端: 由于Custom Binder是和具体的类型相关,比如指定类型A由我们的Custom Binder解析,那么导致系统运行中的所有Action的访问参 ...
- Asp.net MVC的Model Binder工作流程以及扩展方法(3) - DefaultModelBinder
Default Binder是MVC中的清道夫,把守着Model Binder中的最后一道防线.如果我们没有使用Custom Model Binder等特殊处理,那么Model的绑定都是有Defaul ...
- Asp.net MVC的Model Binder工作流程以及扩展方法(1) - Custom Model Binder
在Asp.net MVC中, Model Binder是生命周期中的一个非常重要的部分.搞清楚Model Binder的流程,能够帮助理解Model Binder的背后发生了什么.同时该系列文章会列举 ...
- ASP.NET MVC中默认Model Binder绑定Action参数为List、Dictionary等集合的实例
在实际的ASP.NET mvc项目开发中,有时会遇到一个参数是一个List.Dictionary等集合类型的情况,默认的情况ASP.NET MVC框架是怎么为我们绑定ASP.NET MVC的Actio ...
- Asp.net MVC的Model Binder工作流程以及扩展方法(1)
Asp.net MVC的Model Binder工作流程以及扩展方法(1)2014-03-19 08:02 by JustRun, 523 阅读, 4 评论, 收藏, 编辑 在Asp.net MVC中 ...
- ASP.NET MVC Model绑定(二)
ASP.NET MVC Model绑定(二) 前言 上篇对于Model绑定的简单演示想必大家对Model绑定的使用方式有一点的了解,那大家有没有想过Model绑定器是在什么时候执行的?又或是执行的过程 ...
- ModelBinder——ASP.NET MVC Model绑定的核心
ModelBinder——ASP.NET MVC Model绑定的核心 Model的绑定体现在从当前请求提取相应的数据绑定到目标Action方法的参数.通过前面的介绍我们知道Action方法的参数通过 ...
- ASP.NET MVC2之Model Binder
Model Binder在Asp.net MVC中非常简单.简单的说就是你控制器中的Action方法需要参数数据:而这些参数数据包含在HTTP请求中,包括表单上的Value和URL中的参 数等.而Mo ...
随机推荐
- 使用apt-get autoremove造成的系统无法开机
由于误操作(apt-get autoremove xxx)删除了一些lib文件貌似,之后,系统直接重启,然后就无法进入系统,后使用引导盘对系统进行修复,思路如下: 1.挂载已经有的分区,挂载为可读可写 ...
- python list(列表)和tuple(元组)
200 ? "200px" : this.width)!important;} --> 介绍 python中存在两种有序的类型列表,分别是list(列表)和tuple(元组) ...
- 从gitbook将书籍导入到github中
gitbook自己的导出工具经常出问题,可直接使用git. 从gitbook中clone下书 $ git clone https://git.gitbook.com/username/name_of_ ...
- C++ 内存相关
1.C++的内存管理可分为以下几个部分: 栈:记录程序的执行过程. 堆:采用new,delete申请释放内存. 自由存储区:对应于C中使用malloc,free申请释放内存. 全局存储区:也叫静态存储 ...
- JSON API in Javascript
1. Serialize JavaScript object to JSON var messageObject = { title: 'Hello World!', body: 'It\'s gr ...
- IOS AutoLayout 文章
开始iOS 7中自动布局教程(一) 开始iOS 7中自动布局教程(二) 代码的方式自动布局 自动布局时计算Cell高度
- Jquery 表格固定表头
网上找了好多现成的.结果没一个能成.只得自己动手. (function($){ $.fn.fixHeader = { init : function(obj){ var p = obj.parent( ...
- debian清除无用的库文件(清理系统,洁癖专用)
deborphan 可以用来找出在系统中已经没有被依赖的套件.一般的情况是 library 会在其他套件需要的时候被牵引进来,但是当这些套件升级或删除后,被牵引进来的 library package ...
- 细说linux挂载——mount,及其他……
http://forum.ubuntu.org.cn/viewtopic.php?t=257333
- grep时排除指定的文件和目录
参考:http://winterth.duapp.com/notes/ar03s04.htmlhttp://blog.sina.com.cn/s/blog_7169c8ce0100qkyf.html ...