zoukankan      html  css  js  c++  java
  • ASP.NET MVC5 ModelBinder

    什么是ModelBinding

    ASP.NET MVC中,所有的请求最终都会到达某个Controller中的某个Action并由该Action负责具体的处理和响应。为了能够正确处理请求,Action的参数(如果有的话),必须在Action执行之前,根据相应的规则,把请求中所包含的数据提取出来并将映射为Action的参数值,这个过程就是ModelBinding。ModelBinding的作用就是为Action提供参数列表。

    ModelBinding的好处

    1. 使代码变得更加简洁
    2. 帮助我们获取HTTP请求中的数据
    3. 帮助我们完成必要的数据类型转换

    ASP.NET MVC中ModelBinding的实现过程

    ASP.NET MVC中ModelBinding的实现过程比较复杂,这里简要说明它的总体流程。具体的实现过程可以看蒋金楠的《ASP.NET MVC5框架揭秘》或者看他的博客How ASP.NET MVC Works?,讲解很详细。


     
    • HTTP请求中的数据可能存在于querystring中,也可能在表单中,也有可能是JSON字符串。究竟从哪里获取数据,这要依赖于参数的描述信息ParameterDescriptor
    • ParameterDescriptor的获取需要借助于ControllerDescriptorActionDescriptor,它们分别用来描述Controller和Action
    • IModelBinderProvider用于提供合适的ModelBinder对象,我们可以自己实现该接口以获取自定义的IModelBinder
    • ModelBinding的核心IModelBinder,默认实现类是DefaultModelBinder,我们可以自己实现IModelBinder接口来扩展ModelBinder
    • IValueProvider针对不同的数据源提供了数据的访问机制
    • ValueProviderResult提供了两个ConvertTo方法重载以实现向指定目标类型的转换。
    • 经过上述一系列的处理获取最终结果

    自定义ModelBinder

    自定义Modelbinder只需实现System.Web.Mvc.IModelBinder接口即可。这里需要注意一点,System.Web.ModelBinding命名空间下也有一个IModelBinder接口,不要搞错了。

    public class LessonEditInfoViewModelBinder : IModelBinder
    {
        //根据前台传递的id值获取对象
        public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
        {
            var idStr = controllerContext.HttpContext.Request["id"] ?? controllerContext.RouteData.Values["id"]?.ToString();
            int id = 0;
            if (!int.TryParse(idStr, out id))
            {
                return null;
            }
            var model = new LessonBLL().GetLessonEditInfo(id);
            return model;
        }
    }

    然后使用ModelBinderAttribute进行标注即可:

    /*
        根据前台传递的id值解析出对象数据,Action无需关注对象的获取,使代码变得清晰简洁
    */
    public ActionResult Edit([ModelBinder(typeof(LessonEditInfoViewModelBinder))]LessonEditInfoViewModel lesson)
    {
        if (lesson == null)
        {
            //跨控制器的视图跳转要使用视图的路径+文件名
            return View("/Views/Exception/GenericError.cshtml", new ExceptionViewModel { Title = "404", Description = "课程不存在!" });
        }
        return View(lesson);
    }

    如果项目中多处需要使用自定义的ModelBinder,那么再使用ModelBinderAttribute进行标注就不大合适了。这种情况我们可以使用自定义的ModelBinderProvier。代码如下:

    public class CustomeModelBinderProvider : IModelBinderProvider
    {
        public IModelBinder GetBinder(Type modelType)
        {
            if (modelType == typeof(LessonEditInfoViewModel))
            {
                return new LessonEditInfoViewModelBinder();
            }
            return null;
        }
    }

    然后将自定义的ModelBinderProvider注册到ASP.NET MVC系统中

    public class MvcApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            ModelBinderProviders.BinderProviders.Insert(0, new CustomeModelBinderProvider());
        }
    }

    完成上述两步之后,就无需使用ModelBuilderAttribute进行标注了。

    除此之外,还可在Global文件中使用使用ModelBinder类的Binder属性来注册ModelBinderProvider

    ModelBinders.Binders.Add(typeof(LessonEditInfoViewModel),new LessonEditInfoViewModelBinder());

    不同的ModelBinder提供策略有不同的优先级,具体如下:

    1. 在参数上使用CustomModelBinderAttribute
    2. 使用ModelBinderProviders.BinderProviers
    3. 使用ModelBinders.Binders
    4. 参数类型上标记CustomModelBinderAttribute
    5. ASP.NET MVC中提供的DefaultModelBinder

    注意,CustomModelBinderAttribute是抽象类,在ASP.NET MVC中有唯一子类ModelBinderAttribute。

    参考文章:

    Model Binders in ASP.NET MVC
    ModelBinder——ASP.NET MVC Model绑定的核心
    ASP.NET MVC以ValueProvider为核心的值提供系统
    玩转Asp.net MVC 的八个扩展点
    ASP.NET MVC中你必须知道的13个扩展点

    版权声明

    本文为作者原创,版权归作者雪飞鸿所有。 转载必须保留文章的完整性,且在页面明显位置处标明原文链接

    如有问题, 请发送邮件和作者联系。

  • 相关阅读:
    字符串语法
    组合数
    并查集
    Java Collection HashMap源码分析
    Java 虚拟机 ClassLoader
    Java 多线程 Future
    Java 虚拟机 GC机制
    Java 基础 原生类型
    Java 多线程 死锁deadlock产生原因+避免方法
    Java 基础 基本类型vs引用类型,传值vs传引用
  • 原文地址:https://www.cnblogs.com/Cwj-XFH/p/5977508.html
Copyright © 2011-2022 走看看