ASP.NET MVC Model绑定(五)

前言

前面的篇幅对于IValueProvider的获取位置和所处的生成过程做了讲解,本篇将会对IValueProvider的使用做个基础的示例讲解,读完本篇你将会对IValueProvider有个更清晰的印象。

Model绑定

  • IModelBinder、自定义Model绑定器简单实现
  • Model绑定器在MVC框架中的位置
  • MVC中的默认Model绑定器生成过程
  • IModelBinderProvider的简单应用
  • IValueProvider在MVC框架中生成的位置以及过程
  • IValueProvider的应用场景
  • IValueProvider的实现之NameValueCollectionValueProvider

IValueProvider的应用场景

图1

图1中所示的就是本篇所要演示的IValueProvider的简单示例了。这里不对图中的类型做讲解,看下文的示例代码自会知晓。

首先红色方框所示的就是主要流程了,我们先来实现一下:

1.  控制器方法的定义

代码1-1

namespace MvcApplication.Controllers
{
public class ValueProviderCaseController : Controller
{ public ActionResult Index(string ValueProviderCase)
{
ViewBag.value = ValueProviderCase;
return View();
} }
}

代码1-1中很简单的定义了一个Index()方法,并且参数类型(Model类型)为string类型,参数名称(Model名称)为ValueProviderCase,请大家记住这个参数名称后面会用到的。

2.视图呈现端代码

代码1-2

@{
ViewBag.Title = "Index";
} <h2>Index</h2>
<p>@ViewBag.value</p>

代码1-2为视图呈现端代码,这里用了ViewBag动态类型来传值。

从图1中可以看到,在执行控制器方法之前,首先要获取Model绑定器,然后是执行Model绑定器,我们先把获取Model绑定器的部分流程放一放,先来看一下执行Model绑定器的流程。

3.自定义值提供程序的定义

从图1中看到,在执行Model绑定器的流程中,最后是执行的自定义值提供程序MyCustomValueProvider,这里我们先不管其他的,看一下这个类型的定义:

代码1-3

using System.Web.Mvc;

namespace MvcApplication.ValueProvider
{
public class MyCustomValueProvider:IValueProvider
{
public bool ContainsPrefix(string prefix)
{
if (prefix == "ValueProviderCase")
{
return true;
}
return false;
} public ValueProviderResult GetValue(string key)
{
return ContainsPrefix(key)
?new ValueProviderResult( "这是一个值提供程序示例",null,System.Globalization.CultureInfo.InstalledUICulture)
:null;
}
}
}

看到代码1-3中MyCustomValueProvider的定义,小伙伴们莫慌待我慢慢解释,首先MyCustomValueProvider类型实现了IValueProvider接口类型,这个是必须的。对于IValueProvider接口类型的定义我就不放代码了,也就是MyCustomValueProvider类型的的两个方法了。

ContainsPrefix()方法的意思是值提供程序内部判断是否含有指定的前缀,把值提供程序想象成一个数据源,这个数据源中包含了键和值,这个ContainsPrefix()方法就是用来判断指定的键是否存在,如果存在的话GetValue()方法则会返回对应的值(在我们的示例中这里的ContainsPrefix()只是作了一逻辑判断,判断当前控制器方法的参数名称【Model名称】是否为ValueProviderCase)。

而GetValue()方法的意思上面也说到了,就是用来返回指定前缀的值(指定键的值),在我们的示例中只是返回了"这是一个值提供程序示例"。有的朋友可能发现了GetValue()方法的返回类型并不是String类型,而是ValueProviderResult类型,这是MVC框架干的好事,也就是它要我们强制的封装我们的返回值,没办法受制于人封装就封装吧,小伙伴们看一下ValueProviderResult类型的定义:

代码1-4

public class ValueProviderResult
{
protected ValueProviderResult();
public ValueProviderResult(object rawValue, string attemptedValue, CultureInfo culture);
public string AttemptedValue { get; protected set; }
public CultureInfo Culture { get; protected set; }
//
// 摘要:
// 获取或设置值提供程序所提供的原始值。
//
// 返回结果:
// 原始值。
public object RawValue { get; protected set; }
public object ConvertTo(Type type);
public virtual object ConvertTo(Type type, CultureInfo culture);
}

看到代码1-4中的ValueProviderResult类型的构造函数定义和RawValue属性的注释了吧,然后再看一下代码1-3中GetValue()方法的代码定义,一目了然吧。

4.自定义值提供程序工厂定义

切回主要流程,我们在使用Model绑定器中的自定义值提供程序的同时,我们也要回想一下上一个篇幅中所讲的就是自定义值提供程序的由来,自定义值提供程序是由我们自定义值提供程序工厂生成的,然后把这个工厂注册到系统的ValueProviderFactories. Factories中,然后会在Model绑定器执行之前生成ModelBindingContext类型实例的时候从ValueProviderFactories. Factories中获取到自定义值提供程序(MyCustomValueProvider类型)赋值到ModelBindingContext类型实例的属性ValueProvider上(对于这里的过程可以观看上一篇)。

现在我们看一下自定义值提供程序工厂定义,代码1-5.

代码1-5

using System.Web.Mvc;

namespace MvcApplication.ValueProvider
{
public class MyCustomValueProviderFactory:ValueProviderFactory
{
public override IValueProvider GetValueProvider(ControllerContext controllerContext)
{
if (controllerContext.Controller.GetType().Name == "ValueProviderCaseController")
{
return new MyCustomValueProvider();
}
return null;
}
}
}

代码1-5中GetValueProvider()方法被我添加了个逻辑判断,想指示这个工厂只为ValueProviderCaseController控制器服务,这里大家都好理解的就不多说了。

5.自定义Model绑定器

再次回到主要流程,上面说过先看Model绑定器执行部分的,现在来看Model绑定器获取部分流程。不多说直接来看自定义Model绑定器的定义,代码1-6.

代码1-6

namespace MvcApplication.Binders
{
public class ValueProviderModelBinder : IModelBinder
{
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
return bindingContext.ValueProvider.GetValue(bindingContext.ModelName).RawValue;
}
}
}

代码1-6中通过bindingContext中的ValueProvider属性有着对值提供程序的引用,调用了代码1-3中的GetValue()方法,并且把参数名称传递过去进行逻辑判断。最后通过返回值ValueProviderResult类型的RawValue直接返回我们定义的值。

6.将我们自定义的"乱七八糟"类型注册到MVC框架中

通过上面那些类型的定义还是不够的,我们还需要将他们注册到系统中,惯例我们在Global.asax文件中添加,当然也可以在控制器激活的过程中进行注册,针对特定的控制器定制特定的Model绑定器,当然了在实际的项目开发实用不实用不清楚,只是这样感觉Global.asax文件中会“干净”一点。不瞎扯了,来看注册的代码定义1-7.

代码1-7

ModelBinders.Binders.Add(typeof(string), new Binders.ValueProviderModelBinder());
ValueProviderFactories.Factories.Insert(, new ValueProvider.MyCustomValueProviderFactory());

将代码1-7添加到Application_Start()方法中,首先是向系统注册了我们自定义的Model绑定器,然后将自定义的值提供程序工厂添加到系统,这里用了Insert()方法来添加,目的是想让我的这个工厂处在默认的之前在第一个的位置,省的再一个个的去判断浪费时间。也可以用Add()方法,只不过是添加到了尾处。

最后我们看一下结果图:

图2

作者:金源

出处:http://www.cnblogs.com/jin-yuan/

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面

ASP.NET MVC Model绑定(五)的更多相关文章

  1. ASP.NET MVC Model验证(五)

    ASP.NET MVC Model验证(五) 前言 上篇主要讲解ModelValidatorProvider 和ModelValidator两种类型的自定义实现, 然而在MVC框架中还给我们提供了其它 ...

  2. ASP.NET MVC Model元数据(五)

    ASP.NET MVC Model元数据(五) 前言 在上一篇中我们描述了应用于Model上面的各种用于显示控制的特性类,在本篇中将详细的介绍这些特性类的应用,虽然它们跟Model元数据的直接关系并不 ...

  3. ASP.NET MVC Model绑定(六)

    ASP.NET MVC Model绑定(六) 前言 前面的篇幅对于IValueProvider的使用做个基础的示例讲解,但是没并没有对 IValueProvider类型的实现做详细的介绍,然而MVC框 ...

  4. ASP.NET MVC Model绑定(四)

    ASP.NET MVC Model绑定(四) 前言 前面的篇幅对于Model绑定器IModelBinder以及实现类型.Model绑定器提供程序都作了粗略的讲解,可以把Model绑定器想象成一个大的容 ...

  5. ASP.NET MVC Model绑定(三)

    ASP.NET MVC Model绑定(三) 前言 看过前两篇的朋友想必对Model绑定有个大概的了解,然而MVC框架给我们提供了更高的可扩展性的提供程序编程模式,也就是本篇的主题了,会讲解一下Mod ...

  6. ASP.NET MVC Model绑定(二)

    ASP.NET MVC Model绑定(二) 前言 上篇对于Model绑定的简单演示想必大家对Model绑定的使用方式有一点的了解,那大家有没有想过Model绑定器是在什么时候执行的?又或是执行的过程 ...

  7. ASP.NET MVC Model绑定(一)

    ASP.NET MVC Model绑定(一) 前言 ModelMetadata系列的结束了,从本篇开始就进入Model绑定部分了,这个系列阅读过后你会对Model绑定有个比较清楚的了解, 本篇对于Mo ...

  8. ASP.NET MVC Model绑定

    ASP.NET MVC Model绑定(一) 前言 ModelMetadata系列的结束了,从本篇开始就进入Model绑定部分了,这个系列阅读过后你会对Model绑定有个比较清楚的了解, 本篇对于Mo ...

  9. ModelBinder——ASP.NET MVC Model绑定的核心

    ModelBinder——ASP.NET MVC Model绑定的核心 Model的绑定体现在从当前请求提取相应的数据绑定到目标Action方法的参数.通过前面的介绍我们知道Action方法的参数通过 ...

随机推荐

  1. 通过ProGet搭建一个内部的Nuget服务器

    .NET Core项目完全使用Nuget 管理组件之间的依赖关系,Nuget已经成为.NET 生态系统中不可或缺的一个组件,从项目角度,将项目中各种组件的引用统统交给NuGet,添加组件/删除组件/以 ...

  2. 【初学python】使用python调用monkey测试

    目前公司主要开发安卓平台的APP,平时测试经常需要使用monkey测试,所以尝试了下用python调用monkey,代码如下: import os apk = {'j': 'com.***.test1 ...

  3. SQL Server-聚焦查询计划Stream Aggregate VS Hash Match Aggregate(二十)

    前言 之前系列中在查询计划中一直出现Stream Aggregate,当时也只是做了基本了解,对于查询计划中出现的操作,我们都需要去详细研究下,只有这样才能对查询计划执行的每一步操作都了如指掌,所以才 ...

  4. JS判断鼠标进入容器方向的方法和分析window.open新窗口被拦截的问题

    1.鼠标进入容器方向的判定 判断鼠标从哪个方向进入元素容器是一个经常碰到的问题,如何来判断呢?首先想到的是:获取鼠标的位置,然后经过一大堆的if..else逻辑来确定.这样的做法比较繁琐,下面介绍两种 ...

  5. [C#] 回眸 C# 的前世今生 - 见证 C# 6.0 的新语法特性

    回眸 C# 的前世今生 - 见证 C# 6.0 的新语法特性 序 目前最新的版本是 C# 7.0,VS 的最新版本为 Visual Studio 2017 RC,两者都尚未进入正式阶段.C# 6.0 ...

  6. pt-pmp

    pt-pmp有两方面的作用:一是获取进程的堆栈信息,二是对这些堆栈信息进行汇总. 进程的堆栈信息是利用gdb获取的,所以在获取的过程中,会对mysql服务端的性能有一定的影响. 用官方的话说: Thi ...

  7. hadoop2.7之Mapper/reducer源码分析

    一切从示例程序开始: 示例程序 Hadoop2.7 提供的示例程序WordCount.java package org.apache.hadoop.examples; import java.io.I ...

  8. PHP 获取 特定时间范围 类

    目录  前序 用途 功能及事项 使用方法 代码及注释 前序: 总体来说,我更应该是一个 android 移动开发者,而不是一个 phper,如果说只做移动端的 APP ,我也不会学这么多,这 2年来, ...

  9. 由js apply与call方法想到的js数据类型(原始类型和引用类型)

    原文地址:由js apply与call方法想到的js数据类型(原始类型和引用类型) js的call方法与apply方法的区别在于第二个参数的不同,他们都有2个参数,第一个为对象(即需要用对象a继承b, ...

  10. PHP设计模式(六)原型模式(Prototype For PHP)

    原型设计模式: 用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象. 原型设计模式简单的来说,顾名思义, 不去创建新的对象进而保留原型的一种设计模式. 缺点:原型设计模式是的最主要的缺点就 ...