MVC Model Binder_.NET_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > .NET > MVC Model Binder

MVC Model Binder

 2013/11/12 22:45:21  立地太岁  博客园  我要评论(0)
  • 摘要:这篇博客是借助一个自己写的工程来理解modelbinder的过程.MVC通过路由系统,根据url找到对应的Action,然后再执行action,在执行action的时候,根据action的参数和数据来源比对,生成各个参数的值,这就是modelbinder.IActionInvokerMVC中这个核心处理逻辑都在ControllerActionInvoker里,用reflector看
  • 标签:MVC

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


 

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

IActionInvoker


 

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

1     public interface IActionInvoker
2     {
3         bool InvokeAction(ControllerContext controllerContext, string actionName);
4     }

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

以下是我自己写的ActionInvoker类

 1     public class CustomActionInvoker : IActionInvoker
 2     {
 3 
 4         public bool InvokeAction(ControllerContext controllerContext, string actionName)
 5         {
 6             bool flag = false;
 7             try
 8             {
 9                 //get controller type
10                 Type controllerType = controllerContext.Controller.GetType();
11                 //get controller descriptor
12                 ControllerDescriptor controllerDescriptor = 
new ReflectedControllerDescriptor(controllerType); 13 //get action descriptor 14 ActionDescriptor actionDescriptor =
controllerDescriptor.FindAction(controllerContext, actionName);
15 Dictionary<string, object> parameters =

new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase); 16 //get parameter-value entity 17 foreach (ParameterDescriptor parameterDescriptor in actionDescriptor.GetParameters()) 18 { 19 Type parameterType = parameterDescriptor.ParameterType; 20 //get model binder 21 IModelBinder modelBinder = new CustomModelBinder(); 22 IValueProvider valueProvider = controllerContext.Controller.ValueProvider; 23 string str = parameterDescriptor.BindingInfo.Prefix ?? parameterDescriptor.ParameterName; 24 ModelBindingContext bindingContext = new ModelBindingContext(); 25 bindingContext.FallbackToEmptyPrefix = parameterDescriptor.BindingInfo.Prefix == null; 26 bindingContext.ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(null, parameterType); 27 bindingContext.ModelName = str; 28 bindingContext.ModelState = controllerContext.Controller.ViewData.ModelState; 29 bindingContext.ValueProvider = valueProvider; 30 parameters.Add(parameterDescriptor.ParameterName,
modelBinder.BindModel(controllerContext, bindingContext));
31 } 32 ActionResult result = (ActionResult)actionDescriptor.Execute(controllerContext, parameters); 33 result.ExecuteResult(controllerContext); 34 flag = true; 35 } 36 catch (Exception ex) 37 { 38 //log 39 } 40 return flag; 41 } 42 }

以下详细解释下执行过程

*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

1     public interface IModelBinder
2     {
3         object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext);
4     }

其中CustomModelBinder的代码如下

 1     public class CustomModelBinder : IModelBinder
 2     {
 3 
 4         public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
 5         {
 6             return this.GetModel(controllerContext, bindingContext.ModelType, bindingContext.ValueProvider, bindingContext.ModelName);
 7         }
 8 
 9         public object GetModel(ControllerContext controllerContext, Type modelType, IValueProvider valueProvider, string key)
10         {
11             if (!valueProvider.ContainsPrefix(key))
12             {
13                 return null;
14             }
15             return valueProvider.GetValue(key).ConvertTo(modelType);
16         }
17     }

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

中间有最核心的方法

valueProvider.GetValue(key).ConvertTo(modelType)

ValueProvider


 

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

1     ValueProviderFactoryCollection factorys = new ValueProviderFactoryCollection();
2     factorys.Add(new ChildActionValueProviderFactory());
3     factorys.Add(new FormValueProviderFactory());
4     factorys.Add(new JsonValueProviderFactory());
5     factorys.Add(new RouteDataValueProviderFactory());
6     factorys.Add(new QueryStringValueProviderFactory());
7     factorys.Add(new HttpFileCollectionValueProviderFactory());

注册ActionInvoker


 

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

1         protected override IActionInvoker CreateActionInvoker()
2         {
3             return new CustomActionInvoker();
4         }

到此,整个过程已讲完。

发表评论
用户名: 匿名