通过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. 《Thinking in Java》习题——吸血鬼数字

    最近在看<Java编程思想>,这本书非常棒,不愧是Java程序员的圣经.看到第四章,后面有道题目很有意思,于是就自己做了做.

  2. v9定时发布的简单实现方法[支持静态生成]

    将以下代码放到 api/count.php 文件最后 的 ?>之前 //add 定时发布审核功能 $modelid = $modelid ? $modelid : intval($_GET['m ...

  3. python使用pyqt写带界面工具

    上篇介绍的使用python自带tkinter包,来写带界面的工具. 此篇介绍使用pyqt来开发测试工具. tkinter的好处是python官方自带,上手容易(但手写控件复杂),布局和摆放都不直观和容 ...

  4. Java多线程之可见性与原子性——synchronized VS volatile

    <转:http://blog.csdn.net/uniquewonderq/article/details/48113071> 程序举例: 代码: package com.synch; p ...

  5. Java泛型方法与数据查询

    在使用JDBC查询数据库中数据时,返回的结果是ResultSet对象,使用十分不方便.Commons DbUtils组件提供了将ResultSet转化为Bean列表的方法,但是该方法在使用时需要根据不 ...

  6. laravel 5.3升级5.4

    1)修改 composer 配置文件 composer.json 1.如果你用了 laravel-admin,larvel-admin 版本改 1.4.x-dev 2.laravel 版本改 5.4. ...

  7. 【安全开发】IOS安全编码规范

    申明:本文非笔者原创,原文转载自:https://github.com/SecurityPaper/SecurityPaper-web/blob/master/_posts/2.SDL%E8%A7%8 ...

  8. 【代码审计】MIPCMS 远程写入配置文件Getshell

    0x00 环境准备 MIPCMS官网:https://www.mipcms.cn 网站源码版本:MIPCMS内容管理系统 V3.1.0(发布时间:2018-01-01) 程序源码下载:http://w ...

  9. 【RF库测试】set variable if

  10. STL——迭代器与traits编程技法

    一.迭代器 1. 迭代器设计思维——STL关键所在 在<Design Patterns>一书中对iterator模式定义如下:提供一种方法,使之能够依序巡访某个聚合物(容器)所含的各个元素 ...