ASP.NET WebAPI (反)序列化用[SerializableAttribute]修饰的类的一个坑
发现问题
在 ASP.NET WebAPI 项目中,有这样的 ViewModel 类:
[Serializable]
class Product
{
public int Id { get; set; }
public decimal Price { get; set; }
public DateTime ProductDate { get; set; }
}
Controller 和 Action 代码如下:
public class ProductController : ApiController
{
public Product Get(int id)
{
return new Product()
{
Id = 1,
Price = 12.9m,
ProductDate = new DateTime(1992, 1, 1)
};
}
}
客户端请求该资源: http://localhost:5000/api/product/1,结果发现 WebAPI 返回这样的JSON,如下:
{
"<Id>k__BackingField": 1,
"<Price>k__BackingField": 12.9,
"<ProductDate>k__BackingField": "1992-01-01T00:00:00"
}
我们知道,自动属性虽然没有定义字段,但是C#编译器会生成相应的私有字段,类似 private int <Id>k__BackingField。
我们期望 WebAPI 序列化时将属性名作为 JSON 的键,而这里 WebAPI 序列化的却是编译器生成的私有字段,显然不符合我们的要求。
奇怪的地方是,如果单独用 Json.NET 类库去序列化,则能得到期望的 JSON,如下:
{
"Id": 1,
"Price": 12.9,
"ProductDate": "1992-01-01T00:00:00"
}
找到原因
经过 Google 一番,原来是和 SerializableAttribute 有关。
从 Json.NET 4.5 Release 2 版本开始,新增这样的特性:
如果检测到类型有 SerializableAttribute,将序列化该类型的所有私有/公开字段,并且忽略其属性。
如果不想要这个新特性,可以对类应用 JsonObjectAttribute 来覆盖,或者在全局范围内 设置 DefaultContractResolver 的 IgnoreSerializableAttribute 为 true。
而从 release 3 版本开始 IgnoreSerializableAttribute 默认为 true。
而 ASP.NET WebAPI 依赖 Json.NET,但是却将 IgnoreSerializableAttribute 设置为 false,也就是不忽略 SerializableAttribute,导致如果类用 [SerializableAttribute] 修饰,就只(反)序列化字段而忽略属性,于是当用自动属性时,输出的就是编译器自动生成的字段名。
解决问题
了解到问题的原因后,可以通过以下方式解决:
- 去掉 [Serializable]
- 应用 [JsonObjectAttribute]
- 设置 IgnoreSerializableAttribute
最简单的方法就是去掉 [Serializable],如果由于某些原因不能去除,可以用其他两种办法。
应用 JsonObjectAttribute
[Newtonsoft.Json.JsonObject]
[System.Serializable]
class Product
{
public int Id { get; set; }
public decimal Price { get; set; }
public DateTime ProductDate { get; set; }
}
设置 IgnoreSerializableAttribute
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// 其他代码省略 .........
// 将 SerializerSettings 重置为默认值 IgnoreSerializableAttribute = true
config.Formatters.JsonFormatter.SerializerSettings = new JsonSerializerSettings();
}
}
参考:
Json.NET 4.5 Release 2 – Serializable support and bug fixes
Why won't Web API deserialize this but JSON.Net will?
ASP.NET WebAPI (反)序列化用[SerializableAttribute]修饰的类的一个坑的更多相关文章
- 细说Asp.Net WebAPI消息处理管道
我们在开发完Asp.Net WebAPI程序后,可以使用WebHost寄宿方式或者SelfHost寄宿方式来部署Asp.Net WebAPI.所谓WebHost寄宿就是通过Asp.Net来实现:所谓S ...
- ASP.NET WebAPI使用Swagger生成测试文档
ASP.NET WebAPI使用Swagger生成测试文档 SwaggerUI是一个简单的Restful API测试和文档工具.简单.漂亮.易用(官方demo).通过读取JSON配置显示API .项目 ...
- ASP.NET WebAPI 测试文档 (Swagger)
ASP.NET WebAPI使用Swagger生成测试文档 SwaggerUI是一个简单的Restful API测试和文档工具.简单.漂亮.易用(官方demo).通过读取JSON配置显示API .项目 ...
- 笔记-ASP.NET WebApi
本文是针对ASP.NET WepApi 2 的笔记. Web API 可返回的结果: 1.void 2.HttpResponseMessage 3.IHttpActionResult 4.其他类型 返 ...
- Asp.Net WebApi核心对象解析(下篇)
在接着写Asp.Net WebApi核心对象解析(下篇)之前,还是一如既往的扯扯淡,元旦刚过,整个人还是处于晕的状态,一大早就来处理系统BUG,简直是坑爹(好在没让我元旦赶过来该BUG),队友挖的坑, ...
- 【开源】分享一个前后端分离方案-前端angularjs+requirejs+dhtmlx 后端asp.net webapi
一.前言 半年前左右折腾了一个前后端分离的架子,这几天才想起来翻出来分享给大家.关于前后端分离这个话题大家也谈了很久了,希望我这个实践能对大家有点点帮助,演示和源码都贴在后面. 二.技术架构 这两年a ...
- 前端angularjs+requirejs+dhtmlx 后端asp.net webapi
享一个前后端分离方案源码-前端angularjs+requirejs+dhtmlx 后端asp.net webapi 一.前言 半年前左右折腾了一个前后端分离的架子,这几天才想起来翻出来分享给大家 ...
- Asp.Net WebApi核心对象解析(二)
在接着写Asp.Net WebApi核心对象解析(下篇)之前,还是一如既往的扯扯淡,元旦刚过,整个人还是处于晕的状态,一大早就来处理系统BUG,简直是坑爹(好在没让我元旦赶过来该BUG),队友挖的坑, ...
- [翻译] ASP.NET WebAPI 中的异常处理
原文链接:https://docs.microsoft.com/en-us/aspnet/web-api/overview/error-handling/exception-handling 本文介绍 ...
随机推荐
- 企业官网Web原型制作分享-Tesla
Tesla是汽车行业知名的奢华品牌,产品为纯电动汽车,知名度极高.此模板正是取自Tesla的官网,高端大图配上文字排版,彰显了汽车的奢华感觉. 本原型由国产Mockplus(原型工具)和iDoc(智能 ...
- samtools flagstat
samtools flagstat命令简介: 统计输入文件的相关数据并将这些数据输出至屏幕显示.每一项统计数据都由两部分组成,分别是QC pass和QC failed,表示通过QC的reads数据量和 ...
- ListView动态改变每一项的高度。
ListView中每一项的高度默认是相同的,除非超过其预定高度值,否则需要动点手脚. VariableSizedListView 继承 ListView然后重写protected override v ...
- 如何将spring boot项目打包成war包
一.修改打包形式 在pom.xml里设置 <packaging>war</packaging> 二.移除嵌入式tomcat插件 在pom.xml里找到spring-boot-s ...
- mysql的一些配置优化
[mysqld]lower_case_table_names=1datadir=/var/lib/mysqlsocket=/var/lib/mysql/mysql.sockuser=mysql# Di ...
- 2018.12.15 spoj Substrings(后缀自动机)
传送门 后缀自动机基础题. 求长度为iii的子串出现次数的最大值. 对原串建出samsamsam,然后用sizsizsiz更新每个maxlenmaxlenmaxlen的答案. 然后由于后缀链接将其转化 ...
- 2018.12.15 bzoj3676: [Apio2014]回文串(后缀自动机)
传送门 对原串建立一个后缀自动机,然后用反串在上面匹配. 如果当前匹配的区间[l,r][l,r][l,r]包裹了当前状态的endposendposendpos中的最大值,那么[l,maxpos][l, ...
- Educational Codeforces Round 62 E 局部dp + 定义状态取消后效性
https://codeforces.com/contest/1140/problem/E 局部dp + 定义状态取消后效性 题意 给你一个某些位置可以改变的字符串,假如字符串存在回文子串,那么这个字 ...
- 安装SourceTree遇到的一个个坑
之前在公司的电脑上满心欢喜的安装了下,很顺利就成功了,回来在自己电脑上安装,结果坑不能停,以此来纪念下吧! 下载完成后,进行安装: 这里我是申请了个账户,选第一个user an existing ac ...
- location位置操作
使用location对象可以通过很多方式来改变浏览器的位置. location.assign('http://www.klkx.com') 传入一个URL地址 这样可以立即打开一个新的URL并在浏览器 ...