Archive for the ‘JavaScript’ Category

Ajax.NET Professional with Mootools (part 2)

This is an update to my original post.  That version was a preliminary attempt and should not be used in production.

The MootoolsTypeJavaScriptProvider is a compatibility layer between AjaxPro and Mootools

The provider now supports most of the native AjaxPro javascript functionality.  The idea is to maintain as much compatibility as possible with the original AjaxPro javascript library to eliminate the need for changes to existing code.

Download Version 1.6 Binaries
Download Source Project

Tested on Internet Explorer 6 & 7, Firefox 1.5 & 2.0, Opera 9.


Working AjaxPro javascript options:

  • Fully compatible method signature for invoking calls from script: MyServerClass.Method(<arguments…>, callback, context, onError);
  • Synchronous requests (no change in syntax)
  • Compatible with most Global AjaxPro options & event handlers:
    • AjaxPro.onLoading
    • AjaxPro.onError
    • AjaxPro.onTimeout
    • AjaxPro.onStateChanged
    • AjaxPro.timeoutPeriod

Not working:

  • Support for any IE version less than 6 (this is a requirement for Mootools in general)
  • Tokens (they are implemented on the client, but when you set AjaxPro to RenderJsonCompliant, it stops emitting/checking the token data required.  An modified build of AjaxPro is required to fix this)
  • AjaxPro.cryptProvider
  • AjaxPro.queue (see below)
  • Using IFrames instead of XmlHttpRequest


Additions / Breaking Changes from default AjaxPro javascript lib:

  • AjaxPro.toJSON simply references Mootools Json.toString.  The resulting JSON string may be different.
  • AjaxPro.queue does not work, however you can toggle request queuing by using the AjaxPro.queueRequests flag I’ve added (defaults to true).  This is just a wrapper for Mootools autoCancel property which handles the actual request queue.
  • Aborting asynchronous requests uses different syntax.  To abort a request, use the following:
    var req = MyServerClass.Method(...); req.cancel();

    This is using the native cancel function from the Mootools XHR class.

Usage

  • Copy the mootools-core.js file into your project
  • Reference the Ifw.AjaxNet.dll assembly in your project
  • Adjust the AjaxPro web.config options in ajaxNet/ajaxSettings:
<scriptReplacements> <file name="core" path="~/res/js/ajaxpro/mootools-core.js"/> <file name="prototype" path=""/> <file name="converter" path=""/> </scriptReplacements> <providers> <typeJavaScriptProvider type="Ifw.AjaxNet.MootoolsTypeJavaScriptProvider, Ifw.AjaxNet"/> </providers> <oldStyle> <renderJsonCompliant/> <renderDateTimeAsString/> </oldStyle>

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.