ASP.NET Web API Model-ActionBinding

前言

前面的几个篇幅把Model部分的知识点划分成一个个的模块来讲解,而在控制器执行过程中分为好多个过程,对于控制器执行过程(一)主要讲解了过滤器以及在后面的过滤器篇幅中也有讲到,而在过滤器之中还有一些执行过程,也就是在授权过滤器执行完毕后,行为过滤器执行之前,我们要做的就是Model绑定,面前也都说了之前对Model的知识点模块都讲解的差不多了,今天这个篇幅我们就来看一下这些零散知识点的源头,也就是Model绑定的入口点。

Model-ActionBinding

HttpActionBinding的由来

我们通过前面几篇的了解都知道在ASP.NET Web API框架中进入整个Model绑定的入口点就是在HttpActionBinding类型中,对于这个类型前面的篇幅也介绍过,它里面封装了ParameterBinding数组,这些ParameterBinding就是控制器方法中每个参数执行Model绑定的对象了,既然我们知道HttpActionBinding类型中有着许多ParameterBinding类型的对象实例,那么我们就要看看HttpActionBinding类型是怎么生成的。

示例代码1-1

this.SetSingle<IActionValueBinder>(new DefaultActionValueBinder());

首先我们看到示例代码1-1中可以看到在HttpConfiguration类型的服务容器中,默认注册为IActionValueBinder类型服务的是DefaultActionValueBinder类型。

示例代码1-2

namespace System.Web.Http.ModelBinding
{
public class DefaultActionValueBinder : IActionValueBinder
{
public DefaultActionValueBinder(); public virtual HttpActionBinding GetBinding(HttpActionDescriptor actionDescriptor);
protected virtual HttpParameterBinding GetParameterBinding(HttpParameterDescriptor parameter);
}
}

代码1-2中所示的是DefaultActionValueBinder类型的定义,其中的这两个方法很重要,第一个GetBinding()方法是用以框架内部来进行调用,根据HttpActionDescriptor控制器方法描述类型对象获取到我们所需的HttpActionBinding,而其内部实现则是调用下面的GetParameterBinding()方法,利用HttpActionDescriptor对象获取到HttpParameterDescriptor集合后,然后遍历的去调用GetParameterBinding()方法,从而能够获取到HttpParameterBinding对象实例,最后生成HttpActionBinding对象实例,从设计角度来看这个DefaultActionValueBinder类型中的两个方法GetBinding()和GetParameterBinding()方法都是采用了template method模式,这种模式在框架设计中很常见。

HttpParameterBinding的由来

下面我们就要来说说GetParameterBinding()方法的细节实现了因为关乎着使用哪种方式来进行绑定。也就是根据HttpParameterDescriptor类型实例怎么去创建HttpParameterBinding的。

示例代码1-3

    protected virtual HttpParameterBinding GetParameterBinding(HttpParameterDescriptor parameter)
{
ParameterBindingAttribute parameterBinderAttribute = parameter.ParameterBinderAttribute;
if (parameterBinderAttribute == null)
{
ParameterBindingRulesCollection parameterBindingRules = parameter.Configuration.ParameterBindingRules;
if (parameterBindingRules != null)
{
HttpParameterBinding binding = parameterBindingRules.LookupBinding(parameter);
if (binding != null)
{
return binding;
}
}
Type parameterType = parameter.ParameterType;
if (TypeHelper.IsSimpleUnderlyingType(parameterType) || TypeHelper.HasStringConverter(parameterType))
{
return parameter.BindWithAttribute(new FromUriAttribute());
}
parameterBinderAttribute = new FromBodyAttribute();
}
return parameterBinderAttribute.GetBinding(parameter);
}

代码1-3就是具体的实现了,那我们就就来看一下其中的过程以及会涉及到的类型。

首先会根据参数HttpParameterDescriptor类型实例获取到在这个控制器方法参数上使用了ParameterBindingAttribute标识,并且获取ParameterBindingAttribute类型实例。我们暂且就来看一下ParameterBindingAttribute类型定义。

示例代码1-4

    [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Class, Inherited = true, AllowMultiple = false)]
public abstract class ParameterBindingAttribute : Attribute
{
// Methods
protected ParameterBindingAttribute();
public abstract HttpParameterBinding GetBinding(HttpParameterDescriptor parameter);
}

从代码1-4可以看出,这个ParameterBindingAttribute类型适用于类型以及参数,也就是说我们选择绑定的方式可以在Model类型定义的时候标识这个特性,也可以在定义控制器方法的时候适当的给参数这个特性标识。

然而在这个类型中为什么会有GetBinding()方法呢?因为这个类型是抽象类型,也就是采用了上面所说过的template method模式,而在子类实现中,根据自身适应的情况生成响应的HttpParameterBinding类型。看下如下的图表示相关的对象模型。

图1

上面图1中涉及到的每个类型大家可以去看前面的篇幅,篇幅中有遗漏的就麻烦大家自己多动一下手去看看吧。

HttpParameterBinding的选择机制

接着代码1-3的思绪,在我们获取到了ParameterBindingAttribute之后,并不知道这个控制器方法中的参数是否标识有ParameterBindingAttribute,或者是参数类型上是否有标识。这个时候假使是有的话,可以看到代码1-3中的最后一句代码,直接使用获取到的ParameterBindingAttribute类型进行调用GetBinding()方法,也就是在上一小节中图1所示的那样。

然而还有一种情况,就是我们在定义控制器方法的时候参数没有明确的标识我们要使用某种绑定机制,或者是在定义Model的时候没有明确的表示,这个时候框架则会从定义好的规则集合中根据当前控制其方法参数的描述类型来获取对应的ParameterBinding类型实例。如下的示例代码定义了规则集合的定义。

示例代码1-5

    internal static ParameterBindingRulesCollection GetDefaultParameterBinders()
{
ParameterBindingRulesCollection ruless = new ParameterBindingRulesCollection();
ruless.Add(typeof(CancellationToken), parameter => new CancellationTokenParameterBinding(parameter));
ruless.Add(typeof(HttpRequestMessage), parameter => new HttpRequestParameterBinding(parameter));
ruless.Add(delegate (HttpParameterDescriptor parameter) {
if (!typeof(HttpContent).IsAssignableFrom(parameter.ParameterType))
{
return null;
}
return parameter.BindAsError(Error.Format(SRResources.ParameterBindingIllegalType, new object[] { parameter.ParameterType.Name, parameter.ParameterName }));
});
return ruless;
}

代码1-5中所表示的就是规则定义,意思就是在我们使用HttpParameterDescriptor类型实例来从集合中想获取ParameterBinding的时候,ParameterBindingRulesCollection类型会把我们的HttpParameterDescriptor类型实例中的ParameterType取出来和之前定义的每一项规则的类型进行比对,类型吻合了就会随之调用对应的委托类型进行ParameterBinding生成。从代码1-5中我们可以看到的是规则中只有CancellationToken类型和HttpRequestMessage类型,假使这个时候我们的控制其方法参数类型是自定义的复杂类型,这里也都没有定义,这个时候框架会取出HttpParameterDescriptor类型中的ParameterType进行判断,假使是可以转换成string类型的简单类型参数,则会生成一个FromUriAttribute类型作为标识,FromUriAttribute类型继承自ModelBinderAttribute类型。

假使这里的判断没有通过则说明是复杂类型,最后我们再看待代码1-3中的定义最后生成的是FromBodyAttribute标识类型,这个时候请参照图1。

作者:金源

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

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

ASP.NET Web API Model-ActionBinding的更多相关文章

  1. Model Validation in ASP.NET Web API

    Model Validation in ASP.NET Web API 原文:http://www.asp.net/web-api/overview/formats-and-model-binding ...

  2. Asp.Net Web API 2第十五课——Model Validation(模型验证)

    前言 阅读本文之前,您也可以到Asp.Net Web API 2 系列导航进行查看 http://www.cnblogs.com/aehyok/p/3446289.html 本文参考链接文章地址htt ...

  3. ASP.NET Web API Model-ParameterBinding

    ASP.NET Web API Model-ParameterBinding 前言 通过上个篇幅的学习了解Model绑定的基础知识,然而在ASP.NET Web API中Model绑定功能模块并不是被 ...

  4. ASP.NET Web API 过滤器创建、执行过程(二)

    ASP.NET Web API 过滤器创建.执行过程(二) 前言 前面一篇中讲解了过滤器执行之前的创建,通过实现IFilterProvider注册到当前的HttpConfiguration里的服务容器 ...

  5. 在一个空ASP.NET Web项目上创建一个ASP.NET Web API 2.0应用

    由于ASP.NET Web API具有与ASP.NET MVC类似的编程方式,再加上目前市面上专门介绍ASP.NET Web API 的书籍少之又少(我们看到的相关内容往往是某本介绍ASP.NET M ...

  6. ASP.NET Web API Model-ModelBinder

    ASP.NET Web API Model-ModelBinder 前言 本篇中会为大家介绍在ASP.NET Web API中ModelBinder的绑定原理以及涉及到的一些对象模型,还有简单的Mod ...

  7. ASP.NET Web API Model-ValueProvider

    ASP.NET Web API Model-ValueProvider 前言 前面一篇讲解了Model元数据,Model元数据是在Model绑定中很重要的一部分,只是Model绑定中涉及的知识点比较多 ...

  8. ASP.NET Web API Model-ModelMetadata

    ASP.NET Web API Model-ModelMetadata 前言 前面的几个篇幅主要围绕控制器的执行过程,奈何执行过程中包含的知识点太庞大了,只能一部分一部分的去讲解,在上两篇中我们看到在 ...

  9. ASP.NET Web API 控制器执行过程(一)

    ASP.NET Web API 控制器执行过程(一) 前言 前面两篇讲解了控制器的创建过程,只是从框架源码的角度去简单的了解,在控制器创建过后所执行的过程也是尤为重要的,本篇就来简单的说明一下控制器在 ...

随机推荐

  1. js学习笔记:webpack基础入门(一)

    之前听说过webpack,今天想正式的接触一下,先跟着webpack的官方用户指南走: 在这里有: 如何安装webpack 如何使用webpack 如何使用loader 如何使用webpack的开发者 ...

  2. Jexus 5.8.2 正式发布为Asp.Net Core进入生产环境提供平台支持

    Jexus 是一款运行于 Linux 平台,以支持  ASP.NET.PHP 为特色的集高安全性和高性能为一体的 WEB 服务器和反向代理服务器.最新版 5.8.2 已经发布,有如下更新: 1,现在大 ...

  3. 标准产品+定制开发:专注打造企业OA、智慧政务云平台——山东森普软件,交付率最高的技术型软件公司

    一.公司简介山东森普信息技术有限公司(以下简称森普软件)是一家专门致力于移动互联网产品.企业管理软件定制开发的技术型企业.公司总部设在全国五大软件园之一的济南齐鲁软件园.森普SimPro是由Simpl ...

  4. angular实现统一的消息服务

    后台API返回的消息怎么显示更优雅,怎么处理才更简洁?看看这个效果怎么样? 自定义指令和服务实现 自定义指令和服务实现消息自动显示在页面的顶部,3秒之后消失 1. 显示消息 这种显示消息的方式是不是有 ...

  5. 带你实现开发者头条APP(三) 首页实现

    title: 带你实现开发者头条APP(三) 首页实现 tags: 轮播广告,ViewPager切换,圆形图片 grammar_cjkRuby: true --- 一.前言 今天实现开发者头条APP的 ...

  6. [.NET] C# 知识回顾 - Event 事件

    C# 知识回顾 - Event 事件 [博主]反骨仔 [原文]http://www.cnblogs.com/liqingwen/p/6060297.html 序 昨天,通过<C# 知识回顾 - ...

  7. java 利用ManagementFactory获取jvm,os的一些信息--转

    原文地址:http://blog.csdn.net/dream_broken/article/details/49759043 想了解下某个Java项目的运行时jvm的情况,可以使用一些监控工具,比如 ...

  8. Velocity初探小结--Velocity在spring中的配置和使用

    最近正在做的项目前端使用了Velocity进行View层的数据渲染,之前没有接触过,草草过了一遍,就上手开始写,现在又回头细致的看了一遍,做个笔记. velocity是一种基于java的模板引擎技术, ...

  9. 【用户交互】APP没有退出前台但改变系统属性如何实时更新UI?监听系统广播,让用户交互更舒心~

    前日,一小伙伴问我一个问题,说它解决了半天都没解决这个问题,截图如下: 大概楼主理解如下: 如果在应用中有一个判断wifi的开关和一个当前音量大小的seekbar以及一个获取当前电量多少的按钮,想知道 ...

  10. BAT“搅局”B2B市场,CIO们准备好了吗?

    "CIO必须灵活构建其所在企业的IT系统,深入业务,以应对日新月异的数字化业务环境."   BAT军团"搅局"B2B市场,CIO们准备好了吗? 庞大的企业级市场 ...