首页 技术 正文
技术 2022年11月19日
0 收藏 685 点赞 4,980 浏览 6551 个字

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

 

 

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

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

2)model 指明了是 point类

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

值提供器 AND 模型绑定器

 

 

 

 

 

 

 

 

 

模型绑定器的原理

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

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

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

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

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

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

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

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

[ModelBinder(typeof(PointModelBinder))]

相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:9,078
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,553
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,402
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,177
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:7,814
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:4,898