Archive for the ‘NHibernate’ Category

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.

AjaxPro + NHibernate = Crash

The Problem

I’m currently using Castle ActiveRecord (which builds on NHibernate) for a web project. One problem I was having was pretty annoying when trying to access NHibernate-generated entities as JavaScript objects via Ajax.NET Professional. ASP.NET would hang for a while and then crash completely with the dreaded “Application Unavailable” error from IIS (or something like that).

With no error messages or stack trace, I immediately blamed the NHibernate proxy objects as the reason why this was happening. On this assumption, I started considering what would be involved to use DTOs instead of the actual domain objects. These would be simpler and hopefully, serializable. After going down that path and getting frustrated by the added effort required to make that solution work, I decided to come back to the AjaxPro serialization issue and see if I could figure out what the problem was.

The Cause

After writing some serialization tests using manually created instances of my domain models (not proxies that were generated from the NHibernate repository), I found that I had the same problem. Great, I thought, my class hierarchy is just too complex for the serializer to handle…

Actually, after considering what is happening in the JSON conversion process, it started to make sense. When using ActiveRecord (or NHibernate) you need bidirectional references with any collections (or else you lose a lot of functionality). So the Post object needs to have a Blog property referencing its parent object (which has a collection of Posts as well). Hence the reason for the crash: an infinite loop.

The Solution

Any circular references in your class relationships need to be excluded from serialization by marking those properties with [AjaxPro.AjaxNonSerializable] (in this case, the Blog property of the Post object). If you are a DDD purist, you may not like the idea of tacking attributes all over your domain model, but I already bit that bullet when going with ActiveRecord over pure NHibernate anyway.

Keep in mind that if you are passing JavaScript proxy objects back to the server for deserialization, you will need to reconnect the parent-child associations or NHibernate won’t be able to save them correctly. It is a little work, but much less than using DTOs with a ton of duplicated properties.

Example:

    using System;
    using System.Collections;

    using Castle.ActiveRecord;

    [ActiveRecord]
    public class Blog : ActiveRecordBase
    {
        ...

        private IList posts = new ArrayList();

        ...
        [HasMany(typeof(Post), Inverse=true)]
        public IList Posts
        {
            get { return posts; }
            set { posts = value; }
        }

The Post class:

    [ActiveRecord]
    public class Post : ActiveRecordBase
    {
        ...

        private Blog blog;

        ...
        [AjaxPro.AjaxNonSerializable]
        [BelongsTo("BlogId")]
        public Blog Blog
        {
            get { return blog; }
            set { blog = value; }
        }

I think that it would be helpful if AjaxPro would check for these kinds of things and throw an Exception instead of just crashing, but the rest of it works quite well so I won’t complain too much there. It would also be nice if you didn’t have to wire up bidirectional associations to make NHibernate work. I suppose we have to work with the tools we are given though…