• 值提供器 AND 模型绑定器


    本章介绍了值提供器的作用,ASP MVC自带的5中值提供器.以及模型绑定器的作用,自定义模型绑定器并使用自定义的模型绑定器(类型上加上[ModelBinder(typeof(xx))]或者在全局模型绑定器中注册)。

    补充:全局模型绑定器中注册自定义模型绑定器

    protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();

        RegisterGlobalFilters(GlobalFilters.Filters);
        RegisterRoutes(RouteTable.Routes);
        ModelBinders.Binders.Add(typeof(Point), new PointModelBinder());
    }

    值提供器

    ASP .NET MVC 框架自带的若干值提供器可以提供以下数据源中的数据:
    ●  子操作(RenderAction)的显式值
    ●  表单值
    ●  来自 XMLHttpRequest 的 JSON 数据
    ●  路由值
    ●  查询字符串值
    ●  上传的文件
    值提供器来自值提供器工厂,并且系统按照值提供器的注册顺序来从中搜寻数据(上面
    的列表使用的是默认顺序,自顶而下)。开发人员可以编写自己的值提供器工厂和值提供器,
    并且还可以将它们插入到包含在 ValueProviderFactories.Factories 中的工厂列表中。当在模
    型绑定期间需要使用额外的数据源时,开发人员通常选择编写自己的值提供器工厂和值提
    供器。

    除了 ASP .NET  MVC 本身包含的值提供器工厂以外,开发团队也在 ASP.NET  MVC  3
    Futures 包中包含了一些提供器工厂和值提供器,可从 http://aspnet.codeplex.com/releases/view/
    58781 上下载,或者安装 NuGet 包 Mvc3Futures。具体包括以下提供器:
    ●  Cookie 值提供器
    ●  服务器变量值提供器
    ●  Session 值提供器
    ●  TempData 值提供器

    模型绑定器

    1.作用

    模型扩展的另一部分是模型绑定器。它们从值提供器系统中获取值,并利用获取的值创建新模型或者填充已有的模型。

    模型绑定器,从值提供器中获取值。

    ASP .NET  MVC 中的默认模型绑定器( 为方便起见,命名为DefaultModelBinder)是一段功能非常强大的代码,它可以对传统类、集合类、列表、数组 甚至字典进行模型绑定。

    但是不支持对不改变对象的模型绑定(不可变指的是只能通过构造函数初始化值的类),如果遇见不可变的对象或者类型则默认的模型绑定器就无用了。此时需要自定义模型绑定器

    2. 自定义模型绑定器

    实现IModelBinder接口的 BinderModel方法

    object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)

    主要是用到ModelBindingContext类

    假设要对Point类进行模型绑定(Point类只能通过构造函数进行初始化,所以只能通过自定义模型提供器)

    下面是Point类代码和自定义模型绑定器代码

    Code Snippet
    1. using System;
    2. using System.Collections.Generic;
    3. using System.Linq;
    4. using System.Web;
    5.  
    6. using System.Web.Mvc; //IModelBinder
    7.  
    8. namespace MvcApplication1.Sample_ModelBinder
    9. {
    10.  
    11.     public class TestModelBinder : IModelBinder
    12.     {
    13.  
    14.         public object BindModel(ControllerContext controllerContext,
    15.         ModelBindingContext bindingContext)
    16.         {
    17.             var valueProvider = bindingContext.ValueProvider;
    18.           
    19.                 int x = (int)valueProvider.GetValue("X").ConvertTo(typeof(int));
    20.                 int y = (int)valueProvider.GetValue("Y").ConvertTo(typeof(int));
    21.  
    22.            
    23.            
    24.             return new Point(x, y);
    25.         }
    26.     }
    27.  
    28.  
    29.  
    30.     public class PointModelBinder : IModelBinder
    31.     {
    32.         //public object BindModel(ControllerContext controllerContext,
    33.         //ModelBindingContext bindingContext)
    34.         //{
    35.         //    var valueProvider = bindingContext.ValueProvider;
    36.         //    int x = (int)valueProvider.GetValue("X").ConvertTo(typeof(int));
    37.         //    int y = (int)valueProvider.GetValue("Y").ConvertTo(typeof(int));
    38.         //    return new Point(x, y);
    39.         //}
    40.  
    41.  
    42.         private TModel Get<TModel>(ControllerContext controllerContext,ModelBindingContext bindingContext,string name)
    43.         {
    44.             string fullName = name;
    45.             //1.modelname
    46.             if (!String.IsNullOrWhiteSpace(bindingContext.ModelName))
    47.                 fullName = bindingContext.ModelName + "." + name;
    48.  
    49.             //2.,valueProviderResult
    50.                 ValueProviderResult valueProviderResult =bindingContext.ValueProvider.GetValue(fullName);
    51.             //3.modelState
    52.                 ModelState modelState = new ModelState { Value = valueProviderResult };
    53.             //4.ModelstatebindingContext.ModelState
    54.                 bindingContext.ModelState.Add(fullName, modelState);
    55.             //5.null
    56.                 ModelMetadata metadata = bindingContext.PropertyMetadata[name];
    57.                 string attemptedValue = valueProviderResult.AttemptedValue;
    58.                 if (metadata.ConvertEmptyStringToNull&& String.IsNullOrWhiteSpace(attemptedValue))
    59.                     attemptedValue = null;
    60.  
    61.             //6.  
    62.                 TModel model;
    63.                 bool invalidValue = false;
    64.                 try
    65.                 {
    66.                     model = (TModel)valueProviderResult.ConvertTo(typeof(TModel));
    67.                     metadata.Model = model;                  //XX
    68.                 }
    69.                 catch (Exception)
    70.                 {
    71.                     model = default(TModel);             //int 0.boolfalse,null
    72.                     metadata.Model = attemptedValue;
    73.                     invalidValue = true;              //null
    74.                 }
    75.  
    76.  
    77.             ///
    78.                 IEnumerable<ModelValidator> validators =
    79.                 ModelValidatorProviders.Providers.GetValidators(
    80.                 metadata,
    81.                 controllerContext
    82.                 );
    83.             
    84.                 foreach (var validator in validators)
    85.                     foreach (var validatorResult in
    86.                     validator.Validate(bindingContext.Model))
    87.                         modelState.Errors.Add(validatorResult.Message);
    88.                 if (invalidValue && modelState.Errors.Count == 0)
    89.                     modelState.Errors.Add(
    90.                     String.Format(
    91.                     "The value '{0}' is not a valid value forr {1}.",
    92.                     attemptedValue,
    93.                     metadata.GetDisplayName()
    94.                     )
    95.                     );
    96.                 return model;
    97.         }
    98.         public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    99.         {
    100.  
    101.             //1.modelname object
    102.             //
    103.             if (!String.IsNullOrEmpty(bindingContext.ModelName) &&
    104.                 !bindingContext.ValueProvider.ContainsPrefix(bindingContext.ModelName))
    105.             {
    106.                 if (!bindingContext.FallbackToEmptyPrefix)
    107.                     return null;
    108.                 bindingContext = new ModelBindingContext
    109.                 {
    110.                     ModelMetadata = bindingContext.ModelMetadata,
    111.  
    112.                     ModelState = bindingContext.ModelState,
    113.                     PropertyFilter = bindingContext.PropertyFilter,
    114.                     ValueProvider = bindingContext.ValueProvider
    115.                 };
    116.             }
    117.  
    118.             bindingContext.ModelMetadata.Model = new Point();
    119.  
    120.             return new Point(Get<int>(controllerContext, bindingContext, "X"), Get<int>(controllerContext, bindingContext, "Y"));
    121.  
    122.         }
    123.  
    124.     }
    125.     [ModelBinder(typeof(PointModelBinder))]
    126.     //[ModelBinder(typeof(TestModelBinder))]
    127.     public class Point
    128.     {
    129.         private int x;
    130.  
    131.         public int X
    132.         {
    133.             get { return x; }
    134.           
    135.             set { x = value;}  //
    136.         }
    137.     
    138.         private int y;
    139.  
    140.     public int Y
    141.     {
    142.         get { return y;}
    143.         set { y = value;}
    144.     }
    145.     
    146.  
    147.  
    148.         public Point(int x, int y)
    149.         {
    150.             this.x = x;
    151.             this.y = y;
    152.         }
    153.         public Point()
    154.         {
    155.  
    156.         }
    157.     }
    158. }

    通过调试可以发现ModelBindingContext  包含了

    1)值提供器(字符串值提供器,form值提供器,routeDate值提供其,httpfilCollection提供器,childAction值提供器)

    2)model 指明了是 point类

    3)属性元数据 propertyMetadata  表明了有 x,y两属性

    image

    模型绑定器的原理

    注明:元数据指的是属性的详细信息,比如:dispalyname特性,属性类型  等等

    1. 值提供器中检索值,然后在模型状态中记录值

    1)ModelBindingContext的值提供器,默认提供了5种值提供器

    2)在模型状态中记录值是因为如果信息错误,可以将错误信息回传显示

    2.获得一个描述该属性的模型元数据的副本,然后再决定用户输入值的内容

    3.将值转换为目标类型,转换错误则赋值类型的默认值

    4.记录错误默认错误信息,回传model

    5.使用自定义模型版定器,在类型上面加上

    [ModelBinder(typeof(PointModelBinder))]

  • 相关阅读:
    字典对象的 Pythonic 用法(上篇:转载)
    代码这样写更优雅(Python 版)(转载)
    [Python爬虫] 之二十七:Selenium +phantomjs 利用 pyquery抓取今日头条视频
    [Python爬虫] 之二十六:Selenium +phantomjs 利用 pyquery抓取智能电视网站图片信息
    [Python爬虫] 之二十五:Selenium +phantomjs 利用 pyquery抓取今日头条网数据
    [Python爬虫] 之二十四:Selenium +phantomjs 利用 pyquery抓取中广互联网数据
    [Python爬虫] 之二十三:Selenium +phantomjs 利用 pyquery抓取智能电视网数据
    MOVE降低高水位 HWM
    select查询语句执行顺序
    Oracle表空间维护总结
  • 原文地址:https://www.cnblogs.com/StudyLife/p/3628292.html
Copyright © 2020-2023  润新知