More AjaxPro Serialization Problems with NHibernate Entities

Edit: It seems that disabling lazy loading with NHibernate/ActiveRecord will keep properties from being overridden (and therefore AjaxPro will still see the base property AjaxNonSerializable attributes).  This can still have a negative effect on performance and I would like to fix the actual cause, but at least I can use this solution in the interim.

In my previous post, I mentioned how the bidirectional object references that manage parent-child relationships for a domain model intended for use with NHibernate causes AjaxPro’s JSON serializer to crash with an infinite loop.  The answer to this was to mark the “parent” properties of all child objects with an [AjaxNonSerializable] attribute.  In my initial tests, this worked great.  However, when actually using NHibernate to retrieve objects from the database, I’m back to my original crashing problem.

The crash is occurring because of how NHibernate creates new instances of objects from the database.  It is actually inheriting from your base object and returning an instance of that instead.  So instead of getting a Blog object, you are getting an instance of the Blog_NHibernate_proxy class which derives from Blog (that is not the actual naming convention, but illustrates the point).

The [AjaxNonSerializable] attribute doesn’t affect derived types, only the type you actually mark with it.  This creates a problem, since the NHibernate proxy types are generated at runtime via reflection.  There is no way that I know of to tell NHibernate to copy over attributes from the base class.  There is no way to tell AjaxPro to check base types for the attributes either.

I hope I am wrong about this.  Here is a simple test case to show that the AjaxPro serialization attributes only affect the defined type:

using System; using System.Text; using AjaxPro; using NUnit.Framework; namespace Ifw.Cgd.Tests.AjaxPro { public class Foo { public virtual string Name { get { return _test; } set { _test = value; } } [AjaxNonSerializable] public virtual string Name2 { get { return _test2; } set { _test2 = value; } } private string _test = ""; private string _test2 = ""; } public class Bar : Foo { public override string Name2 { get { return "overriden"; } set { base.Name2 = value; } } public virtual string Name3 { get { return _test3; } set { _test3 = value; } } private string _test3 = ""; } [TestFixture] public class AjaxProJsonTests { public string ajaxSerialize(object o) { StringBuilder sb = new StringBuilder(); JavaScriptSerializer.Serialize(o, sb); return sb.ToString(); } [Test] public void CanSerializeBaseObject() { Foo x = new Foo(); x.Name = "test"; x.Name2 = "test2"; //should be ignored by AjaxPro string js = ajaxSerialize(x); Console.WriteLine("Foo JSON: " + js); Foo abc = JavaScriptDeserializer.DeserializeFromJson<Foo>(js); Assert.AreEqual("test", abc.Name, "Foo.Name not set properly"); Assert.AreNotEqual("test2", abc.Name2, "Foo.Name2 should not be serialized"); } [Test] public void CanSerializeInheritedObject() { Bar x = new Bar(); x.Name = "test"; x.Name2 = "test2"; //should be ignored by AjaxPro x.Name3 = "test3"; string js = ajaxSerialize(x); Console.WriteLine("Bar JSON: " + js); Bar abc = JavaScriptDeserializer.DeserializeFromJson<Bar>(js); Assert.AreEqual("test", abc.Name, "Foo.Name not set properly"); Assert.AreEqual("test3", abc.Name3, "Foo.Name3 not set properly"); Assert.AreNotEqual("test2", abc.Name2, "Foo.Name2 should not be serialized"); } } }

Here is the output:

Foo JSON: {“Name”:”test”}
Bar JSON: {“Name2″:”overriden”,”Name3″:”test3″,”Name”:”test”}

If anyone knows a way around this, I would LOVE to hear it.  Thanks.


2 comments so far

  1. Ayende Rahien on

    AjaxPro seems to violate OOP in this case, can you fix that?
    NH is behaving correctly from its point of view.

  2. ifwdev on

    AjaxPro is open source so I may take a look at it when I get a minute. I have posted this to the AjaxPro Google Group as well. I’m sure there are other people trying to use the same thing…

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: