MVC5-10 ModleBinder那点事

模型绑定器

之前或多或少也提到过模型绑定器,方法的形参就是由模型绑定器把参数绑定上去的,今天就说说ModuleBingder那点事

在MVC中有一个接口叫IModuleBinder

//
    // 摘要:
    //     Defines the method that is required for a model binder.
    public interface IModelBinder
    {
        //
        // 摘要:
        //     Binds the model to a value by using the specified execution context and binding
        //     context.
        //
        // 参数:
        //   modelBindingExecutionContext:
        //     The execution context.
        //
        //   bindingContext:
        //     The binding context.
        //
        // 返回结果:
        //     true if model binding is successful; otherwise, false.
        bool BindModel(ModelBindingExecutionContext modelBindingExecutionContext, ModelBindingContext bindingContext);
    }

当然,这是接口,是没有实现的,MVC给我们提供了相应的实现类。DefaultModelBinder,所有的形参都是通过它去处理的。

image

下面是源码,这里可以看到有两个重要的方法  BindSimpleModel、BindComplexModel 简单类型绑定与复杂类型的绑定,实际上方法是递归调用的,如果参数是对象的话,那就会创建一个对象,然后在绑定每一个属性,而绑定每一个属性的方法里又调用了BindModel方法。

public virtual object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
        {
            RuntimeHelpers.EnsureSufficientExecutionStack();
            if (bindingContext == null)
            {
                throw new ArgumentNullException("bindingContext");
            }
            bool flag = false;
            if (!string.IsNullOrEmpty(bindingContext.ModelName) && !bindingContext.ValueProvider.ContainsPrefix(bindingContext.ModelName))
            {
                if (!bindingContext.FallbackToEmptyPrefix)
                {
                    return null;
                }
                ModelBindingContext context = new ModelBindingContext {
                    ModelMetadata = bindingContext.ModelMetadata,
                    ModelState = bindingContext.ModelState,
                    PropertyFilter = bindingContext.PropertyFilter,
                    ValueProvider = bindingContext.ValueProvider
                };
                bindingContext = context;
                flag = true;
            }
            if (!flag)
            {
                bool flag2 = ShouldPerformRequestValidation(controllerContext, bindingContext);
                ValueProviderResult valueProviderResult = bindingContext.UnvalidatedValueProvider.GetValue(bindingContext.ModelName, !flag2);
                if (valueProviderResult != null)
                {
                    return this.BindSimpleModel(controllerContext, bindingContext, valueProviderResult);
                }
            }
            if (!bindingContext.ModelMetadata.IsComplexType)
            {
                return null;
            }
            return this.BindComplexModel(controllerContext, bindingContext);
        }
protected virtual object GetPropertyValue(ControllerContext controllerContext, ModelBindingContext bindingContext, PropertyDescriptor propertyDescriptor, IModelBinder propertyBinder)
        {
            object objA = propertyBinder.BindModel(controllerContext, bindingContext);
            if (bindingContext.ModelMetadata.ConvertEmptyStringToNull && object.Equals(objA, string.Empty))
            {
                return null;
            }
            return objA;
        }

 

MVC是高度可替换的,如果DefaultModelBinder无法很好的实现我们的需求,那么可以写自己的ModelBinder。首先定义一个类去继承自IModelBinder实现BindModel方法,然后在Global里替换我们的MyModelBinder

public class Global : System.Web.HttpApplication
    {
        protected void Application_Start(object sender, EventArgs e)
        {
            //替换
            ModelBinders.Binders.DefaultBinder = new MyModelBinder();
        }

        public class MyModelBinder : IModelBinder
        {
            public object BindModel(ModelBindingExecutionContext modelBindingExecutionContext, ModelBindingContext bindingContext)
            {
                //Todo...   
            }
        }
    }
posted @ 2016-11-07 23:14  liangshiwei  阅读(470)  评论(0编辑  收藏  举报