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个扩展点

    版权声明

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

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

  • 相关阅读:
    Linux 下的类似Windows下Everything的搜索工具
    windows和linux环境下制作U盘启动盘
    程序调试手段之gdb, vxworks shell
    LeetCode 1021. Remove Outermost Parentheses (删除最外层的括号)
    LeetCode 1047. Remove All Adjacent Duplicates In String (删除字符串中的所有相邻重复项)
    LeetCode 844. Backspace String Compare (比较含退格的字符串)
    LeetCode 860. Lemonade Change (柠檬水找零)
    LeetCode 1221. Split a String in Balanced Strings (分割平衡字符串)
    LeetCode 1046. Last Stone Weight (最后一块石头的重量 )
    LeetCode 746. Min Cost Climbing Stairs (使用最小花费爬楼梯)
  • 原文地址:https://www.cnblogs.com/Cwj-XFH/p/5977508.html
Copyright © 2011-2022 走看看