这篇博客是借助一个自己写的工程来理解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. 去除Linq to Sql 查询结果中的空格

    原来的写法: Dim db = From city In DataContext1.AddressCity Where city.ProvinceID = dgvAddress(2, e.RowInd ...

  2. cloudstack 修改显示名称

    http://192.168.153.245:8900/client/api?command=updateVirtualMachineid=922d15e1-9be0-44ac-9494-ce5afc ...

  3. jQuery 源码解析一:jQuery 类库整体架构设计解析

    如果是做 web 的话,相信都要对 Dom 进行增删查改,那大家都或多或少接触到过 jQuery 类库,其最大特色就是强大的选择器,让开发者脱离原生 JS 一大堆 getElementById.get ...

  4. Oracle DataGuard搭建(二)

    三.配置备库 创建catalog数据库 用dbca创建数据库,用oracle自带模板,不用em,启用归档,同一管理密码oracle,global name:dbcat1.node249.gewara, ...

  5. javascript 笔记(待续)

    1.基础对象  var o=new Object();  o.xxx=1; o.xx=2;    var 01={xxx=1,xx=2} 2.==与===   "5"==5 Tru ...

  6. Winform-控制边框显示属性

  7. Java模拟登陆【转载】

    import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.i ...

  8. delphi 11 编辑模式 浏览模式

    编辑模式 浏览模式 设置焦点 //在使用前需要Webbrowser已经浏览过一个网页 否则错误 uses MSHTML; ///获取Webbrowser编辑模式里面的内容procedure EditM ...

  9. 从user 登陆開始

    首先.我们来看看我们的需求,看看需求里有没有你感兴趣的知识点: 用户登陆: 实现用户从网页登陆界面输入正确的username.password及验证码后跳转到一个页面显示登陆成功 要求:  1. 数据 ...

  10. android151 笔记 3

    34. 对android虚拟机的理解,包括内存管理机制垃圾回收机制. 虚拟机很小,空间很小,谈谈移动设备的虚拟机的大小限制 16M , 谈谈加载图片的时候怎么处理大图片的,压缩. 垃圾回收,没有引用的 ...