ASP.NET Web API Model-ParameterBinding

前言

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

Model-ParameterBinding(对象篇)

在ASP.NET Web API中ParameterBinding代表着参数绑定并且在这其中涉及了几种绑定的方式,然而ParaMeterBinding并不是单独执行的,就好比一个控制器方法中有可能会有多个参数一样,所以我们就先来看一下ActionBinding的相关对象,对于这些对象的生成的环境以及过程我们在后面的篇幅中会有讲解。

HttpActionBinding

代码1-1

namespace System.Web.Http.Controllers
{
public class HttpActionBinding
{
public HttpActionBinding();
public HttpActionBinding(HttpActionDescriptor actionDescriptor, HttpParameterBinding[] bindings);
public HttpActionDescriptor ActionDescriptor { get; set; }
public HttpParameterBinding[] ParameterBindings { get; set; } public virtual Task ExecuteBindingAsync(HttpActionContext actionContext, CancellationToken cancellationToken);
}
}

代码1-1中对于HttpActionBinding类型的定义一目了然,看HttpActionBinding类型的重载构造函数中有HttpActionDescriptor类型、HttpParameterBinding类型的数组类型作为参数,HttpActionDescriptor类型作为控制器方法描述类型大家已经很熟悉了吧,这个类型中包含着控制器方法的元数据信息,而后者HttpParameterBinding类型则是表示着参数绑定对象,其实在Model绑定中每个参数的绑定都是通过ParameterBinding来绑定的,所以这里的执行过程我们暂时不去深入了解,就是单纯的了解一下相关的对象模型。

HttpParameterBinding

代码1-2

namespace System.Web.Http.Controllers
{
public abstract class HttpParameterBinding
{
protected HttpParameterBinding(HttpParameterDescriptor descriptor); public HttpParameterDescriptor Descriptor { get; }
public virtual string ErrorMessage { get; }
public bool IsValid { get; }
public virtual bool WillReadBody { get; } public abstract Task ExecuteBindingAsync(ModelMetadataProvider metadataProvider, HttpActionContext actionContext, CancellationToken cancellationToken);
protected object GetValue(HttpActionContext actionContext);
protected void SetValue(HttpActionContext actionContext, object value);
}
}

在代码1-2中我们看到HttpParameterBinding类型的定义,可以看到HttpParameterBinding是抽象类型,并且实现绑定的方法ExecuteBindingAsync()也是抽象的,这也是为了在不同的环境和情况相爱采取不同的绑定机制做好铺垫就是多态啦,这个我们后面会说,我们还是先看下HttpParameterBinding类型的内部定义,首先我们看到的是构造函数中的参数类型,HttpParameterDescriptor类型,又是一个对象描述类型,这次的描述对象则是控制其方法中的某个参数,而HttpParameterBinding对象实例的生成则是根据HttpParameterDescriptor对象实例而来,这个后续的篇幅中会有讲解。ErrorMessage属性表示在ParameterBinding绑定的过程中出现的错误信息,而IsValid属性表示绑定是否可以完成的依据就是判断ErrorMessage属性是否为Null,WillReadBody属性表示ParameterBinding对象是否读取Http消息正文内容作为参数绑定的数据源,这个稍后给大家看的示例中就有,一看便知。GetValue()和SetValue()方法就是向当前HttpActionContext中获取对应的参数值和设置参数对应值。

ModelBinderParameterBinding

代码1-3

namespace System.Web.Http.ModelBinding
{
public class ModelBinderParameterBinding : HttpParameterBinding, IValueProviderParameterBinding
{
public ModelBinderParameterBinding(HttpParameterDescriptor descriptor, IModelBinder modelBinder, IEnumerable<System.Web.Http.ValueProviders.ValueProviderFactory> valueProviderFactories); public IModelBinder Binder { get; }
public IEnumerable<System.Web.Http.ValueProviders.ValueProviderFactory> ValueProviderFactories { get; } public override Task ExecuteBindingAsync(ModelMetadataProvider metadataProvider, HttpActionContext actionContext, CancellationToken cancellationToken);
}
}

代码1-3表示的是ModelBinderParameterBinding类型,这个类型代表的绑定方式(绑定的数据来源)是通过IModelBinder来获取的,也就正如代码1-3中我们看到的构造函数一样,其中有IModelBinder和ValueProviderFactory类型的集合,这些就是数据绑定的数据源。Binder属性和ValueProviderFactories属性也就是构造函数传入的两个类型值。对于绑定的细节这里就不说多了。

FormatterParameterBinding

代码1-4

namespace System.Web.Http.ModelBinding
{
public class FormatterParameterBinding : HttpParameterBinding
{
public FormatterParameterBinding(HttpParameterDescriptor descriptor, IEnumerable<MediaTypeFormatter> formatters, IBodyModelValidator bodyModelValidator); public IBodyModelValidator BodyModelValidator { get; set; }
public override string ErrorMessage { get; }
public IEnumerable<MediaTypeFormatter> Formatters { get; set; }
public override bool WillReadBody { get; } public override Task ExecuteBindingAsync(ModelMetadataProvider metadataProvider, HttpActionContext actionContext, CancellationToken cancellationToken);
public virtual Task<object> ReadContentAsync(HttpRequestMessage request, Type type, IEnumerable<MediaTypeFormatter> formatters, IFormatterLogger formatterLogger);
}
}

代码1-4中所示的FormatterParameterBinding类型是通过哪种方式来获取绑定数据源的呢?大家可以看到WillReadBody属性在这个类型中被重写了,原来在HttpParameterBinding类型中默认为false的是不会对Http请求的正文内容进行读写的,而这里在FormatterParameterBinding类型中,已然的重写了,说明在这个类型中我们所能用到的绑定数据源就是从Http请求的正文内容来读取了,然而Http请求的正文内容并不是直接放在那里供我们读取的,而是在客户端发送前就已经被指定的序列化器序列化了。

那么我们在服务器端就要反序列化才能获取到值,这里在代码1-4中我们看到构造函数中可以看到和代码1-3一样都是具有一个HttpParameterDescriptor类型的参数对象,而后则是一个MediaTypeFormatter类型的集合对象,最后是进行Model验证的对象,这个后续再说。

现在我们就来看看第二个参数类型中的MediaTypeFormatter类型。

MediaTypeFormatter

代码1-5

namespace System.Net.Http.Formatting
{
public abstract class MediaTypeFormatter
{
protected MediaTypeFormatter();
public abstract bool CanReadType(Type type);
public abstract bool CanWriteType(Type type);
public virtual Task<object> ReadFromStreamAsync(Type type, Stream readStream, HttpContent content, IFormatterLogger formatterLogger);
public virtual Task WriteToStreamAsync(Type type, object value, Stream writeStream, HttpContent content, TransportContext transportContext);
}
}

在代码1-5中所示的MediaTypeFormatter类型是被删减过的一部分,所剩4个方法中两个是抽象方法两个是虚方法,先看两个抽象方法的定义,CanReadType()方法表示的是根据指定的参数类型从当前的Http请求正文中能否读取到改类型的值,简单来说就是能否把正文内容反序列化为指定的参数类型,同理CanWriterType()是对响应正文进行操作判断。而ReadFromStreamAsync()方法和WriteToStreamAsync()方法则是对Http请求正文内容和Http响应正文内容进行实际操作的两个方法。

对于MediaTypeFormatter类型的实现类型比如说针对Json格式的JsonMediaTypeFormatter和针对Xml格式的XmlMediaTypeFormatter.

我们看一下JsonMediaTypeFormatter类型的简单示例,大家就会知道是怎么回事了。

首先我们在服务器端的控制器中定义一个接收Post请求的方法,

代码1-6

        [CustomControllerActionAuthorizationFilter]
public void Post(Product product)
{
products.Add(product);
}

为了方便演示在其控制其方法上加了个授权过滤器,然后我们对Post请求的处理使用JsonMediaTypeFormatter类型进行反序列化的操作将在CustomControllerActionAuthorizationFilter过滤器类型中进行。

代码1-7

public Task<System.Net.Http.HttpResponseMessage> ExecuteAuthorizationFilterAsync(System.Web.Http.Controllers.HttpActionContext actionContext, System.Threading.CancellationToken cancellationToken, Func<Task<System.Net.Http.HttpResponseMessage>> continuation)
{
Console.WriteLine(actionContext.Request.Content.Headers.ContentType.MediaType); IEnumerable<MediaTypeFormatter> formatters = new MediaTypeFormatter[]
{
new JsonMediaTypeFormatter()
};
Product product = actionContext.Request.Content.ReadAsAsync<Common.Product>(formatters).Result;
Console.WriteLine(product.ProductID);
Console.WriteLine(product.ProductName);
Console.WriteLine(product.ProductCategory);
return continuation();
}

在代码1-7中,在请求到达控制器方法之前会先经过授权过滤器,在这其中首先我们是先向服务器端的控制器输出了当前请求的格式类型,然后就对当前请求的正文内容使用JsonMediaTypeFormatter类型进行反序列化操作。

我们再看下客户端使用HttpClient类型进行模拟Post请求,

代码1-8

            HttpClient httpClient = new HttpClient();
Product product = new Product()
{
ProductID = "",
ProductName = "旺仔牛奶",
ProductCategory = "食品类"
};
await httpClient.PostAsJsonAsync<Product>("http://localhost/selfhost/api/product", product);

最后结果如图1.

图1

看到这里想必大家也知道对于XmlMediaTypeFormatter的使用方式是怎样的了。

还有一种MediaTypeFormatter类型FormUrlEncodedMediaTypeFormatter类型,FormUrlEncodedMediaTypeFormatter类型表示的是在Http Post请求中表单提交的数据所用格式器,我们看一下FormUrlEncodedMediaTypeFormatter类型中CanReadType()方法的实现。

代码1-9

    public override bool CanReadType(Type type)
{
if (type == null)
{
throw Error.ArgumentNull("type");
}
if (!(type == typeof(FormDataCollection)))
{
return FormattingUtilities.IsJTokenType(type);
}
return true;
}

在代码1-9我们可以看到FormDataCollection类型实际就是IEnumerable<KeyValuePair<string, string>>类型的对象,在表单提交后的请求Url中大家也都可以看到是是key=value的形式,所以这里就是这种格式的。对于这个格式器的示例会在后面的篇幅给大家做演示讲解。

HttpRequestParameterBinding

最后我们再看一个RequestParameterBinding对象。

代码1-10

    public class HttpRequestParameterBinding : HttpParameterBinding
{
// Methods
public HttpRequestParameterBinding(HttpParameterDescriptor descriptor)
: base(descriptor)
{
} public override Task ExecuteBindingAsync(ModelMetadataProvider metadataProvider, HttpActionContext actionContext, CancellationToken cancellationToken)
{
string parameterName = base.Descriptor.ParameterName;
HttpRequestMessage request = actionContext.ControllerContext.Request;
actionContext.ActionArguments.Add(parameterName, request);
return TaskHelpers.Completed();
}
}

在代码1-10中我们看到再ExecuteBindingAsync()方法的实现中,是直接获取到参数名称和当前的请求对象,然后添加到控制其方法执行上下文的ActionArguments属性中,在之前的篇幅中也说过这个属性用来存放方法对应参数值(Model绑定后的值)。

本篇关于ParameterBinding的对象介绍就到这里,都是零零散散的不过在后面的篇幅中都会有示例介绍说明的。

作者:金源

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

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

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

  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-ActionBinding

    ASP.NET Web API Model-ActionBinding 前言 前面的几个篇幅把Model部分的知识点划分成一个个的模块来讲解,而在控制器执行过程中分为好多个过程,对于控制器执行过程(一 ...

  4. ASP.NET Web API Model-ModelMetadata

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

  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 过滤器创建、执行过程(二)

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

  9. ASP.NET Web API路由系统:路由系统的几个核心类型

    虽然ASP.NET Web API框架采用与ASP.NET MVC框架类似的管道式设计,但是ASP.NET Web API管道的核心部分(定义在程序集System.Web.Http.dll中)已经移除 ...

随机推荐

  1. Storm如何保证可靠的消息处理

    作者:Jack47 PS:如果喜欢我写的文章,欢迎关注我的微信公众账号程序员杰克,两边的文章会同步,也可以添加我的RSS订阅源. 本文主要翻译自Storm官方文档Guaranteeing messag ...

  2. php报错 ----> Call to undefined function imagecreatetruecolor()

    刚才在写验证码的时候,发现报错,然后排查分析了一下,原来是所用的php版本(PHP/5.3.13)没有开启此扩展功能. 进入php.ini 找到extension=php_gd2.dll ,将其前面的 ...

  3. css元素水平居中和垂直居中的方式

    关于居中的问题,一直处于疑惑不解的状态,知道的几种方法好像也不是每一次都会起到作用,所以更加迷惑.主要是不清楚该 在什么情况下采用哪种解决方法,所以,整理了一些方法,梳理一下思路,做一个总结. 1. ...

  4. [算法]——归并排序(Merge Sort)

    归并排序(Merge Sort)与快速排序思想类似:将待排序数据分成两部分,继续将两个子部分进行递归的归并排序:然后将已经有序的两个子部分进行合并,最终完成排序.其时间复杂度与快速排序均为O(nlog ...

  5. Flyweight(享元模式)

    import java.util.Hashtable; /** * 享元模式 * @author TMAC-J * 享元模式一般和工厂模式一起使用,但此处为了更好说明,只用享元模式 * 定义:享元模式 ...

  6. 文档对象模型DOM通俗讲解

    转自:http://www.jb51.net/article/42671.htm 在开始之前先说一点,DOM是非常容易理解的,但是大家说的太官方,让人很是难于理解,我们就用非常简单的语言翻译一遍.加深 ...

  7. 去IOE的一点反对意见以及其他

    某天在机场听见两老板在聊天,说到他们目前销售的报表老跟不上的问题,说要请一个人,专门合并和分析一些发过来的excel表格,我真想冲上去说,老板,你需要的是一个信息处理的系统,你需要咨询么.回来一直耿耿 ...

  8. 【干货分享】流程DEMO-制度发文和干部任免

    流程名: 制度发文和干部任免  业务描述: 当员工在该出勤的工作日出勤但漏打卡时,于一周内填写补打卡申请.  流程相关文件: 流程包.xml  流程说明: 直接导入流程包文件,即可使用本流程  表单: ...

  9. Atitit.cto 与技术总监的区别

    Atitit.cto 与技术总监的区别 1. 核心区别1 2. Cto主要职责1 3. 如何提升到cto1 4. CTO五种基本的必备素质:2 5. 2 1. 核心区别 技术总监(Chief Tech ...

  10. GCC学习(1)之MinGW使用

    GCC学习(1)之MinGW使用 因为后续打算分享一些有关GCC的使用心得的文章,就把此篇当作一个小预热,依此来了解下使用GNU工具链(gcc.gdb.make等)在脱离IDE的情况下如何开发以及涉及 ...