Geeks With Blogs

News Awarded Microsoft MVP C#.NET - 2007, 2008 and 2009


I am born in Bangladesh and currently live in Melbourne, Australia. I am a Microsoft Certified Application Developer MCAD Chartered Member (C# .Net)and born in Bangladesh.
I am founder and Chief Executive Officer of
Simplexhub, a highly experienced software development company based in Melbourne Australia and Dhaka, Bangladesh. Co-founder and core developer of Pageflakes www.pageflakes.com.
Simplexhub, is on its mission to build a smart virtual community in Bangladesh and recently launched beta realestatebazaar.com.bd an ASP.NET MVC application written in C#.NET.


Some of My Articles
Flexible and Plugin based .Net Application..
Mass Emailing Functionality with C#, .NET 2.0, and Microsoft® SQL Server 2005 Service Broker'
Write your own Code Generator or Template Engine in .NET
Shahed Khan blog

Recently I had to display some hierarchical data in a treeview. I looked around and found JQuery treeview can transforms an unordered list into an expandable and collapsable tree, and supports both location and cookie based persistence.
treeview1
Fig: JQuery Treeview

As I was dealing with a large amount of data I needed something that will allow me to navigate through the data asynchronously, and I found jQuery Treeview fits well for my purpose. I found this demo of Lazy Loading Tree and I needed to implement similar functionality where the JQuety Treeview communicates to a ASP.NET Webservice.

Problem 1: Unfortunately the codes that ships with the demo do not work with ASP.NET Webservice out of the box. First of all if you have downloaded the TreeView plugin from this link http://bassistance.de/jquery-plugins/jquery-plugin-treeview/ you will notice the "jquery.treeview.async.js" file uses $.getJSON method to make AJAX calls to the server. But this is no good for ASP.NET webservice or WCF which expect JSON POST , this function is only useful for simple JSON results returned from arbitrary services.

treeviewasync

Problem 2: However if you download the jquery.treeview.async.js from http://view.jquery.com/trunk/plugins/treeview you will notice the $.getJSON function is commented and an alternative $ajax() method has been used.

treeviewasync2

but this one is still not good for ASP.NET Webservice calls, I am explaining this in a moment.

There are several options available in JQuery to make AJAX calls to the server. They are
1. $.ajax(opt),
2. $(sel).load(url,data,callback)
3. $.get(url,data,callback,type)
4. $.post(url,data,callback,type)
5. $.getJSON(url,data,callback)
6. $.getScript(url,callback)

The complete list of JQuery AJAX "Requests" and "Event" based functions are all listed here. However to get JQuery working with ASP.NET Webservices we should be interested with $.ajax(opt) function, a low level Ajax function which offers to create any kind of Ajax request. This allow us to configure Ajax request with a set of key/value pairs, and all options are optional. We should be aware that ASP.NET AJAX 1.0 includes a number of default settings and built-in features to prevent from JSON hijacking attacks, ASP.NET AJAX webmethods do not enable HTTP GET requests by default. To make a successful call to the ASP.NET webservice using JQuery we need to make sure that the request must be a POST request, and the request's content-type must be: "application/json; charset=utf-8. By now you have already realized that the above $.ajax() call do not fit any of these two requirements. So I attempted to fulfill these requirements and passed more option paramameters as part of the $.ajax() call.

Problem 3: I modified the script to fit the requirements
- the request must be a POST request
- the request's content-type must be: "application/json; charset=utf-8

treeviewasync3

However this did not work either. now I started facing another problem, "Invalid JSON primitive: root."

invalidJSON 

After googling on this issue for a while I found, as the data parameter is a valid JSON object, calling the webservice in this way do not throw any exception, but it also do not produce the desired result either. Instead of passing the data JSON object to the webservice, JQuery automatically serializes and sends it as root = source.

JSONserialize
The solution is to make sure that we pass data parameter as a string instead of a JSON object. Encosia.com has a very good post on this subject "3 mistakes to avoid when using JQuery with ASP.NET AJAX", a must read. Finally I adjusted the script as follows and it started working as desired.

 treeviewFinal
 

Conclusion

I have discussed how to get JQuery treeview working with ASP.NET Webservice. Out of the box treeview ships with "jquery.treeview.async.js" file that is not compatible with ASP.NET Webservices or WCF. To make a successful call to the ASP.NET webservice using JQuery we need to make sure
- the request must be a POST request, and
- the request's content-type must be: "application/json; charset=utf-8.
- the data parameter of the $.ajax() method must be passed as a string.

I hope this will save you some time. Thank you for being with me so far.

Posted on Saturday, July 11, 2009 12:10 AM | Back to top


Comments on this post: ASP.NET Tips : Getting asynchronous JQuery treeview to work with ASP.NET Webservices

# re: ASP.NET Tips : Getting asynchronous JQuery treeview to work with ASP.NET Webservices
Requesting Gravatar...
Nice work, thanks for the info. I use ASP.Net MVC framework so call the Mvc controller actions directly.
Left by Renso on Jul 11, 2009 3:39 AM

# re: ASP.NET Tips : Getting asynchronous JQuery treeview to work with ASP.NET Webservices
Requesting Gravatar...
Magic! I have been addressing this same problem for the last couple of days and had to cover a lot of ground to get things close ... .NET3.5 install, settng JSON going. My last barrier was exactly as you discuss in this article. Thanks.

Your discussion and screenshots of code are so clear.

I'm left with one problem. When my data comes back (finally! thank you) I receive an error:
createNode is not defined.

In your first codeshot you show that function commented out along with the $.getJSON. code. I've added the function back in straight after document ready and before the load call ... ie:
function($) {
function createNode(parent) { .... }
function load (settings, root, child, container) {
$.ajax ... as with your final code shot
}
}

This works to a point - I think I'm just not packaging my JSON return data properly. So will do more with that.
Left by Piquet on Jul 16, 2009 11:59 AM

# re: ASP.NET Tips : Getting asynchronous JQuery treeview to work with ASP.NET Webservices
Requesting Gravatar...
More toiling and no joy. Perhaps others will be receiving the same problem so wonder if you can point me in the right direction. My webservice is returning [I believe] correctly packaged JSON data ... from write to firebug console at line inserted between your code lines 61&62 above, response.d is:

[{"text": "C", "hasChildren": true, "id": "anothernode"}]

but then the .each call to createNode is iterating over each character in the JSON string ... rather than the elements.

Can you advise? Thanks.
Left by Piquet on Jul 16, 2009 3:15 PM

# re: ASP.NET Tips : Getting asynchronous JQuery treeview to work with ASP.NET Webservices
Requesting Gravatar...
Can you please post the codes of your Webservice here. Possibly you are not returning valid JSON type. Did you decorate your webservice and webmethods with correct attributes? ie. [ScriptService] and [ScriptMethod(ResponseFormat = ResponseFormat.Json)]

[ScriptService]
public class MyWebService : System.Web.Services.WebService
{

[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
public List<SomeClass> GetList(string root)
{
....
}
}


Left by Shahed Khan on Jul 17, 2009 1:20 AM

# re: ASP.NET Tips : Getting asynchronous JQuery treeview to work with ASP.NET Webservices
Requesting Gravatar...
You can try this, it should work.

Step 1: Define a custom class as follows

//TheTreeNode class
[Serializable]
public class TheTreeNode
{
public string id { get; set; }
public string text { get; set; }
public bool expanded = true;
public string classes;
public bool hasChildren;
public List<TheTreeNode> children { get; set; }
}

Step 2: return List<TheTreeNode> from your webservice / webmethod

[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
public List<TheTreeNode> BuildSubNavigation(string root)
{
List<TheTreeNode> nodes = new List<TheTreeNode>();
if (root.ToUpper().CompareTo("SOURCE") == 0)
{
TheTreeNode node = new TheTreeNode();
node.text = "C";
node.hasChildren = true;
node.id = "anothernode";
nodes.Add(node);
}
else
{
TheTreeNode node = new TheTreeNode();
node.text = "A";
node.hasChildren = true;
node.id = "somenode";

TheTreeNode node1 = new TheTreeNode();
node1.text = "B";
node1.hasChildren = true;
node1.id = "someothernode";
nodes.Add(node);

nodes.Add(node1);
}
return nodes;
}


Left by Shahed Khan on Jul 17, 2009 1:46 PM

# re: ASP.NET Tips : Getting asynchronous JQuery treeview to work with ASP.NET Webservices
Requesting Gravatar...
Thanks Shahed, I had not decorated the web method with the response format - however, I believe that the service was already returning application/json responses due to web.config settings.

I have uncovered my problem - as my webservice returned a string I needed to eval() that response. So, from your code shot line 62 above I altered to:
$.each(eval('('+ response.d + ')'), createNode, [child]);
and everything began working fine.

I guess this is not the best resolution. I'm not sure of how I should alter my service to return a list value that does not need to be eval()ed.
Left by Piquet on Jul 17, 2009 1:52 PM

# re: ASP.NET Tips : Getting asynchronous JQuery treeview to work with ASP.NET Webservices
Requesting Gravatar...
Thanks Shahed. As discussed by email your last response outlining the custom class was the correct path to go down to cure the .eval calls to my response data. I guess this shows that it took me longer than 6 minutes to compose my previous comment!
Left by Piquet on Jul 27, 2009 8:41 AM

Your comment:
 (will show your gravatar)


Copyright © Shahed Khan | Powered by: GeeksWithBlogs.net