[Web API] Web API 2 深入系列(7) Model绑定(下)
目录
ModelBinder
ModelBinderProvider
不同类型的Model绑定
- 简单类型
- 复杂类型
- 其他类型
ModelBinder
ModelBinder是Model绑定的核心.
public interface IModelBinder
{
//绑定Model方法,返回绑定是否成功
bool BindModel(HttpActionContext actionContext, ModelBindingContext bindingContext);
}
ModelBindingContext
public class ModelBindingContext
{
//数据源
public IValueProvider ValueProvider { get; set; }
//最终创建的对象 绑定过程就是创建Model
public object Model { get; set; }
//参数名称
public string ModelName { get; set; }
//参数类型
public Type ModelType { get; }
//参数元数据
public ModelMetadata ModelMetadata { get; set; }
//属性元数据
public IDictionary<string, ModelMetadata> PropertyMetadata { get; }
//存储绑定结果(包括错误信息,ValueProviderResult),该值引用自ApiController的ModelState
public ModelStateDictionary ModelState { get; set; }
public bool FallbackToEmptyPrefix { get; set; }
}
当ModelBinder特性的Name(为null),FallbackToEmptyPrefix为True.
FallbackToEmptyPrefix为False时,则必须数据源有前缀才能绑定上.
Web API定义了一系列的ModelBinder,这里先介绍
public class CompositeModelBinder : IModelBinder
{
//IModelBinder 集合
public CompositeModelBinder(params IModelBinder[] binders)
//使用内部ModelBinder进行绑定Model(默认遍历一次,如果FallbackToEmptyPrefix为True,则会有2次遍历机会)
public virtual bool BindModel(HttpActionContext actionContext, ModelBindingContext bindingContext)
}
ModelBinderProvider
Web API通过ModelBinderProvider创建ModelBinder
public abstract class ModelBinderProvider
{
public abstract IModelBinder GetBinder(HttpConfiguration configuration, Type modelType);
}
Web API中默认注册了一系列的ModelBinderProvider
this.SetMultiple<ModelBinderProvider>(new ModelBinderProvider[8]
{
(ModelBinderProvider) new TypeConverterModelBinderProvider(),
(ModelBinderProvider) new TypeMatchModelBinderProvider(),
(ModelBinderProvider) new KeyValuePairModelBinderProvider(),
(ModelBinderProvider) new ComplexModelDtoModelBinderProvider(),
(ModelBinderProvider) new ArrayModelBinderProvider(),
(ModelBinderProvider) new DictionaryModelBinderProvider(),
(ModelBinderProvider) new CollectionModelBinderProvider(),
(ModelBinderProvider) new MutableObjectModelBinderProvider()
});
对应的我们先介绍一下
//同样都是组装一批ModelBinderProvider
public sealed class CompositeModelBinderProvider : ModelBinderProvider
{
public CompositeModelBinderProvider(IEnumerable<ModelBinderProvider> providers)
public override IModelBinder GetBinder(HttpConfiguration configuration, Type modelType)
}
ModelBinderAttribute除了通过Name设置FallbackToEmptyPrefix,还有个更重要的属性BinderType
public class ModelBinderAttribute : ParameterBindingAttribute
{
public string Name { get; set; }
//用来指定ModelBinder 或 ModelBinderProvider
public Type BinderType { get; set; }
}
不同类型的Model绑定
不同的数据类型,有不同的数据结构.
所以针对他们的绑定机制也是不同的.
简单类型
TypeConverterModelBinder
public sealed class TypeConverterModelBinder : IModelBinder
{
public bool BindModel(HttpActionContext actionContext, ModelBindingContext bindingContext)
{
ValueProviderResult valueProviderResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
bindingContext.ModelState.SetModelValue(bindingContext.ModelName, valueProviderResult);
model = valueProviderResult.ConvertTo(bindingContext.ModelType);
bindingContext.Model = model;
return true;
}
}
复杂类型
在介绍复杂类型的Bind前,先介绍一下下面2个类型.
ComplexModelDto包含复杂类型的元数据和绑定结果
public class ComplexModelDto
{
public ComplexModelDto(ModelMetadata modelMetadata, IEnumerable<ModelMetadata> propertyMetadata)
public ModelMetadata ModelMetadata { get; private set; }
public Collection<ModelMetadata> PropertyMetadata { get; private set; }
//key 为属性的元数据,value 为绑定结果
public IDictionary<ModelMetadata, ComplexModelDtoResult> Results { get; private set; }
}
ComplexModelDtoResult
public sealed class ComplexModelDtoResult
{
//绑定结果值
public object Model { get; private set; }
//验证信息
public ModelValidationNode ValidationNode { get; private set; }
}
复杂类型的绑定由 MutableObjectModelBinder 和 ComplexModelDtoModelBinder共同完成.
而上面2个类型,实际就是用来在2个ModelBinder间传递的对象
public class MutableObjectModelBinder : IModelBinder
{
public virtual bool BindModel(HttpActionContext actionContext, ModelBindingContext bindingContext)
{
//类型筛选
if (!bindingContext.ValueProvider.ContainsPrefix(bindingContext.ModelName) || !MutableObjectModelBinder.CanBindType(bindingContext.ModelType))
return false;
//1. 创建空对象
bindingContext.ModelMetadata.Model = Activator.CreateInstance(bindingContext.ModelType);
//2. 创建ComplexModelDto对象
ComplexModelDto complexModelDto = new ComplexModelDto(bindingContext.ModelMetadata,bindingContext.PropertyMetadata);
//3. 进入绑定流程
this.ProcessDto(actionContext, bindingContext, complexModelDto);
return true;
}
internal void ProcessDto(HttpActionContext actionContext, ModelBindingContext bindingContext, ComplexModelDto dto)
{
//创建子ModelBindingContext
var subContext = new ModelBindingContext(bindingContext)
{
ModelName = bindingContext.ModelName,
ModelMetadata = GetMetadata(typeof(ComplexModelDto))
};
//调用ComplexModelDtoModelBinder 对ComplexModelDto进行绑定
actionContext.Bind(subContext);
//对复杂类型的属性进行绑定
foreach (var result in (IEnumerable<KeyValuePair<ModelMetadata, ComplexModelDtoResult>>) dto.Results)
{
ModelMetadata key = result.Key;
ComplexModelDtoResult dtoResult = result.Value;
if (dtoResult != null)
{
var property = bindingContext.ModelType.GetProperty(key.PropertyName);
this.SetProperty(actionContext, bindingContext, key, dtoResult,property);
}
}
}
}
ComplexModelDtoModelBinder则将所有属性再通过调度其他的ModelBinder进行绑定.并将结果保存在ComplexModelDto的Results属性中.
其他类型
Web API还提供了其他常用的数据类型 ModelBinder
CollectionModelBinder来实现 集合 类型(指的集合是实现了IEnumerable接口的类型)
ArrayModelBinder来实现 数组 类型
DictionaryModelBinder来实现 字典 类型
通过对应的ModelBinderProvider可以知道对应的ModelBinder 能实现哪种类型的绑定
备注
文章中的代码并非完整WebAPI代码,一般是经过自己精简后的.
本篇内容使用MarkDown语法编辑
[Web API] Web API 2 深入系列(7) Model绑定(下)的更多相关文章
- [Web API] Web API 2 深入系列(6) Model绑定(上)
目录 解决什么问题 Model元数据解析 复杂类型 ValueProvider ValueProviderFactory 解决什么问题 Model: Action方法上的参数 Model绑定: 对Ac ...
- ASP.NET Web API - ASP.NET MVC 4 系列
Web API 项目是 Windows 通信接口(Windows Communication Foundation,WCF)团队及其用户激情下的产物,他们想与 HTTP 深度整合.WCF ...
- 如何用Baas快速在腾讯云上开发小程序-系列1:搭建API & WEB WebSocket 服务器
版权声明:本文由贺嘉 原创文章,转载请注明出处: 文章原文链接:https://www.qcloud.com/community/article/221059001487422606 来源:腾云阁 h ...
- Java web与web gis学习笔记(二)——百度地图API调用
系列链接: Java web与web gis学习笔记(一)--Tomcat环境搭建 Java web与web gis学习笔记(二)--百度地图API调用 JavaWeb和WebGIS学习笔记(三)-- ...
- HTML5权威指南--Web Storage,本地数据库,本地缓存API,Web Sockets API,Geolocation API(简要学习笔记二)
1.Web Storage HTML5除了Canvas元素之外,还有一个非常重要的功能那就是客户端本地保存数据的Web Storage功能. 以前都是用cookies保存用户名等简单信息. 但是c ...
- 初试ASP.NET Web API/MVC API(附Demo)
写在前面 HTTP RESTful 创建Web API 调用Web API 运行截图及Demo下载 ASP.NET Web API是一个框架,可以很容易构建达成了广泛的HTTP服务客户端,包括浏览 ...
- 我所理解的RESTful Web API [Web标准篇]
REST不是一个标准,而是一种软件应用架构风格.基于SOAP的Web服务采用RPC架构,如果说RPC是一种面向操作的架构风格,而REST则是一种面向资源的架构风格.REST是目前业界更为推崇的构建新一 ...
- 重构Web Api程序(Api Controller和Entity)续篇
昨天有写总结<重构Web Api程序(Api Controller和Entity)>http://www.cnblogs.com/insus/p/4350111.html,把一些数据交换的 ...
- web api写api接口时返回
web api写api接口时默认返回的是把你的对象序列化后以XML形式返回,那么怎样才能让其返回为json呢,下面就介绍两种方法: 方法一:(改配置法) 找到Global.asax文件,在Applic ...
随机推荐
- maven 本地仓库和远程仓库
在Maven中,任何一个依赖.插件或者项目构建的输出,都可以称之为构件. Maven在某个统一的位置存储所有项目的共享的构件,这个统一的位置,我们就称之为仓库.(仓库就是存放依赖和插件的地方) 任何的 ...
- web端限时活动逻辑处理总结
由于要在web端做一个限时活动的功能,功能大致为:一个小时内可以报名参加活动,然后给予报名者奖品,先到先得.用到一些处理逻辑做下总结,以前没有做过类似的东西,都是自己先体验其他网站的报名方式,然后再摸 ...
- 使用Junit等工具进行单元测试
一.类的定义: 类是同一事物的总称,类是封装对象的属性和行为的载体,反过来说具有相同属性和行为的一类实体被称为类. 二.Junit工具的使用: 1.首先新建一个项目叫JUnit_Test,我们编写一个 ...
- linux下git以及github的连接与使用
简单理解 Git 的思想和基本的工作原理,能够更好的进一步和使用Git.在开始学习Git 的时候,最好不要把Git的各种概念和其他的版本控制系统诸如 Subversion 等相比,否则容易混淆每个操作 ...
- ASP.NET Core 数据保护(Data Protection)【中】
前言 上篇主要是对 ASP.NET Core 的 Data Protection 做了一个简单的介绍,本篇主要是介绍一下API及使用方法. API 接口 ASP.NET Core Data Prote ...
- Code First开发系列之数据库迁移
返回<8天掌握EF的Code First开发>总目录 本篇目录 开启并运行迁移 使用迁移API 应用迁移 给已存在的数据库添加迁移 EF的其他功能 本章小结 自我测试 本系列的源码本人已托 ...
- 关于大型网站技术演进的思考(二十一)--网站静态化处理—web前端优化—下【终篇】(13)
本篇继续web前端优化的讨论,开始我先讲个我所知道的一个故事,有家大型的企业顺应时代发展的潮流开始投身于互联网行业了,它们为此专门设立了一个事业部,不过该企业把这个事业部里的人事成本,系统运维成本特别 ...
- Worktile协同特色之一:无处不在的关注
团队沟通中常见问题 在回答这个问题之前,我们不妨先来思考一下,团队成员之间互相配合沟通的几个问题:1. 任务的执行者在完成这个任务时,如何通知到此任务相关联的其他成员,比如该任务的后续任务执行者?2. ...
- 《Spark快速大数据分析》—— 第三章 RDD编程
- kettle资源库配置
资源库的作用:资源库是用来保存操作步骤和相关的日志,转换,JOB 等信息.用户通过图形界面创建的的转换任务可以保存在资源库中.资源库可以是各种常见的数据库,用户通过用户名/ 密码来访问资源库中的资源, ...