通过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. MFC中CString.Format的详细用法

          本文转载自:http://blog.csdn.net/wangkaishou/article/details/5846152,感谢网友 Technorati 标签: CString For ...

  2. Thinkphp5模板继承

    代码 application\index\controller\index.php <?php namespace app\index\controller; use app\index\con ...

  3. QT QGraphicsProxyWidget对象可选择或移动的一些tricks

    我在QT图形视图框架中使用QGraphicsProxyWidget嵌入widget,但是无法使其和其它的QGraphicsItem一样可以选择或移动,使用如下语句无效:  C++ Code  1234 ...

  4. SpringMVC由浅入深day01_9商品修改功能开发

    9 商品修改功能开发 9.1 需求 操作流程: 1.进入商品查询列表页面 2.点击修改,进入商品修改页面,页面中显示了要修改的商品(从数据库查询) 要修改的商品从数据库查询,根据商品id(主键)查询商 ...

  5. 使用webbench做压力测试

    Memcached是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载.它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提供动态.数据库驱动网站的速度.下文介绍的是在Ubu ...

  6. ios开发之--[_NSInlineData objectForKeyedSubscript:]

    reason: '-[_NSInlineData objectForKeyedSubscript:]: unrecognized selector sent to instance 0x7fa2049 ...

  7. java.util.concurrent.RejectedExecutionException 线程池饱和

    java.util.concurrent.RejectedExecutionException at java.util.concurrent.ThreadPoolExecutor$AbortPoli ...

  8. JSPatch 部署安全策略

    本文转载至 http://blog.cnbang.net/tech/2879/ 使用 JSPatch 有两个安全问题: 传输安全:JS 脚本可以调用任意 OC 方法,权限非常大,若被中间人攻击替换代码 ...

  9. Github上star和fork比较高的vim配置方案

    https://github.com/amix/vimrchttps://github.com/humiaozuzu/dot-vimrchttps://github.com/spf13/spf13-v ...

  10. golang文件传输服务

    续上篇,本篇介绍一个完整的golang文件传输服务器. 完整的代码可以看服务器,客户端 网络使用的框架如上篇介绍,这里就不再复述. 首先定义3个命令码: const ( request_file = ...