.NET Core WebApi中实现多态数据绑定
什么是多态数据绑定?
我们都知道在ASP.NET Core WebApi中数据绑定机制(Data Binding)负责绑定请求参数, 通常情况下大部分的数据绑定都能在默认的数据绑定器(Binder)中正常的进行,但是也会出现少数不支持的情况,例如多态数据绑定。所谓的多态数据绑定(polymorphic data binding),即请求参数是子类对象的Json字符串, 而action中定义的是父类类型的变量,默认情况下ASP.NET Core WebApi是不支持多态数据绑定的,会造成数据丢失。
以下图为例
Person类是一个父类,Doctor类和Student类是Person类的派生类。Doctor类中持有的HospitalName属性,Student中持有的SchoolName属性。
接下來我们创建一个Web Api项目并添加一个PeopleController。
在PeopleController中我们添加一个Add api,并将请求数据直接返回,以便查看效果。
这里我们使用Postman请求这个api, 请求的Content-Type是application/json, 请求的Body内容如下。
请求的返回内容
返回结果和我们希望得到的结果不太一样,Student持有的SchoolName属性和Doctor持有的HospitalName属性都丢失了。
现在我们启动项目调试模式,重新使用Postman请求一次,得到的结果如下
People集合中存放3个People类型的对象, 没有出现我们期望的Student类型对象和Doctor类型对象,这说明.NET Core WebApi默认是不支持多态数据绑定的,如果使用父类类型变量来接收数据,Data Binding只会实例化父类对象,而非一个派生类对象, 从而导致属性丢失。
自定义JsonConverter来实现多态数据绑定
JsonConverter是Json.NET中的一个类,主要负责Json对象的序列化和反序列化。
首先我们创建一个泛型类JsonCreationConverter,并继承了JsonConverter类,代码如下:
其中,我们加入了一个抽象方法Create,这个方法会负责根据Json字符串的内容,返回一个泛型类型对象,这里既可以返回一个当前泛型类型的对象,也可以返回一个当前泛型类型派生类的对象。JObject是Json.NET中的Json字符串读取器,负责读取Json字符串中属性的值。
另外我们还复写了ReadJson方法,在ReadJson中我们会先调用Create方法获取一个当前泛型类对象或者当前泛型类的派生类对象(Json.NET中默认的KeyValuePairConverter会直接实例化当前参数类型对象,这也就是默认不支持多态数据绑定的主要原因),serializer.Popluate方法的作用是将Json字符串的内容映射到目标对象(当前泛型类对象或者当前泛型类的派生类对象)的对应属性。
这里由于我们只需要读取Json, 所以WriteJson的方法我们不需要实现,CanWrite属性我们也强制返回了False。
第二步,我们创建一个PersonJsonConverter类,它继承了JsonCreationConverter<Person>, 其代码如下
在这个类中我们复写了Create方法,这里我们使用JObject来获取Json字符串中拥有的属性。
如果字符串中包含schoolName属性,就返回一个新的Student对象
如果字符串中包含hospitalName属性,就返回一个新的Doctor对象
否则,返回一个新Person对象
最后一步,我们在Person类中使用特性标注Person类使用PersonJsonConverter来进行转换Json序列化和反序列化。
现在我们重新使用调试模式启动程序, 然后使用Postman请求当前api
我们会发现,people集合中已经正确绑定了的派生子类类型对象,最终Postman上我们得到以下响应结果
至此多态数据绑定成功。
刨根问底
为什么添加了一个PersonJsonConverter类,多态绑定就实现了呢?
让我们来一起Review一下MVC Core以及Json.NET的代码。
首先我们看一下MvcCoreMvcOptionsSetup代码
MvcCoreMvcOptionsSetup类中的Configure方法设置了默认数据绑定使用Provider列表。
当一个api参数被标记为[FromBody]时,BodyModelBinderProvider会实例化一个BodyModelBinder对象来处理这个参数并尝试进行数据绑定。
BodyModelBinder类中有一个BindModelAsync方法,从名字的字面意思上我们很清楚的知道这个方法就是用来绑定数据的。
在这个方法中它会尝试寻找一个匹配的IInputFormatter对象来绑定数据,由于这时候请求的Content-Type是application/json, 所以这里会使用JsonInputFormatter对象来进行数据绑定。
下面我们看一下JsonInputFormatter类的部分关键代码
JsonInputFormatter类中的ReadRequestBodyAsync方法负责数据绑定, 在该方法中使用了Json.NET的JsonSerializer类的Deserialize方法来进行反序列化, 这说明Mvc Core的底层是直接使用Json.NET来操作Json的。
JsonSerializer类的部分关键代码
JsonSerializer会调用JsonSerializerInternalReader类的Deserialize方法将Json字符串内容反序列化。
最终我们看一下JsonSerializerInternalReader中的部分关键代码
JsonSerializerInternalReader类里面的Deserialize方法会尝试根据当前请求参数的类型,去查找并实例化一个合适的JsonConverter。 如果查找到匹配的Converter, 就使用该Converter进行实际的反序列化数据绑定操作。在当前例子中由于api的参数类型是Person,所以它会匹配到PersonJsonConverter, 这就是为什么我们通过添加PersonJsonConverter就完成了多态数据绑定的功能。
原文地址:https://www.cnblogs.com/lwqlun/p/9532803.html
.NET社区新闻,深度好文,欢迎访问公众号文章汇总 http://www.csharpkit.com
.NET Core WebApi中实现多态数据绑定相关推荐
- NET问答: 如何将 ASP.NET Core WebAPI 中抛出的异常封装成对象?
咨询区 rianjs: 在 ASP.NET Core WebAPI 中,我的 Controller 代码如下: [Route("create-license/{licenseKey}&quo ...
- .NET Core WebApi中实现数据库的操作(之SqlServer)
一.实现效果 .NET Core WebApi基础入门项目源码下载 二.SqlSugar数据操作框架介绍 SqlSugar是一款老牌 .NET 开源ORM框架,由果糖大数据科技团队维护和更新的国产操作 ...
- ASP.NET Core WebAPI中使用JWT Bearer认证和授权
为什么是 JWT Bearer ASP.NET Core 在 Microsoft.AspNetCore.Authentication 下实现了一系列认证, 包含 Cookie, JwtBearer, ...
- 在 Asp.Net Core WebAPI 中防御跨站请求伪造攻击
什么是跨站请求伪造 跨站请求伪造(英语:Cross-site request forgery),也被称为 one-click attack 或者 session riding,通常缩写为 CSRF 或 ...
- 【WebAPI No.5】Core WebAPI中的自定义格式化
介绍 Web API为JSON和XML提供媒体类型格式化程序.框架默认将这些格式化程序插入管道中.客户端可以在HTTP请求的Accept标头中请求JSON或XML. 格式化数据这个东西,其实没有什么最 ...
- ASP.NET Core WebAPI中的分析工具MiniProfiler
安装 我们可以使用Nuget来下载这个包. PM> Install-Package MiniProfiler.AspNetCore.Mvc 配置Startup.cs MiniProfiler配置 ...
- 在Core WebApi中使用Swagger
1.打开项目NuGet包管理,搜索 Swashbuckle.AspNetCore ,安装. 2.打开Startup.cs,添加以下代码 public void ConfigureService ...
- ASP.NET CORE WebAPI 中 Route 属性配置
1 访问路径属性 Route public class OrdersController : ApiController {[Route("customers/{customerId}/o ...
- ASP.NET Core WebApi使用Swagger生成api说明文档看这篇就够了
引言 在使用asp.net core 进行api开发完成后,书写api说明文档对于程序员来说想必是件很痛苦的事情吧,但文档又必须写,而且文档的格式如果没有具体要求的话,最终完成的文档则完全取决于开发者 ...
最新文章
- ASP.NET MVC 2示例Tailspin Travel
- Linux Graphic DRI Wayland 显示子系统
- [C语言] 文件操作,解压华为官方固件UNDATE.APP工具(源代码);
- yii2中的事件和行为
- 职高学会计电算化好还是学计算机好,会计电算化主要学什么?
- 【数据结构 JavaScript版】- web前端开发精品课程【红点工场】 --javascript-- 链表实现...
- 使用 IAsyncResult 进行 .NET 异步编程
- ionic android绝对定位,Safari中的CSS故障与Ionicons作为背景内容和绝对定位
- linux指定cpu运行程序,进程/线程绑定到特定CPU核的linux实现(有代码有实例)
- (转载)Linux的IPC命令
- 赴日游个人签证门槛降低 年薪3万可申请
- LINUX 7.0真机系统安装问题
- Vc2013实战(1) 别无选择的Mfc
- 小学计算机微课教案及ppt,小学数学微课程ppt
- 论文阅读:Aspect-based Sentiment Classification with Aspect-specific Graph Convolutional Networks
- 永恒之蓝ms17_010漏洞利用攻击
- java test1
- 【数据结构】之图的遍历(C语言)
- 定义一个图书类(Book)
- 【 jQuery 】利用 jQuery 选择器实现表格的全选,取消选择,单击更 改选中状态,反选等功能,为表格添加光棒效果
热门文章
- 据廖雪峰python3教程----python学习第十三天
- ext 浅谈类的实例
- [每日一题] 11gOCP 1z0-052 :2013-09-23 Oracle11g 内存参数设置...................................C7...
- zabbix2.0安装与配置
- 九度 1376 最近零子序列
- 【鉴权/授权】一步一步实现一个简易JWT鉴权
- 2021 .NET 开发者峰会顺利在网上落幕,线上直播回看汇总
- ASP.NET Core 配置 - 创建自定义配置提供程序
- Api网关Kong集成Consul做服务发现及在Asp.Net Core中的使用
- 如何在 ASP.Net Core 使用 分布式缓存