通过NHibernate我们多表查询是实现了 但由于查询出来的集合中的对象“不是平的”,如何在送到UI绑定成了问题。ExtJs UI组件的数据绑定支持多种格式,如简单数组,Json,Xml。在本项目中我们统一,服务器端通过Json把数据传输到Ext进行解析和绑定。

那么我们现在只需要找个方便的办法把我们的.Net对象(集合)转化为Json格式的字符串就可以了。于是乎我们google了一下发现.Net下还真有这么个方法能把.Net对象序列化成Json字符串
new System.Web.Script.Serialization.JavaScriptSerializer().Serialize([要序列化的.Net对象]);
Asp.Net Mvc里也有(看过MVC源码后可知,其实里面用的也是上面的JavaScriptSerializer):

public ActionResult test5()
{
return Json([要序列化的Json对象]);
}

我们试试

//Json输出试一试
public ActionResult test5()
{
return Json(new {
Name = "弦哥",
Age = 26,
IsMarry = true,
MyDog = new { Name = "大海", Age = 1, Variety="罗威纳" }
});}

输出的Json字符串为:{"Name":"弦哥","Age":26,"IsMarry":true,"MyDog":{"Name":"大海","Age":1,"Variety":"罗威纳"}}

但把NHibernate查询出的集合对象也放进去序列化一下:出现错误了,序列化类型对象的时候检测到对象循环使用。

解决方法:

我们用Json.Net(Newtonsoft.Json),下面我们继承他的DefaultContractResolver类并重写GetSerializableMembers方法 ,定义我们自己的Json序列化规则NHibernateContractResolver,代码如下:

namespace Demo.HIS.FrameWork
{
/// <summary>
/// 自定义Json.Net的规则
/// </summary>
public class NHibernateContractResolver : DefaultContractResolver
{
private string[] exceptMemberName;//例外 private static readonly MemberInfo[] NHibernateProxyInterfaceMembers = typeof(INHibernateProxy).GetMembers(); public NHibernateContractResolver(string[] exceptMemberName)
{
this.exceptMemberName = exceptMemberName;
}
protected override List<MemberInfo> GetSerializableMembers(Type objectType)
{
var members = new List<PropertyInfo>(objectType.GetProperties());
members.RemoveAll(memberInfo =>
// (IsMemberNames(memberInfo))||
(IsMemberPartOfNHibernateProxyInterface(memberInfo))||
(IsMemberDynamicProxyMixin(memberInfo))||
(IsMemberMarkedWithIgnoreAttribute(memberInfo,objectType))||
(IsInheritedISet(memberInfo))||
(IsInheritedEntity(memberInfo))
); var actualMemberInfos = new List<MemberInfo>();
foreach (var memberInfo in members)
{
var infos = memberInfo.DeclaringType.BaseType.GetMember(memberInfo.Name);
actualMemberInfos.Add(infos.Length == 0 ? memberInfo : infos[0]);
//Debug.WriteLine(memberInfo.Name);
}
return actualMemberInfos;
}
private static bool IsMemberDynamicProxyMixin(PropertyInfo memberInfo)
{
return memberInfo.Name == "__interceptors";
} private static bool IsMemberPartOfNHibernateProxyInterface(PropertyInfo memberInfo)
{
return Array.Exists(NHibernateProxyInterfaceMembers, mi => memberInfo.Name == mi.Name);
} private static bool IsMemberMarkedWithIgnoreAttribute(PropertyInfo memberInfo, Type objectType)
{
var infos = typeof(INHibernateProxy).IsAssignableFrom(objectType) ?
objectType.BaseType.GetMember(memberInfo.Name) :
objectType.GetMember(memberInfo.Name);
return infos[0].GetCustomAttributes(typeof(JsonIgnoreAttribute), true).Length > 0;
} private bool IsExceptMember(PropertyInfo memberInfo)
{
if (exceptMemberName == null)
return false;
return Array.Exists(exceptMemberName, i => memberInfo.Name == i);
} private bool IsInheritedISet(PropertyInfo memberInfo)
{
return (memberInfo.PropertyType.Name == "ISet`1" && !IsExceptMember(memberInfo));
} private bool IsInheritedEntity(PropertyInfo memberInfo)
{
return (FindBaseType(memberInfo.PropertyType).Name == "Entity" && !IsExceptMember(memberInfo));
}
private static Type FindBaseType(Type type)
{
if (!type.IsClass)
return type;
if (type.Name == "Entity"||type.Name=="Object")
{
return type;
}
return FindBaseType(type.BaseType);
}
}
}

代码有点复杂,涉及到对NHibernate动态代理的一些特殊处理。大概意思就是如果对象里的属性的类型为Entity或ISet<T>的我们就忽略掉,不序列化,除非我们显示指定需要序列化的属性名。

为了方便Asp.Net MVC调用我们自己的Json序列化,我们自定义一个ActionResult:

public class FormatJsonResult : ActionResult
{
public string[] ExceptMemberName { get; set; }
public Object Data { get; set; }
public override void ExecuteResult(ControllerContext context)
{
if (context == null)
{
throw new ArgumentNullException("context");
}
HttpResponseBase response = context.HttpContext.Response;
response.ContentType = "application/json"; StringWriter sw = new StringWriter();
JsonSerializer serializer = JsonSerializer.Create(
new JsonSerializerSettings
{
Converters = new JsonConverter[] { new Newtonsoft.Json.Converters.JavaScriptDateTimeConverter() },
ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
NullValueHandling = NullValueHandling.Ignore,
ContractResolver = new NHibernateContractResolver(ExceptMemberName)
}
); using (JsonWriter jsonWriter = new JsonTextWriter(sw))
{
jsonWriter.Formatting = Formatting.Indented;
serializer.Serialize(jsonWriter, Data);
}
response.Write(sw.ToString());
}
}

再给Asp.net MVC的Controller类定义两个扩展方法:

public static class FormatJsonExtension
{
public static FormatJsonResult JsonFormat(this Controller c, object data, string[] exceptMemberName)
{
FormatJsonResult result = new FormatJsonResult();
result.Data = data;
result.ExceptMemberName = exceptMemberName;
return result;
} public static FormatJsonResult JsonFormat(this Controller c, object data)
{
return JsonFormat(c, data, null);
} }

//测试一下
public ActionResult test()
{
Demo.HIS.Infrastructure.Core.Repositories.IDictionaryRepository r = new Demo.HIS.Infrastructure.Repositories.Data.DictionaryRepositoryImpl();
long total;
var list = r.GetPlistByCategoryId("48391bb4-471b-4499-899b-cea9748e1a7b", 0, 15, "Index", "desc", null, out total);

//我们自己的Json序列化方法
return this.JsonFormat(
list,
new string[] { "Category" });//指定需要序列化属性“Category”
}

Asp.Net MVC大型项目实践整合 NHibernate与Json序列化的更多相关文章

  1. [转]Asp.Net大型项目实践(11)-基于MVC Action粒度的权限管理【续】【源码在这里】(在线demo,全部源码)

    本文转自:http://www.cnblogs.com/legendxian/archive/2010/01/25/1655551.html 接上篇Asp.Net大型项目实践(10)-基于MVC Ac ...

  2. ASP.NET MVC搭建项目后台UI框架—5、Demo演示Controller和View的交互

    目录 ASP.NET MVC搭建项目后台UI框架—1.后台主框架 ASP.NET MVC搭建项目后台UI框架—2.菜单特效 ASP.NET MVC搭建项目后台UI框架—3.面板折叠和展开 ASP.NE ...

  3. ASP.NET MVC搭建项目后台UI框架—6、客户管理(添加、修改、查询、分页)

    目录 ASP.NET MVC搭建项目后台UI框架—1.后台主框架 ASP.NET MVC搭建项目后台UI框架—2.菜单特效 ASP.NET MVC搭建项目后台UI框架—3.面板折叠和展开 ASP.NE ...

  4. 使用Visual Studio 2015 开发ASP.NET MVC 5 项目部署到Mono/Jexus

    最新的Mono 4.4已经支持运行asp.net mvc5项目,有的同学听了这句话就兴高采烈的拿起Visual Studio 2015创建了一个mvc 5的项目,然后部署到Mono上,浏览下发现一堆错 ...

  5. ASP.NET MVC搭建项目后台UI框架—1、后台主框架

    目录 ASP.NET MVC搭建项目后台UI框架—1.后台主框架 ASP.NET MVC搭建项目后台UI框架—2.菜单特效 ASP.NET MVC搭建项目后台UI框架—3.面板折叠和展开 ASP.NE ...

  6. ASP.NET MVC搭建项目后台UI框架—11、自动加载下拉框查询

    ASP.NET MVC搭建项目后台UI框架—1.后台主框架 需求:在查询记录的时候,输入第一个字,就自动把以这个字开头的相关记录查找出来,输入2个字就过滤以这两个子开头的记录,依次类推. 突然要用到这 ...

  7. ASP.NET MVC搭建项目后台UI框架—2、菜单特效

    目录 ASP.NET MVC搭建项目后台UI框架—1.后台主框架 ASP.NET MVC搭建项目后台UI框架—2.菜单特效 ASP.NET MVC搭建项目后台UI框架—3.面板折叠和展开 ASP.NE ...

  8. ASP.NET MVC搭建项目后台UI框架—3、面板折叠和展开

    目录 ASP.NET MVC搭建项目后台UI框架—1.后台主框架 ASP.NET MVC搭建项目后台UI框架—2.菜单特效 ASP.NET MVC搭建项目后台UI框架—3.面板折叠和展开 ASP.NE ...

  9. ASP.NET MVC搭建项目后台UI框架—4、tab多页签支持

    目录 ASP.NET MVC搭建项目后台UI框架—1.后台主框架 ASP.NET MVC搭建项目后台UI框架—2.菜单特效 ASP.NET MVC搭建项目后台UI框架—3.面板折叠和展开 ASP.NE ...

随机推荐

  1. Linux I/O优化 磁盘读写参数设置

    关于页面缓存的信息,可以用cat /proc/meminfo 看到.其中的Cached 指用于pagecache的内存大小(diskcache-SwapCache).随着写入缓存页,Dirty 的值会 ...

  2. 【DL】物体识别与定位

    https://cloud.tencent.com/community/article/414833

  3. 父组件中vuex方法更新state,子组件不能及时更新并渲染的解决方法

    场景: 我实际用到的是这样的,我父组件引用子组件related,父组件调用获取页面详情的方法,更新了state值related,子组件根据该related来渲染相关新闻内容,但是页面打开的时候总是先加 ...

  4. vue加百度统计代码(亲测有效)

    申请百度统计后,会得到一段JS代码,需要插入到每个网页中去,在Vue.js项目首先想到的可能就是,把统计代码插入到index.html入口文件中,这样就全局插入,每个页面就都有了;这样做就涉及到一个问 ...

  5. es 5 数组reduce方法记忆

    reduce() 方法接收一个函数作为累加器(accumulator),数组中的每个值(从左到右)开始合并,最终为一个值. 概念:对数组中的所有元素调用指定的回调函数.该回调函数的返回值为累积结果,并 ...

  6. node.js和socket.io实现im

    im——Instant Messaging 即时通讯 基本技术原理 (1)通过IM服务器登陆或注销 (2)用户A通过列表找到B,用户B获得消息并与之交谈 (3)通过IM服务器指引建立与B单独的通讯通道 ...

  7. 纯CSS制作的TAB选项卡

    代码 这里主要使用表单的单选按钮来实现这个TAB显示和隐藏,首页tab里的内容默认隐藏,如果单选按钮为选中状态(checked)就显示内容.具体请看下面代码. 关于兼容性,因为是用CSS3来制作的,所 ...

  8. PostgreSQL的表空间

    1. 表空间的概念 PostgreSQL中的表空间允许在文件系统中定义用来存放表示数据库对象的文件的位置.在PostgreSQL中表空间实际上就是给表指定一个存储目录. 2. 表空间的作用 官方解释 ...

  9. 如何使Ubuntu Linux12.04 LTS版可以用root用户登陆

    如何使Ubuntu Linux12.04 LTS版可以用root用户登陆 1.  用普通用户登录2.  在终端执行sudo -s,然后输入当前登录的普通用户密码,进入到root用户模式3.  执行ge ...

  10. Ora2Pg的安装和使用

    1. 安装DBI,DBD::Oracle DBI只是个抽象层,要实现支持不同的数据库,则需要在DBI之下,编写针对不同数据库的驱动.对MySql来说,有DBD::Mysql, 而对ORACLE来说,则 ...