zoukankan      html  css  js  c++  java
  • ModelBinder

    MVC Form表单的value就会自动匹配到Action的参数中,是如何实现的呢?

    通过 反编译System.Web.Mvc.dll, 从Controller入手,会发现Controller中的执行核心ExcuteCore()中会InvokeAction

    这里ActionInvoker是一个ControllerActionInvoker对象中调用了GetPrameterValues方法

    ActionDescriptor的作用是对Action方法的元数据的描述,通过ActionDescriptor可以获取action的参数列表。

    遍历参数列表为参数列表和表单数据做binding。

    这里Modelbinder出现了,初始化Modelbinding上下文

    ModelMetaData: model的显示和验证信息。

    ModelName:model名称,如果有前缀的话就是前缀名(User.Name),没有的话就是参数名(User or Name)

    ModelState: 提示model的错误信息,验证通过IsValid = ture

    PropertyFilter:ParameterBindingInfo参数绑定的信息,如:有没有前缀,有没有需要include或exclude binding的数据。

    关键方法ModelBinder.BindModel.

    MVC有默认的ModelBinder:DefaultModelBinder 实现了IModelBinder接口的BindModel方法即可。(所以我们如果想实现自己的ModelBinder,可以实现IModelBinder接口)BindModel中有两种SimpleBind ,ComplexBind

    自定义MyModelBinder:

    public class MyModelBinder : IModelBinder
        {
            public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
            {
                return GetModel(bindingContext.ValueProvider, bindingContext.ModelName, bindingContext.ModelType);
            }
            public object GetModel(IValueProvider valueProvider, string modelName, Type modelType)
            {
    
                ModelMetadata modelMetadata = ModelMetadataProviders.Current.GetMetadataForType(() => null, modelType);
                //如果绑定的类型是简单类型
                if (!modelMetadata.IsComplexType)
                {
                    return valueProvider.GetValue(modelName).ConvertTo(modelType);
                }
                object model = Activator.CreateInstance(modelType);
                //如果是复杂类型
                //前台表单标签的name属性的值有modelName的前缀
                if (valueProvider.ContainsPrefix(modelName))
                {
                    foreach (PropertyDescriptor porperty in TypeDescriptor.GetProperties(modelType))
                    {
    
                        string strkey = modelName + "." + porperty.Name;
                        if (HttpContext.Current.Request.Form.AllKeys.Contains<string>(strkey))
                            porperty.SetValue(model, valueProvider.GetValue(strkey).ConvertTo(porperty.PropertyType));
                    }
                }
                //不包含前缀,但是标签的name属性的值等于绑定类的属性的名字
                else
                {
                    foreach (PropertyDescriptor porperty in TypeDescriptor.GetProperties(modelType))
                    {
                        string strkey = porperty.Name;
                        if (HttpContext.Current.Request.Form.AllKeys.Contains<string>(strkey))
                            porperty.SetValue(model, valueProvider.GetValue(strkey).ConvertTo(porperty.PropertyType));
                    }
    
                }
                return model;
            }
    
    
        }
    View Code
     public ActionResult ModelBinder([ModelBinder(typeof(MyModelBinder))]User User)
  • 相关阅读:
    jdk动态代理
    mysql-索引方案
    闭包的有点以及出现的内存泄露2016/4/12
    表单2016/4/8
    cursor
    同一个事件绑定不同的函数
    a:link visited hover active
    对于属性操作,加入属性,移除属性
    offset获取位置
    清除浮动6中方法
  • 原文地址:https://www.cnblogs.com/lemonP/p/7171669.html
Copyright © 2011-2022 走看看