YbSoftwareFactory 代码生成插件【二十】:DynamicObject的序列化
DynamicObject 是 .NET 4.0以来才支持的一个类,但该类在.NET 4.0下未被标记为[Serializable] Attribute,而在.NET 4.5下则被标记了[Serializable] Attribute。需要注意的是,如果你使用需要进行XML序列化等操作(例如WCF中),部署到未安装.NET 4.5的环境中通常会报错并提示异常,而不管你编译时使用的目标平台是.NET 4.0 还是 .NET 4.5。通常这个错误在安装了.NET 4.5环境的开发机上通常没有问题,即使你创建的项目是基于.NET 4.0的,但实际调用的还是 .NET 4.5的库。因此通常在使用 DynamicObject 并需要进行序列化的情景下需要谨慎(特别是WCF环境下),除非你实现了你自定义的序列化操作。在此提醒广大开发人员注意,否则到你正式部署至不能安装.NET 4.5的环境中将折腾你够呛(例如Windows Server 2003等环境)。
在前文:“实体类配合数据库表字段进行属性扩展” 一文中介绍了如何使用 DynamicObject 进行属性的扩展,但该类在MVC下进行JSON序列化时其序列化的结果并不友好。本文主要讨论的是如何友好地对 DynamicObject 继承类进行JSON序列化。
要对 DynamicObject 对象实现JSON的序列化,其实只需在 DynamicObject 的继承类中实现 IDictionary<string,object> 接口即可,因为 JavaScriptSerializer 和 Json.NET 均支持对 IDictionary<string,object> 的序列化,该接口主要对 DynamicObject 对象的属性和值进行管理。前文所述的ExtensionObject类就继承自DynamicObject类,并实现了 IDynamicMetaObjectProvider 和 IDictionary<string,object> 接口。
在MVC中原生态的 JavascrioptSerializer 序列化时会使用 IDictionary<string,object> 的实现方法 System.Collections.IEnumerable.GetEnumerator() 来获取要序列化的属性名。
而Json.NET则调用 IDictionary<string,object> 的实现方法 IEnumerable<KeyValuePair<string, object>>.GetEnumerator() 来获取属性及其值。
但二者最大的区别是,使用JavascrioptSerializer将序列化成如下的JSON格式:
{{"Key":"Code","Value":"4"},{"Key":"ID","Value":"d8ea26b06d9d4c7e85ccc43da71320ac"},{"Key":"LongName","Value":"null"}, {"Key":"FCode","Value":"/51/5100/4"},{"Key":"NodeLevel","Value":"3"}}
而使用Json.NET则序列化为:{"ID": "d8ea26b06d9d4c7e85ccc43da71320ac","Code": "4","LongName": null,"FCode": "/51/5100/4","NodeLevel": 3}
毫无疑问,使用Json.NET进行序列化更符合实际的情况和需要,而且速度还更快。当然,在WebApi下,因为已使用了Json.NET作为默认的序列化组件,并不存在上述问题,因此本文将主要对MVC中对DynamicObject的Json.NET序列化的实现进行说明。
一、MVC下使用Json.NET序列化
1、实现自定义ActionResult,继承自JsonResult类,代码如下:
using System;
using System.Web.Mvc;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters; namespace YbRapidSolution.Presenter.JsonNet
{
public class JsonNetResult : JsonResult
{
public JsonSerializerSettings SerializerSettings { get; set; }
public JsonNetResult()
: base()
{
// create serializer settings
this.SerializerSettings = new JsonSerializerSettings();
// 阻止属性循环引用的情况下出现的异常
this.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
// setup default serializer settings
this.SerializerSettings.Converters.Add(new IsoDateTimeConverter());
}
public JsonNetResult(string contentType)
: this()
{
ContentType = contentType;
}
public JsonNetResult(string contentType, System.Text.Encoding contentEncoding)
: this(contentType)
{
ContentEncoding = contentEncoding;
}
public override void ExecuteResult(ControllerContext context)
{
if (context == null)
throw new ArgumentNullException("context");
if (JsonRequestBehavior == JsonRequestBehavior.DenyGet &&
String.Equals(context.HttpContext.Request.HttpMethod, "GET", StringComparison.OrdinalIgnoreCase))
{
throw new InvalidOperationException("Json request GET not allowed");
}
// 获取当前 http context response
var response = context.HttpContext.Response;
// 设置 content type
response.ContentType = !String.IsNullOrEmpty(ContentType) ? ContentType : "application/json";
// 设置 encoding
if (ContentEncoding != null)
response.ContentEncoding = this.ContentEncoding;
if (Data != null)
{
// 使用 JSON.Net 把对象序列化为 JSON
string jsonText = JsonConvert.SerializeObject(this.Data, Formatting.Indented, this.SerializerSettings);
// write the response
response.Write(jsonText);
}
}
}
}
2、对Controller进行方法的扩展
using System.Dynamic;
using System.Web.Mvc;
using YbRapidSolution.Presenter.Controllers; namespace YbRapidSolution.Presenter.JsonNet
{
public static class JsonNetControllerExtensions
{
public static JsonNetResult JsonNet(this Controller controller, object data)
{
return new JsonNetResult() { Data = data };
}
public static JsonNetResult JsonNet(this Controller controller, object data,string contentType)
{
return new JsonNetResult(contentType) { Data = data };
}
}
}
3、调用方式的Demo如下:
/// <summary>
/// 查找当前登录用户的当前岗位对本模块所具有的动作权限集合
/// </summary>
/// <param name="orgFId">当前登录用户所使用的岗位(人员成员)的标识全路径</param>
/// <returns></returns>
[AcceptVerbs(HttpVerbs.Post)]
[YbMvcAuthorize(PermissionKeys = PERMISSIONKEY)]
public JsonResult FindAllowActionsFor(string orgFId)
{
try
{
var curMessage = new EasyUIMessage(true, "权限项加载成功");
//查询类型为按钮或右键菜单的动作
var actions = _permissionService
.FindControlsForOrgByKeyAndOrgFId(PERMISSIONKEY,orgFId); curMessage.data = actions;
return this.JsonNet(curMessage);
}
catch (Exception er)
{
var curMessage = new EasyUIMessage(false, string.Format("权限项加载失败:{0}", er.Message));
return this.JsonNet(curMessage);
}
}
二、Web Api下使用Json.NET序列化
Web Api因为使用Json.NET作为默认的JSON序列化实现框架,通常需在 WebApiConfig 类的 Register 中写如下的代码进行配置即可:
config.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling
= ReferenceLoopHandling.Serialize;
config.Formatters.JsonFormatter.SerializerSettings.PreserveReferencesHandling
= PreserveReferencesHandling.Objects;
如需了解更多请点击:权限模型+流程专家 Demo
下一章将分享WebApi和MVC下的提升性能的一些经验。
YbSoftwareFactory 代码生成插件【二十】:DynamicObject的序列化的更多相关文章
- YbSoftwareFactory 代码生成插件【十四】:通过 DynamicLinq 简单实现 N-Tier 部署下的服务端数据库通用分页
YbSoftwareFactory 的 YbRapidSolution for WinForm 插件使用CSLA.NET作为业务层,CSLA.NET的一个强大的特性是支持 N-Tiers 部署.只需非 ...
- YbSoftwareFactory 代码生成插件【十五】:Show 一下最新的动态属性扩展功能与键值生成器功能
YbSoftwareFactory 各种插件的基础类库中又新增了两个方便易用的功能:动态属性扩展与键值生成器,本章将分别介绍这两个非常方便的组件. 一.动态属性扩展 在实际的开发过程中,你肯定会遇到数 ...
- YbSoftwareFactory 代码生成插件【十九】:实体类配合数据库表字段进行属性扩展的小技巧
实体类通常需要和数据库表进行了ORM映射,当你需要添加新的属性时,往往同时也需要在数据库中添加相应的字段并配置好映射关系,同时可能还需对数据访问组件进行重新编译和部署才能有效.而当你开始设计一个通用数 ...
- YbSoftwareFactory 代码生成插件【十八】:树形结构下的查询排序的数据库设计
树形结构的排序在中国特色下十分普遍也非常重要,例如常说的五大班子,党委>人大>政府>政协>纪委,每个班子下还有部门,岗位,人员,最终排列的顺序通常需要按权力大小.重要性等进行排 ...
- YbSoftwareFactory 代码生成插件【十六】:Web 下灵活、强大的审批流程实现(含流程控制组件、流程设计器和表单设计器)
程序=数据结构+算法,而企业级的软件=数据+流程,流程往往千差万别,客户自身有时都搞不清楚,随时变化的情况更是家常便饭,抛开功能等不谈,需求变化很大程度上就是流程的变化,流程的变化会给开发工作造成很大 ...
- 使用Typescript重构axios(二十八)——自定义序列化请求参数
0. 系列文章 1.使用Typescript重构axios(一)--写在最前面 2.使用Typescript重构axios(二)--项目起手,跑通流程 3.使用Typescript重构axios(三) ...
- YbSoftwareFactory 代码生成插件【二十五】:Razor视图中以全局方式调用后台方法输出页面代码的三种方法
上一篇介绍了 MVC中实现动态自定义路由 的实现,本篇将介绍Razor视图中以全局方式调用后台方法输出页面代码的三种方法. 框架最新的升级实现了一个页面部件功能,其实就是通过后台方法查询数据库内容,把 ...
- YbSoftwareFactory 代码生成插件【二十四】:MVC中实现动态自定义路由
上一篇介绍了 公文流转系统 的实现,本篇介绍下MVC下动态自定义路由的实现. 在典型的CMS系统中,通常需要为某个栏目指定个友链地址,通过指定友链地址,该栏目的地址更人性化.方便记忆,也有利用于搜索引 ...
- YbSoftwareFactory 代码生成插件【二十二】:CMS基础功能的实现
很多网友建议在YbRapidSolution for MVC框架的基础上实现CMS功能,以方便进行内容的管理,加快前端页面的开发速度.因此花了一段时间,实现了一套CMS内容发布系统并已集成至YbRap ...
随机推荐
- *HDU2510 DFS
符号三角形 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submi ...
- 【完整靠谱版】结合公司项目,仔细总结自己使用百度编辑器实现FTP上传的完整过程
说在前面 工作中会遇到很多需要使用富文本编辑器的地方,比如我现在发布这篇文章离不开这个神器,而且现在网上编辑器太多了.记得之前,由于工作需要自己封装过一个编辑器的公共插件,是用ckeditor改版的, ...
- PHP中获取星期的几种方法
PHP中获取星期的几种方法 PHP星期几获取代码: 1 date(l); 2 //data就可以获取英文的星期比如Sunday 3 date(w); 4 //这个可以获取数字星期比如123,注意0 ...
- 贪吃蛇的java代码分析(三)
代码剖析 在上一篇文章中,我们完成了贪吃蛇部分代码的构造.回头审视我们写的代码与思路,会发现我们遗漏了一个重要的地方,那就是:贪吃蛇的自身移动.想必大家都知道,贪吃蛇自身是会自己移动的,并且会跟随你的 ...
- 在mvc中实现图片验证码的刷新
首先,在项目模型(Model)层中建立一个生成图片验证码的类ValidationCodeHelper,代码如下: public class ValidationCodeHelper { //用户存取验 ...
- Git & Gitlab 使用指南
2016-02-23 | 9,129字 | 分类于 工具 | 3条评论 去年小组在从 SVN 和 TFS 迁移到 Git 的过程中整理了这份文档,面向的用户是对 Git 和 SV ...
- Sqlserver 导出数据脚本
编写数据压缩选项的脚本 true 要编写脚本的数据的类型 仅限数据
- CentOS7.2 编译安装SVN1.9.5客户端
背景 原来想在Linux机上开Samba共享,在Windows机上把工作目录映射到网络驱动器,用Source Insight编辑代码后就不用来回同步文件了. 然而在使用中发现,Windows机用的SV ...
- spark读取hdfs上的文件和写入数据到hdfs上面
def main(args: Array[String]): Unit = { val conf = new SparkConf() conf.set("spark.master" ...
- Java实现归并排序
package Sort; import java.util.Arrays; public class MergeSort { public static void merge(int[] list, ...