ASP.NET Web API Model-ActionBinding

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/

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

时间: 2024-10-06 01:28:54

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

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

前言 前面一篇中讲解了过滤器执行之前的创建,通过实现IFilterProvider注册到当前的HttpConfiguration里的服务容器中,当然默认的基础服务也是有的,并且根据这些提供程序所获得的的过滤器信息集合进行排序.本篇就会对过滤器在创建完之后所做的一系列操作进行讲解. ASP.NET Web API 过滤器创建.执行过程(二) FilterGrouping过滤器分组类型 FilterGrouping类型是ApiController类型中的私有类型,它的作用就如同它的命名一样,用来对过

ASP.NET Web API Model-ParameterBinding

ASP.NET Web API Model-ParameterBinding 前言 通过上个篇幅的学习了解Model绑定的基础知识,然而在ASP.NET Web API中Model绑定功能模块并不是被直接调用的,而是要通过本篇要介绍的内容ParameterBinding的一系列对象对其进行封装调用,通过本篇的学习之后也会大概的清楚在Web API中绑定会有哪几种方式. Model-ParameterBinding(对象篇) 在ASP.NET Web API中ParameterBinding代表着

ASP.NET Web API基于OData的增删改查,以及处理实体间关系

本篇体验实现ASP.NET Web API基于OData的增删改查,以及处理实体间的关系. 首先是比较典型的一对多关系,Supplier和Product. public class Product { public int Id { get; set; } public string Name { get; set; } public decimal Price { get; set; } public string Category { get; set; } [ForeignKey("Sup

ASP.Net Web API 的参数绑定[翻译]

原文地址:Parameter Binding in ASP.NET Web API 译文如下: 当Web API相应Controller的一个方法时,它必定存在一个设置参数的过程,叫作数据绑定.这篇文章描述了Web API如何绑定参数以及如何自定义绑定过程. 一般情况下,Web API绑定参数符合如下规则: 如果参数为简单类型,Web API 尝试从URI中获取.简单参数类型包含.Net源生类型(int,bool,double...),加上TimeSpan,DateTime,Guid,decim

Asp.Net Web API 2第三课——.NET客户端调用Web API

Asp.Net Web API 导航 Asp.Net Web API第一课——入门http://www.cnblogs.com/aehyok/p/3432158.html Asp.Net Web API第二课——CRUD操作http://www.cnblogs.com/aehyok/p/3434578.html 前言 本教程演示从一个控制台应用程序,使用HttpClient调用Web API.我们也将使用上一个教程中建立的Web API.你可以直接在http://www.cnblogs.com/

开始 ASP.NET Web API 2 之旅

HTTP不仅仅是提供网页而已.它同时也是一个用于公开服务和数据的强大的API平台.HTTP简单.灵活,而且无处不在.你能想到的几乎所有的平台,都会有一个HTTP库,因此HTTP服务可以达到广泛的客户端,包括浏览器.移动设备,和传统的桌面应用程序. ASP.NET Web API是一个用于构建基于.NET Framework 的 Web API 的框架.在本教程中,你将会使用ASP.NET Web API来创建返回一个产品列表的web API. 教程中使用的软件有: Visual Studio 2

ASP.NET Web API 基本操作(CRUD)

上一篇介绍了ASP.NET Web API的基本知识和原理,这一篇我们通过一个更直观的实例,对产品进行CRUD操作(Create/Read/Update/Delete)来继续了解一下它的基本应用. 创建ASP.NET Web API应用程序  在VS中选择创建一个ASP.NET Web Application应用程序,在向导的下一个窗口中选择Web API模板. 创建Model 这里我们在Models文件夹下创建一个简单的Product model类,用来传递数据. 在Models文件夹上点击右

ASP.NET Web API(一):使用初探,GET和POST数据

概述 REST(Representational State Transfer表述性状态转移)而产生的REST API的讨论越来越多,微软在ASP.NET中也添加了Web API的功能. 我们看dudu的文章HttpClient + ASP.NET Web API, WCF之外的另一个选择知道了博客园也开始使用了Web API,且在使用Web API Beta版本的时候遇到了这个问题:痴情意外:ASP.NET WebAPI RC 竟然不支持最常用的json传参. 我们刚好看看Web API的使用

【ASP.NET Web API教程】2.4 创建Web API的帮助页面

参考页面: http://www.yuanjiaocheng.net/CSharp/csharprumenshili.html http://www.yuanjiaocheng.net/entity/mode-first.html http://www.yuanjiaocheng.net/entity/database-first.html http://www.yuanjiaocheng.net/entity/choose-development-approach.html http://ww

Getting Started with ASP.NET Web API 2 (C#)

By Mike Wasson|last updated May 28, 2015 7556 of 8454 people found this helpful Print Download Completed Project HTTP is not just for serving up web pages. It is also a powerful platform for building APIs that expose services and data. HTTP is simple