5943 Views // 2 Comments // Not Rated

Create Your Own Toolkit - ASP.NET 3.5 AJAX Control Toolkit Inheritance

One of my favorite aspects of the AJAX Control Toolkit is that we were given not only a fully functional web app detailing all of the controls, but also the full source code. As a home-grown .NET developer, exploring the source code of the tool / control I am dealing with is a new and fantastic experience. My inner (and sometimes outer) monologue when working with other people's code is usually as such:

"Why the hell did they do that?"

Now it's:

"Why the hell did they do that?"

...peruse source code...


Anyways, beyond gaining a deeper understand of the controls (and Microsoft's AJAX implementation as a whole), we also have the ability to easily extend these controls (in terms of OO development; not to be confusted with the "Extender Control" which is a different Microsoft AJAX concept) and literally inherit the JavaScript that builds them.

Before reading any further, a word of warning: this might be a bit advanced for anyone who hasn't used JavaScript prototypes yet or played much with Microsoft's AJAX framework. I encourage you to do so before going further (which I never do myself when an article tells me to, so whatever).

Here's the scenario I encountered: The animation framework included in the AJAX Control Toolkit (ACT heretofore) handles typical events to kick off animations (clicks, hovers, etc.) Of course, I needed to work with onmouseup to show an animation as the user dragged-and-dropped over a region; this was not supported.

My first approach literally entailed going into the source of the ACT, copy and pasting the code for the click mouse events across half a dozen files, pasting them verbatim, and doing a find-and-replace from "click" to "mousedown." I recompiled the ACT, copied the new DLL to my project, and it actually worked. The problem then is that, ultimately, we will be dealing with multiple versions of the ACT DLL on our server, and other maintenance nightmares.

Unless you are really into parsing fully-qualified assembly names, commenting lines in and out of web.config files, and renaming "AjaxControlToolkit.dll" to "AjaxControlToolkit.dll.old.modified.june13version.dontusethisfile," then we need a better method to extend these controls – ESPECIALLY if we are deploying our code to an environment like SharePoint.

Fortunately, the AJAX JavaScript framework (and, indeed, JavaScript itself) formally supports full object inheritance! Using the approach I'll outline below, you can create your own cut of the ACT and compile it separately. This way, pages in your web app can either reference your custom toolkit to get enhanced features, or revert to the ACT for consistent, out-of-the-box functionality. Here's what to do:

Code Listing 1

  1. using System;
  2. using System.Web.UI;
  3. using System.ComponentModel;
  4. using AJAX = AjaxControlToolkit;
  5. ...
  6. namespace AssemblyName
  7. {
  8. [AJAX.RequiredScript(typeof(AJAX.AnimationScripts))]
  9. [AJAX.ClientScriptResource("AssemblyName.ClassName", "AssemblyName.ClassName.js")]
  10. [TargetControlType(typeof(Control))]
  11. public class ClassName : AJAX.ClassName
  12. {
  13. ...
  14. protected override void OnPreRender(EventArgs e)
  15. {
  16. base.OnPreRender(e);
  17. ...
  18. }
  19. ...
  20. }
  21. }

This class in herits from the ACT class that you want to extend. The first attribute that decorates it ensures that any scripts in the enum you specify will be downloaded and referenced on the client. (For my situation, "AnimationScripts" is a magical value that brings down all the scripts the animation framework has created or just uses.) The second allows your class to find and access its JavaScript file in the assembly, kind of like partial classes in .NET 2.0.

Finally, TargetControlType specifies what your class can extend. For broader concepts (like animation) this is opened up to all web controls. However, for more specific functionality, (such as Collapsible Panels) you can speficy "Panel" as the target control type. If violated, this is what throws the familiair "This type can't extend controls of that type..." AJAX exception.

All you have left to so is implement your extensions. Mostly, on the managed side of things, this entails declaring properties, helper methods, etc. All of the "work" (in terms of UI elements) is done on the client side. The server side class' job is really instead to initialize, wire, and host.

Here's some boilerplate code for the JavaScript file:

Code Listing 2

  1. Type.registerNamespace('AssemblyName.ClassName');
  2. AssemblyName.ClassName = function(element)
  3. {
  4. AssemblyName.ClassName.initializeBase(this, [element]);
  5. //declare members
  6. }
  7. AssemblyName.ClassName.prototype =
  8. {
  9. initialize : function()
  10. {
  11. AssemblyName.ClassName.callBaseMethod(this, 'initialize');
  12. //initialization code
  13. },
  14. dispose : function()
  15. {
  16. //clean up code
  17. }
  18. //events, methods, and properties
  19. }
  20. AssemblyName.ClassName.registerClass('AssemblyName.ClassName', AjaxControlToolkit.ClassName);

At a glance, this looks like a normal JavaScript prototype. The one subtle different is the last third of the last line. The second parameter of the registerClass method is the class that your prototype is inheriting from. Notice that we are directly, literally, inheriting one JavaScript class from another! Remember, JavaScript is OO, and here we are dealing with the most "OO" concept of all: inheritance.

Everything that happens in the class you are inheriting from is happening here as well. If your base class has a button in it somewhere and a click event is wired up to it, you've got all that going on in your prototype.

So think back to my initial problem: there weren't enough events being handled in the animation framework. So in my derived class, I merely add those events; the ones in the base class still work normally!

Finally, we need to wire everything up so that the JavaScript file is included as a web resource. Open the AssemblyInfo.cs file, and add the following:

Code Listing 3

  1. using System.Web.UI;
  2. ...
  3. [assembly: WebResource("AssemblyName.ClassName.js", "text/javascript")]

There is a project type in Visual Studio 2008 that does most of this for you, but it's good to go through it once from scratch to understand everything going on. Have fun!

3 Tags

No Files

2 Thoughts

Hi, exactly joined
Hi, just joined the forum and looking forward to finding out more, looks like a useful place! Thanks! brtghbgf!! xx
Accutleburb, 11/10/2013
Hi, exactly joined
Hi, just joined the forum and looking forward to finding out more, looks like a useful place! Thanks! brtghbgf!! xx
Accutleburb, 11/10/2013

Your Thoughts?

You need to login with Twitter to share a Thought on this post.