ASP.NET MVC Model绑定(三)

简介:

ASP.NET MVC Model绑定(三)

前言

看过前两篇的朋友想必对Model绑定有个大概的了解,然而MVC框架给我们提供了更高的可扩展性的提供程序编程模式,也就是本篇的主题了,会讲解一下Model绑定器提供程序的实现以及解决一下上篇遗留的问题。

第一个问题是ModelBinderProviderCollection类型的执行过程?

还有个本篇的问题就是同样的向系统上下文中注册Model绑定器和Model绑定器提供程序,哪一个优先级更高?

 

Model绑定

  • IModelBinder、自定义Model绑定器简单实现

  • Model绑定器在MVC框架中的位置

  • MVC中的默认Model绑定器生成过程

  • IModelBinderProvider的简单应用

  • IValueProvider在MVC框架中生成的位置以及过程

  • IValueProvider的应用场景

  • IValueProvider的实现之NameValueCollectionValueProvider

 

IModelBinderProvider的简单应用

首先我们先看一下IModelBinderProvider类型的定义,代码1-1:。

代码1-1

1
2
3
4
5
6
7
8
9
10
11
12
13
     public  interface  IModelBinderProvider
     {
         // 摘要:
         //     返回指定类型的模型联编程序。
         //
         // 参数:
         //   modelType:
         //     模型的类型。
         //
         // 返回结果:
         //     指定类型的模型联编程序。
         IModelBinder GetBinder(Type modelType);
     }

在代码1-1中我们看出,其中的GetBinder()方法是根据ViewModel的类型来做一些操作,最后返回Model绑定器。现在我们自定义实现一个Model绑定器提供程序代码1-2。

代码1-2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
using  System.Web.Mvc;
using  ConsoleApplication2;
 
namespace  MvcApplication.Infrastructure
{
     public  class  MyCustomModelBinderProvider : IModelBinderProvider
     {
         public  IModelBinder GetBinder(Type modelType)
         {
             if  (modelType ==  null )
             {
                 throw  new  ArgumentNullException( "modelType" );
             }
             if  (modelType ==  typeof (Customer))
             {
                //返回对应Customer类型的Model绑定器
             }
             return  null ;
         }
     }
}

在代码1-2中我们根据modelType判断是否是Customer类型,然后返回对应Customer类型的Model绑定器。为什么这里的实现是空的,因为我想把我们前面讲解过的IoC框架用起来,让Model绑定器提供程序跟Model绑定器解除耦合,想把IoC框架的应用定义在当前系统的上下文中,我们看一下代码实现,代码1-3。

代码1-3

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
namespace  MvcApplication
{
     public  class  MVCSystemContext
     {
         private  static  MVCSystemContext _MVCSystemContext;
 
         public  static  MVCSystemContext Context
         {
             get
             {
                 if  (_MVCSystemContext ==  null )
                 {
                     _MVCSystemContext =  new  MVCSystemContext();
                 }
                 return  _MVCSystemContext;
             }
         }
 
         private  ServiceContainer _serviceContainer;
 
         private  MVCSystemContext()
         {
             _serviceContainer =  new  ServiceContainer();
             _serviceContainer.AddService( typeof (NinjectController),NinjectController.Instance);
         }
 
         public  NinjectController NinjectController
         {
             get
             {
                 return  (NinjectController)_serviceContainer.GetService( typeof (NinjectController));
             }
         }
 
 
     }
}

代码1-3当中就是我定义的当前系统上下文了,只不过这个是给自己用的,上下文对象中想必是不会把所用到的所有数据或者是功能都添加在里面的,只是添加个引用而已,如代码1-3中的NinjectController属性,NinjectController属性对应的类型就是NinjectController类型,NinjectController类型的作用就是提供IoC框架的功能,我们看一下代码1-4中对于NinjectController类型的定义。

代码1-4

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
using  Ninject;
 
namespace  MvcApplication.Infrastructure.NinjectControllerPart
{
     public  class  NinjectController
     {
         private  static  NinjectController _Instance;
 
         public  static  NinjectController Instance
         {
             get 
             {
                 return  _Instance =  new  NinjectController();
             }
         }
 
         private  IKernel _ninjectKernel;
 
         private  NinjectController()
         {
             _ninjectKernel =  new  StandardKernel();
         }
 
         public  void  AddKernelBind<T, U>() where  U:T
         {
             _ninjectKernel.Bind<T>().To<U>();
         }
 
         public  T GetValueType<T>(Type keyType)
         {
             var  valueType = _ninjectKernel.Get(keyType);
             return  (T)valueType;
         }
     }
}

其中对于Ninject这个IoC框架进行了一个最基础的功能封装,有的朋友可能会问为什么不公开个一个属性,何必这样多此一举,因为我对Ninject的使用也不是很熟练,对于这部分的封装我只是让其简单的公开了两个功能,一个是绑定一个是获取值,这样让这部分内容还在我的可控范围内,如果是公开属性的话,其他人的胡乱使用导致错误的话是不可控的。

切回主题,这样基础定义好了过后,我们再修改1-2中的代码,把具体实现给加上,示例代码1-5所示。

代码1-5

1
2
3
4
5
if  (modelType ==  typeof (Customer))
{
     //返回对应Customer类型的Model绑定器
     return  MVCSystemContext.Context.NinjectController.GetValueType<IModelBinder>( typeof (IModelBinder));
}

可以看到代码1-5中,根据我们自定义上下文中的提供的IoC功能获取到绑定在IoC框架中的值,那么绑定又是在哪里呢?跟ASP.NET MVC Model绑定(一)所演示的那样,还是在项目的Global.asax文件中的MvcApplication类型的Application_Start()方法中添加如代码1-6。

代码1-6

1
2
MVCSystemContext.Context.NinjectController.AddKernelBind<IModelBinder, Binders.MyCustomModelBinder>();
ModelBinderProviders.BinderProviders.Add( new  MyCustomModelBinderProvider());

代码1-6分别做了两个操作,先是把对应Customer类型的Model绑定器注册到了我们自定义上下文的IoC中,然后再把针对处理Customer类型的Model绑定器提供程序注册到系统中。运行结果如图1.

图1

其中涉及到所有部分的代码和ASP.NET MVC Model绑定(一)篇幅中的一样,所以这里就没有列举了。

在此我们根据上篇中最后图2所示的那样,可以判断出ModelBinderProviderCollection类型的执行过程是根据当前ParameterDescriptor类型所提供的Model类型对比我们注册到或者是系统默认提供的Model绑定器提供程序集合,如果有是针对ParameterDescriptor类型所提供的Model类型(上述示例中是Customer类型)则会有Model绑定器的返回,然后再根据Model绑定器进行Model绑定。

 

好了现在第一个问题解决了,来解决第二个问题。来看代码1-7所示。

代码1-7

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
public  class  MyCustomModelBinder:IModelBinder
     {
         public  object  BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
         {
             return  new  Customer()
             {
                 CustomerID =  "010" ,
                 Name =  "测试人员" ,
                 RegistrationDate = DateTime.Now,
                 Address =  new  Address()
                 {
                     AddressName =  "天空之城"
                 }
             };
         }
     }
 
     public  class  MyCustomModelBinder_Test : IModelBinder
     {
         public  object  BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
         {
             return  new  Customer()
             {
                 CustomerID =  "010" ,
                 Name =  "测试人员" ,
                 RegistrationDate = DateTime.Now,
                 Address =  new  Address()
                 {
                     AddressName =  "这里是根据Model绑定器绑定执行的Model"
                 }
             };
         }
     }

看到代码1-7中的MyCustomModelBinder_Test 类型内部Customer类型实例内部的AddressName值已经更改的和之前的不一样了。再看一***册端的修改,示例代码1-8。

代码1-8

1
2
3
ModelBinders.Binders.Add( typeof (Customer),  new  Binders.MyCustomModelBinder_Test());
MVCSystemContext.Context.NinjectController.AddKernelBind<IModelBinder, Binders.MyCustomModelBinder>();
ModelBinderProviders.BinderProviders.Add( new  MyCustomModelBinderProvider());

代码1-8中,我们把新定义的MyCustomModelBinder_Test 类型注册到了系统的Model绑定器集合中,看一下究竟是哪一个级别更高一点。

来看运行结果图2

图2

看到图2这个结果,想必已经知道了是哪个级别更高一点了。



     本文转自jinyuan0829 51CTO博客,原文链接:http://blog.51cto.com/jinyuan/1432752,如需转载请自行联系原作者




相关文章
|
22天前
|
开发框架 前端开发 .NET
ASP.NET CORE 3.1 MVC“指定的网络名不再可用\企图在不存在的网络连接上进行操作”的问题解决过程
ASP.NET CORE 3.1 MVC“指定的网络名不再可用\企图在不存在的网络连接上进行操作”的问题解决过程
76 0
|
22天前
|
开发框架 前端开发 JavaScript
JavaScript云LIS系统源码ASP.NET CORE 3.1 MVC + SQLserver + Redis医院实验室信息系统源码 医院云LIS系统源码
实验室信息系统(Laboratory Information System,缩写LIS)是一类用来处理实验室过程信息的软件,云LIS系统围绕临床,云LIS系统将与云HIS系统建立起高度的业务整合,以体现“以病人为中心”的设计理念,优化就诊流程,方便患者就医。
29 0
|
22天前
|
开发框架 前端开发 .NET
进入ASP .net mvc的世界
进入ASP .net mvc的世界
35 0
|
22天前
|
开发框架 前端开发 .NET
C# .NET面试系列六:ASP.NET MVC
<h2>ASP.NET MVC #### 1. MVC 中的 TempData\ViewBag\ViewData 区别? 在ASP.NET MVC中,TempData、ViewBag 和 ViewData 都是用于在控制器和视图之间传递数据的机制,但它们有一些区别。 <b>TempData:</b> 1、生命周期 ```c# TempData 的生命周期是短暂的,数据只在当前请求和下一次请求之间有效。一旦数据被读取,它就会被标记为已读,下一次请求时就会被清除。 ``` 2、用途 ```c# 主要用于在两个动作之间传递数据,例如在一个动作中设置 TempData,然后在重定向到另
129 5
|
7月前
|
开发框架 自然语言处理 前端开发
基于ASP.NET MVC开发的、开源的个人博客系统
基于ASP.NET MVC开发的、开源的个人博客系统
54 0
|
前端开发 .NET 数据安全/隐私保护
|
前端开发 .NET 开发框架
|
Web App开发 前端开发 数据安全/隐私保护
|
数据安全/隐私保护 容器