Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

ASP.NET Lazy Content Loading Through WCF REST Service

0.00/5 (No votes)
26 Mar 2010 1  
Using WCF REST services to implement dynatree plug-in of jQuery for Lazy loading of child nodes

Introduction

Lazy loading of the content on a web page is basically deferring the load of the content until it is needed. We will try implementing this concept of Lazy content loading in a webpage through a jQuery plug-in called Dynatree.

Dynatree is an open source jQuery tree plug-in that allows to dynamically create an HTML tree view control using JavaScript. More details on this can be found at http://dynatree.googlecode.com.

We will implement the lazy loading of the branches through a REST service written using WCF. Data transfer of the tree nodes will be done through JSON.

I have selected REST services over the conventional webservice because; REST services are a better and simpler option to share the data. To implement REST services, .NET 3.5 has introduces webHttpBindings in WCF. This binding helps to publish our normal WCF service as per the standard of REST.

What are REST Services?

REST stands for Representational State Transfer, this means that each unique URL represents some object. Any REST service can be accessed using the standard HTTP GET or POST request. REST services are lightweight as no extra XML markup is used for transfer and the results are easy to understand and human readable.

Output

1.JPG

5.JPG

Development Environment

  • Framework: .NET 3.5
  • Environment: VS 2008
  • Language: C#
  • jQuery Frameworkversion: v1.3.2

Prerequisite

  1. Basic knowledge of WCF
  2. Basic Knowledge of jQuery

Create Project

Create a new ASP.NET Web Application with name “LazyLoading”.

Tree Node Class

Now we will define a class to store the node data, which will be used to pass the information from server to the client in the form of JSON.

Add a class in the project with name “TreeNode”. The class will look like this:

public class TreeNode
	{
		///<summary>
		/// Title of the Node
		///<summary>
		public string title { get; set; }
		///<summary>
		/// Parent node of leaf node.
		///<summary>
		public bool isFolder { get; set; }
		///<summary>
		/// Lazy loading enabled or not.
		///<summary>
		public bool isLazy { get; set; } 
		///<summary>
		/// Hidden id of the Node
		///<summary>
		public string key { get; set; } 
	}

AJAX Enabled WCF Service

Now we will add an AJAX-enabled WCF Service to the project with name TS.svc.

3.JPG

TS.svc will be the service file where we will be defining our methods which can be invoked from jQuery. In our case, we have only one method with name GetNode which takes “key” parameters and generated nodes of the tree on the basis of the key and return the list of TreeNode to the caller.

To get the list of Nodes, our client will make request to our REST service as follows:

  • http://localhost:5678/TS.svc/GetNodes/1 - To load all the root nodes
  • http://localhost:5678/TS.svc/GetNodes/11234 - To load the child nodes for the node having id as 11234

Code of our WCF Service is as follows:

[ServiceContract(Namespace = "")]
	[AspNetCompatibilityRequirements(
		RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
	public class TS
	{
		[OperationContract]
		[WebInvoke(Method = "GET",
		ResponseFormat = WebMessageFormat.Json,
		UriTemplate = "GetNodes/{key}",
		BodyStyle = WebMessageBodyStyle.Bare)]

		public List<TreeNode> GetNodes(string key)
		{
			Thread.Sleep(1000); // For showing the delay effect
			List<TreeNode> collection = new List<TreeNode>();
			string NodeTitle = string.Empty;
			//Generate the title of the node
			if (key.Equals("1"))
			{
				NodeTitle = "Root";

			}
			else 
			{
				NodeTitle = string.Format("Child Key-{0}", key);
			}
			//Generate some random nodes
			for (int i = 1; i <= new Random().Next(15); i++)
			{
				int rC = new Random().Next(3) + 1;
				collection.Add(
					new TreeNode()
					{
						isFolder = (i % rC != 0),
						isLazy = (i % rC != 0),
						key = string.Format
							("{0}{1}", key, i), 
						title = string.Format("{0}-[{1}]", 
						NodeTitle, i)
					}
						);
			}
			return collection;
		}
	}

In the above code, you can find out some attributes used. Please find the details for each below:

AspNetCompatibilityRequirementsMode: You can then add an explicit attribute to your implementation class to make the ASP.NET context available in your application:

ServiceContract: Namespace for the service to be specified. We are using blank as it is a test service and does not contain any URI format.

[OperationContract]
[WebInvoke(Method = "GET",
ResponseFormat = WebMessageFormat.Json,
UriTemplate = "GetNodes/{key}",
BodyStyle = WebMessageBodyStyle.Bare)]	

In the GetNodes method, we are decorating it with the WebInvoke attribute to specify that the method will be accessed using a standard HTTP GET request and the output of the method call is in the form of JSON. The UriTemplate specifies the path and the format to access the service. UriTemplate class helps us to define Uri formats strings and the template text in the Uri. In our case GetNodes/{key}, where key will be dynamically replaced while calling the service.

In JSON, the bare formatting means generic JSON object without any additional content appended by the WCF. Following is the sample bare JSON generated by our GetNodes method.

4_1.JPG

For our testing, we can access this by simply calling http://localhost:5678/TS.svc/GetNodes/1.

WCF Configuration

<system.serviceModel>
  
    <behaviors>
      <endpointBehaviors>
        <behavior name="LazyLoading.TSAspNetAjaxBehavior">
          <webHttp/>
        </behavior>
      </endpointBehaviors>
      <serviceBehaviors>
        <behavior name="TimeTrakkerServiceBehavior">
          <serviceMetadata httpGetEnabled="true"/>
          <serviceDebug includeExceptionDetailInFaults="true"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
     <services>
      <service name="LazyLoading.TS" behaviorConfiguration="TimeTrakkerServiceBehavior" >
        <endpoint  behaviorConfiguration="LazyLoading.TSAspNetAjaxBehavior"
         binding="webHttpBinding" contract="LazyLoading.TS" />
      </service>
    </services>
  </system.serviceModel>

For our REST service, we are using the binding as WebHttpBinding as we need to configure our endpoint that is exposed through HTTP GET request instead of conventional SOAP message. The rest of the configuration is straight forward.

Client Side Code

Include the jQuery framework and the dynatree plug-in in the page.

  <link href="CSS/Jquery.css" rel="stylesheet" type="text/css" />
    <script src="Script/jquery.js" type="text/javascript"></script>
    <script src="Script/ui.core.js" type="text/javascript"></script>
    <script language="jscript" src="Script/jquery.dynatree.js" 
	type="text/javascript"></script>

JavaScript

$("#tree").dynatree({
                title: "Lazy Tree",
                rootVisible: true,
                fx: { height: "toggle", duration: 200 },
                initAjax: {
                    url: "TS.svc/GetNodes/1"

                },

Here we are passing the URL by providing the key as 1; this will load all the root nodes of our tree.

onActivate: function(dtnode) {
                    $("#echoActive").text(dtnode.data.title);
                },

onActivate function will help if we want to handle the click event an any node, for example we want to load something else on the basis of node click then this function can be used, we can get the current selected node id dtnode.data.key and the title as dtnode.data.title.

onLazyRead: function(dtnode) {

                    dtnode.appendAjax({
                        url: "TS.svc/GetNodes/" + dtnode.data.key
                    });
                }

onLazyRead will be fired if we click on any lazy node of the tree, here we are calling our GetNode method by passing the key of the node.

Conclusion

This article is the ASP.NET implementation of jQuery dynatree plugin. As a web developer, many times we need to develop such trees where lazy loading for huge tree structure becomes necessary for performance reasons.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here