zoukankan      html  css  js  c++  java
  • MVC Model Binder

    这篇博客是借助一个自己写的工程来理解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         }

    到此,整个过程已讲完。

  • 相关阅读:
    jQuery插件:用于获取元素自身的HTML内容
    自定义 Web 部件用户界面简介
    在MOSS2010中实现OU下的用户的上下级组织关系
    sharepoint2010人性化的地方--员工离职AD账号禁用(个人网站自动提醒上级经理功能)
    SharePoint2010文档归档策略(2)-从放置库转移到自己定义的文档库
    SharePoint2010文档归档策略
    如何用VS2010在SharePoint中创建自定义字段类型(以eWebEditor为例)
    如何实现SP文档库类似百度文档库的效果 (副标题:如何在SP2013文档库的SWF文件用FlexPager显示)
    查看SharePoint文档库是,显示层次目录,可以点击返回层次
    安装和配置SharePoint 2013 with SP1 Workflow
  • 原文地址:https://www.cnblogs.com/kyo-lynn/p/3420382.html
Copyright © 2011-2022 走看看