通过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. centos6.5 手动安装gcc

    gcc版本:gcc-4.4.7 rpm -Uvh  mpfr-2.4.1-6.el6.x86_64.rpm rpm -Uvh  cpp-4.4.7-16.el6.x86_64.rpmrpm -Uvh  ...

  2. 和我一起学《HTTP权威指南》——连接管理

    连接管理 1.TCP连接 几乎所有的HTTP通信都是由TCP/IP承载的. 浏览网页时客户端执行的操作: 如浏览http://www.joes-hardware.com:80/power-tools. ...

  3. libaio.so.1: undefined reference to `__stack_chk_fail@GLIBC_2.4'

    没有别的原因: 找正确的  libaio.so.1 包就成. 我这儿有,需要的可以下载奥!

  4. LINUX下安装软件方法命令方法

    1.通常Linux应用软件的安装包有三种: 1) tar包,如software-1.2.3-1.tar.gz.它是使用UNIX系统的打包工具tar打包的. 2) rpm包,如software-1.2. ...

  5. symfony 命令

    1.创建Bundle php bin/console generate:bundle --namespace=Home/IndexBundle --format=yml  创建bundle会更新app ...

  6. HTML5标签canvas制作平面图

    摘要: HTML5规范已经完成了,互联网上已经有数不清的站点使用了HTML5.从现在开始研究HTML5,本文是自己在学习canvas过程中的记录,以备后需. 历史: 这个 HTML 元素是为了客户端矢 ...

  7. oracle sqlplus常用命令大全

    show和set命令是两条用于维护SQL*Plus系统变量的命令 SQL> show all --查看所有68个系统变量值 SQL> show user --显示当前连接用户 SQL> ...

  8. RF失败案例重跑

    1.1        失败案例重跑 该功能主要是针对上次连跑失败的案例需要重新执行测试的情况,可自动识别上次执行失败的案例并进行重跑,无需手动选择相应的案例,简单高效. 1.5.1.        重 ...

  9. osg剔除背面开启

    //设置背部剔除看不见背面东西 osg::ref_ptr<osg::CullFace> cullface=new osg::CullFace(osg::CullFace::BACK); s ...

  10. 搭建ntp服务器

    1.同步网络时间 先关闭掉ntp服务,使用ntpd同步网络时间. /etc/init.d/ntpd stop ntpdate 2.hk.pool.ntp.org 网络时间可以从http://www.p ...