How to create a complete AJAX Server Control. Part 3.

Posted on Updated on

In the previous posts we have created the server control and JS representation in the client. We have also added functionality to add new items in the server and add a client event to display and hide the items in the shopping cart (see part 1 and part 2).

The next step in the development of the server control will be to enable the client side to access the data stored in the control and fire client events that could be handled in the web page.

You may probably think that from the client side you can access to the items stored in the cart by inspecting the DOM and using JQuery, for instance. True. But it’s not the natural way of doing it and it gives you very little margin if you want to change the html that is rendered because then, you should have to go and update all the code that reads from the control.

To implement this functionality I’m going to define some helper methods in the class to interact easily with the Viewstate an avoid casting in the code.

ShoppingCart.cs

 
	public class ShoppingCart : ScriptControlBase
	{
		//...
		#region Helper methods
		/// 
		/// Retrieves the property value from the ViewState
		/// 
		/// Type of value
		/// Property to retrieve
		/// value to be used in case it's not initialised.
		/// 
		[DebuggerStepThrough]
		protected V GetPropertyValue(string propertyName, V nullValue)
		{
			if (ViewState[propertyName] == null)
			{
				return nullValue;
			}
			return (V)ViewState[propertyName];
		}

		/// 
		/// Save the property value in the ViewState
		/// 
		/// Property type
		/// Property name
		/// Value
		[DebuggerStepThrough]
		protected void SetPropertyValue(string propertyName, V value)
		{
			ViewState[propertyName] = value;
		}
		#endregion
		//...
	}

Once we have these methods we can start adding the real juicy stuff.

First of all we need to add a namespace to get the JS serialisation classes to be able to serialise and de-serialise JSON objects.

Now to add a client event (I’ve chosen Double Click on the Cart image) we need to add a property in where we will set the name of the JS function that we need to call for the event. In the code below you can see the property OnClientCartDoubleClick. Notice all the attributes added to the property:

  • CategoryAttribute and Description are the standard attributes to get the nice integration with the properties window in Visual Studio
  • ExtenderControlEvent is used to say that this property is used to define a control event in the client (it’s declared in the AjaxControlToolkit and used via reflexion at runtime)
  • ClientPropertyName(“cartDoubleClick”) helps us to change the name of the event in the client (by default uses the property name unless it’s renamed using this attribute)

I’m also going to add a property in the client called items that will contain the items in the cart the same way they are available in the server so that you can read then in the web page. To do that, the only difference from the event is the attribute that we need to use to do that, now we’ll use ExtenderControlProperty instead of ExtenderControlEvent. To send the items to the client I’m using JSON serialisation so they can be easily serialised to string and they will be deserialised in the client side.

ShoppingCart.cs

	using System.Web.Script.Serialization;

	public class ShoppingCart : ScriptControlBase
	{
		//...
		#region Client Events
		/// 
		/// Client function that will be executed for CartDoubleClick
		/// 
		[CategoryAttribute("Client Events")]
		[Description("Client function that will be executed for OnClientCartDoubleClick.")]
		[ExtenderControlEvent]
		[ClientPropertyName("cartDoubleClick")]
		public string OnClientCartDoubleClick
		{
			[DebuggerStepThrough]
			get { return GetPropertyValue("OnClientCellDoubleClick", (string)null); }
			[DebuggerStepThrough]
			set { SetPropertyValue("OnClientCellDoubleClick", value); }
		}

		#endregion

		#region Client Properties
		/// 
		/// Client property
		/// 
		[Browsable(false)]
		[ExtenderControlProperty]
		[ClientPropertyName("items")]
		public string ClientItems
		{
			get
			{
				JavaScriptSerializer jser = new JavaScriptSerializer();
				string jsonItems = jser.Serialize(items);
				return jsonItems;
			}
			set { }
		}
		#endregion
		//...
	}

To implement the client side is even easier.

Event (cartDoubleClick):

  1. We have to add the methods to hook and unhook the event in the class
    • add_cartDoubleClick: Convention used by MS AJAX Framework to hook (add_ + “eventname”)
    • remove_cartDoubleClick: Convention used by MS AJAX Framework to unhook (remove_ + “eventname”)
  2. Now we can add a handler to handle the double click event of the image ( _addHandlers and _clearHandlers )
  3. In the section HTML Events of the JS class I have created a method to call the client event (_onCartDoubleClick) in where I check if the event is hooked, I call the function that was fetined in the server side

Property (items):

  1. We have to add the methods for the get/set in the class
    • get_items: Convention used by MS AJAX Framework for the get (get_ + “propertyname”)
    • set_items: Convention used by MS AJAX Framework for the set (set_ + “propertyname”)
  2. In the set property I deserialise the items into objects and assign the array to the _items property (remember that as a convention it’s used underscore to express the meaning of private in a class)

ShoppingCart.js

$ShoppingCart.prototype._addHandlers = function()
{
	$addHandlers(this._cartImage, {
		dblclick: Function.createDelegate(this, this._cartDoubleClick)
	});

	//...
}

$ShoppingCart.prototype._clearHandlers = function()
{
	// remove event handlers to avoid memory leaks
	$clearHandlers(this._cartImage);
	//...
}

// ---------------------- HTML Events -----------------------

$ShoppingCart.prototype._infoImageClick = function(e)
{
	this._itemsDiv.style.display = "block";
}

$ShoppingCart.prototype._closeItemsImageClick = function(e)
{
	this._itemsDiv.style.display = "none";
}

$ShoppingCart.prototype._cartDoubleClick = function(e)
{
	e.stopPropagation();

	// raise the client event
	this._onCartDoubleClick(e);
}
// --------------------- Client side Events -------------
// defined in the server side as:
//		[ExtenderControlEvent]
//		[ClientPropertyName("cartDoubleClick")]

$ShoppingCart.prototype.add_cartDoubleClick = function(handler)
{
	this.get_events().addHandler("cartDoubleClick", handler);
}
$ShoppingCart.prototype.remove_cartDoubleClick = function(handler)
{
	this.get_events().removeHandler("cartDoubleClick", handler);
}
$ShoppingCart.prototype._onCartDoubleClick = function(e)
{
	if (!this._events) return;
	var handler = this._events.getHandler("cartDoubleClick");
	if (handler) handler(e);
}

// ---------------------- Client side Properties ----------------------------
$ShoppingCart.prototype.get_items = function() { return this._items; }
$ShoppingCart.prototype.set_items = function(value)
{
	this._items = Sys.Serialization.JavaScriptSerializer.deserialize(value);
}

To use the newly created event and property I have defined a JS function in the web form that enumerated the items in the control and displays a message box when the cart image is double clicked.

ShoppingCart.aspx


    
    
        function onCartDoubleClickInTheClient(e)
        {
            // we use $find to retrieve an AJAX component ( $get to retrieve the HTML element )
            var cart = $find("Cart1");

            var items = cart.get_items();
            var itemsStr = "";
            for (var i = 0; i < items.length; i++)
            {
                itemsStr += "\n  " + i + " - " + items[i].Text;
            }

            alert("Double Click! : " + itemsStr);          
        }
        
    


    
    
    
    <div>
        
    </div>
    

If you view source in the browser you can see how the new control has been created passing all the added elements.

Sys.Application.initialize();
Sys.Application.add_init(function() {
    $create(
    AjaxControl.ShoppingCart, 
    {"items":"[{\"DateAdded\":\"\\/Date(1245633460294)\\/\",\"Text\":\"Learn Ajax in 1h!\",\"Description\":\"If you want to learn Ajax in 1h, this is your book.\",\"Quantity\":1,\"TotalPrice\":28.9},{\"DateAdded\":\"\\/Date(1245633460295)\\/\",\"Text\":\"Ajax for Dummies!\",\"Description\":\"If you think that you are hopeless, this is your book.\",\"Quantity\":2,\"TotalPrice\":70},{\"DateAdded\":\"\\/Date(1245633460295)\\/\",\"Text\":\"Advanced Ajax Server Controls\",\"Description\":\"When you want to go further, this is your book.\",\"Quantity\":1,\"TotalPrice\":86.5}]"}, 
    {"cartDoubleClick":onCartDoubleClickInTheClient}, 
    null, 
    $get("Cart1"));
});

We are closer to have all the functionality ready to be used.

You can download the code here.

Important: I couldn’t upload the file as it was a zip file, so I added the extension jpg. After saving the file, remove the extension and unzip it normally.

2 thoughts on “How to create a complete AJAX Server Control. Part 3.

    Ankit Singh said:
    January 5, 2012 at 08:04

    Hi,

    I was reading your article and I would like to appreciate you for making it very simple and understandable. This article gives me a basic idea of ASP.Net AJAX Server Control: UpdateProgress, UpdatePanel and it helped me a lot. Thanks for sharing with us. Check out this link too its also having nice post with wonderful explanation on ASP.Net AJAX Server Control: UpdateProgress, UpdatePanel…….

    http://mindstick.com/Articles/b1a42dcf-2f81-4141-b9d0-8180565bfefd/?ASP.Net%20AJAX%20Server%20Control:%20UpdateProgress,%20UpdatePanel

    Thanks Everyone for your nice precious post.

    helpful hints said:
    May 17, 2013 at 20:17

    I’ve been surfing online more than 3 hours lately, yet I never discovered any interesting article like yours. It is pretty worth sufficient for me. In my view, if all site owners and bloggers made good content material as you did, the net will be a lot more useful than ever before.

Leave a Reply

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

WordPress.com Logo

You are commenting using your WordPress.com 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