﻿<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
  <channel>
    <title>Jon Henning</title>
    <description>My personal blog on DotNetNuke.</description>
    <link>http://www.dotnetnuke.com/Products/Development/Forge/ComponentWebControls/tabid/873/BlogId/8/Default.aspx</link>
    <language>en-US</language>
    <managingEditor>jon.henning@dotnetnuke.com</managingEditor>
    <webMaster>admin1@dotnetnuke.com</webMaster>
    <pubDate>Thu, 04 Dec 2008 22:46:56 GMT</pubDate>
    <lastBuildDate>Thu, 04 Dec 2008 22:46:56 GMT</lastBuildDate>
    <docs>http://backend.userland.com/rss</docs>
    <generator>Blog RSS Generator Version 3.5.1.19887</generator>
    <item>
      <title>Utilizing the Microsoft AJAX Framework and ClientAPI to Develop Rich Modules: Part III</title>
      <description>&lt;p&gt;As mentioned in &lt;a href="http://www.dotnetnuke.com/Community/Blogs/tabid/825/EntryId/2067/Utilizing-the-Microsoft-AJAX-Framework-and-ClientAPI-to-Develop-Rich-Modules-Part-II.aspx"&gt;Part II&lt;/a&gt; of this series, this entry will focus on another advantage of writing rich client side objects representing our modules on the client side.  One very common use case that comes up again and again is how can one module talk to another on the same page.  For a long time DotNetNuke had this capability from the server side through something called Inter-Module Communication (IMC).  With the adoption of AJAX it is common to hear confusion as to how can IMC work.  The question usually is asked like this.  I have Module1 talking to Module2 just fine until I "enabled AJAX" by wrapping it in an UpdatePanel.  Now Module2 no longer updates when Module1 posts back.  Or another variation is I make a ClientAPI callback that tries to either update the rendering of the module or tries to do IMC and it doesn't work.  Why not?&lt;/p&gt;  &lt;p&gt;To understand why neither of these scenarios works the developer needs to have a basic understanding of what is happening behind the scenes.  An AJAX call into some server-side code should never be about sending a request from the client and have the entire page refresh.  If this is the requirement, then just use a normal postback!  Instead, AJAX calls are about requesting some piece of data (data here could be anything including HTML) that in turn affects the client-side state in some way, usually resulting in some UI update.  One of the primary motivations of using AJAX is to make a more responsive and efficient web experience.  So it makes sense that the AJAX you are adding should be written in such a way to minimize the strain on the server along with the bandwidth of the network.  &lt;/p&gt;  &lt;p&gt;The idea behind the UpdatePanel is to allow only a portion of the page to be posted to the server, have less processing on the server happen than a normal postback, and only send down the updated portions of the page.  This is better than the postback, but not as good as it could be.  For the scenario where a user needs to do some sort of IMC, the UpdatePanel gets rather tricky real quick due to the need for triggers.&lt;/p&gt;  &lt;p&gt;The approach I am pushing is to simply have the module become aware of the other modules it may wish to communicate with on the client.  Once aware, the module can simply interact with the other module's client-side object model, invoking methods and properties as needed.  I mentioned in &lt;a href="http://www.dotnetnuke.com/Community/Blogs/tabid/825/EntryId/2066/Utilizing-the-Microsoft-AJAX-Framework-and-ClientAPI-to-Develop-Rich-Modules-Part-I.aspx"&gt;Part I&lt;/a&gt; of this series that there was an important difference between the initialize and load events.  The load event will fire after &lt;strong&gt;&lt;em&gt;all&lt;/em&gt;&lt;/strong&gt; client-side objects have been initialized.  This offers an ideal place for our modules to become aware of each other.&lt;/p&gt;  &lt;pre class="csharpcode"&gt;&lt;font size="1"&gt;    _onLoad: &lt;span class="kwrd"&gt;function&lt;/span&gt;(src, arg)
    {
        &lt;span class="rem"&gt;//page is completely loaded, you can now access any element or component&lt;/span&gt;
        &lt;span class="kwrd"&gt;var&lt;/span&gt; components = arg.get_components();
        &lt;span class="rem"&gt;//sample of how to do client-side IMC - look for other components we are interested in&lt;/span&gt;
        &lt;span class="rem"&gt;//in this case, we will look for other instances of the same module that are not ourselves&lt;/span&gt;
        &lt;span class="rem"&gt;//but you can communicate with any components&lt;/span&gt;
        &lt;span class="kwrd"&gt;for&lt;/span&gt; (&lt;span class="kwrd"&gt;var&lt;/span&gt; i=0; i&lt;components.length; i++)
        {
            &lt;span class="kwrd"&gt;if&lt;/span&gt; (Object.getTypeName(components[i]) == Object.getTypeName(&lt;span class="kwrd"&gt;this&lt;/span&gt;) &amp;&amp; components[i].get_id() != &lt;span class="kwrd"&gt;this&lt;/span&gt;.get_id())
                &lt;span class="kwrd"&gt;this&lt;/span&gt;.add_propertyChanged(components[i]._delegates.componentPropChangedDelegate);
        }
    },&lt;/font&gt;&lt;/pre&gt;
&lt;style type="text/css"&gt;

.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;

&lt;p&gt;An additional bonus to this event is the arg parameter contains a list of components for us via the get_components property.  We simply need to enumerate the list of components looking for an object of the same type that is not ourself and add an event handler to it.  Obviously, this logic can be tweaked to look for any type of component.  The &lt;a href="http://www.asp.net/ajax/documentation/live/ClientReference/Sys/ComponentClass/ComponentPropertyChangedEvent.aspx"&gt;propertyChanged event&lt;/a&gt; is another feature that the Sys.Component offers.  Whenever we wish to notify other objects of some property changing we simply call &lt;a href="http://www.asp.net/ajax/documentation/live/ClientReference/Sys/ComponentClass/ComponentRaisePropertyChangedMethod.aspx"&gt;raisePropertyChanged&lt;/a&gt;.  In our module's case we will raise the SayHello property changed event when we click a button&lt;/p&gt;

&lt;pre class="csharpcode"&gt;&lt;font size="1"&gt;        &lt;span class="kwrd"&gt;this&lt;/span&gt;.raisePropertyChanged(&lt;span class="str"&gt;'SayHello'&lt;/span&gt;);&lt;/font&gt;&lt;/pre&gt;
&lt;style type="text/css"&gt;

.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;

&lt;p&gt;This event will get trapped by other instances and update the UI accordingly&lt;/p&gt;

&lt;pre class="csharpcode"&gt;&lt;font size="1"&gt;    _onPropChanged: &lt;span class="kwrd"&gt;function&lt;/span&gt;(src, args)
    {
         &lt;span class="kwrd"&gt;this&lt;/span&gt;.showMessage(String.format(&lt;span class="str"&gt;'You {0} to {1} but not to me?'&lt;/span&gt;, args.get_propertyName(), src.get_name()));
    },&lt;/font&gt;&lt;/pre&gt;
&lt;style type="text/css"&gt;

.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;

&lt;p&gt;Notice how we get both the source object that raised the event, along with the propertyName that raised the event.  Obviously this allows for a single event handler to service many different property changed events.  Additionally, it allows for easy interaction with the calling object.  This is effectively all you should need to get your modules talking.  Obviously, each module you talk to could do whatever logic you'd like, including making AJAX calls and updating UI.  &lt;/p&gt;

&lt;p&gt;This concludes the mini-series of blog entries on Microsoft AJAX and the ClientAPI.  Hopefully it gives the reader enough information to go and create a new breed of module, one that fits better into the AJAX era.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;For those interested in my upcoming plans I wanted to mention that I will soon be updating the free module templates &lt;a href="http://www.codeplex.com/codeendeavortemplate"&gt;found on codeplex&lt;/a&gt; which will generate nearly all that has been covered in this series.  Until then, I figured I'd let anyone who is interested play with the package the template creates:  &lt;a href="http://www.dotnetnuke.com/LinkClick.aspx?fileticket=xcDZbpGhDo0%3d&amp;tabid=875&amp;mid=2664"&gt;Install&lt;/a&gt; or &lt;a href="http://www.dotnetnuke.com/LinkClick.aspx?fileticket=7RTCaTtubj0%3d&amp;tabid=875&amp;mid=2664&amp;forcedownload=true"&gt;Source&lt;/a&gt;.  Note:  This module requires DNN5.  I haven't gotten around to updating the manifest yet, that will be done by the time I release the template.  Enjoy!&lt;/p&gt;</description>
      <link>http://www.dotnetnuke.com/Community/Blogs/tabid/825/EntryId/2074/Utilizing-the-Microsoft-AJAX-Framework-and-ClientAPI-to-Develop-Rich-Modules-Part-III.aspx</link>
      <category domain="http://www.dotnetnuke.com/products/development/forge/componentwebcontrols/tabid/873/blogid/31/default.aspx">Core :: ClientAPI</category>
      <author>jon.henning@dotnetnuke.com</author>
      <comments>http://www.dotnetnuke.com/Community/Blogs/tabid/825/EntryId/2074/Utilizing-the-Microsoft-AJAX-Framework-and-ClientAPI-to-Develop-Rich-Modules-Part-III.aspx#Comments</comments>
      <guid isPermaLink="true">http://www.dotnetnuke.com/Community/Blogs/tabid/825/EntryId/2074/Utilizing-the-Microsoft-AJAX-Framework-and-ClientAPI-to-Develop-Rich-Modules-Part-III.aspx</guid>
      <pubDate>Wed, 12 Nov 2008 12:45:23 GMT</pubDate>
      <slash:comments>2</slash:comments>
      <trackback:ping>http://www.dotnetnuke.com/DesktopModules/Blog/Trackback.aspx?id=2074</trackback:ping>
    </item>
    <item>
      <title>Utilizing the Microsoft AJAX Framework and ClientAPI to Develop Rich Modules: Part II</title>
      <description>&lt;p&gt;In part one of this series I mentioned that the Microsoft AJAX Framework along with the ClientAPI are different than a lot of other javascript frameworks since they allow for an end-to-end integration directly with .NET.  This entry will discuss how the this integration makes life easier for a DotNetNuke module developer by allowing communication to and from the server to be simple.   &lt;/p&gt;  &lt;p&gt;The Microsoft AJAX Framework allows for server-side code to add a reference to the js file, initialize the client-side object, and pass in property values by having any control implement the &lt;a href="http://www.asp.net/AJAX/Documentation/Live/tutorials/IScriptControlTutorial1.aspx"&gt;IScriptControl interface&lt;/a&gt;.  For a DotNetNuke module this means a usercontrol typically inheriting from PortalModuleBase.  Since we plan on having both our Edit control and View controls implement the interface we will create a base class to encapsulate the common logic.  Perhaps this base class will make it into the core some day, but until then the &lt;a href="http://www.codeplex.com/codeendeavortemplate"&gt;CodeEndeavors templates&lt;/a&gt; will include it.&lt;/p&gt;  &lt;pre class="csharpcode"&gt;&lt;font size="1"&gt;    &lt;span class="kwrd"&gt;Public&lt;/span&gt; &lt;span class="kwrd"&gt;Class&lt;/span&gt; AjaxPortalModuleBase
        &lt;span class="kwrd"&gt;Inherits&lt;/span&gt; Entities.Modules.PortalModuleBase : &lt;span class="kwrd"&gt;Implements&lt;/span&gt; IScriptControl

        &lt;span class="kwrd"&gt;Public&lt;/span&gt; &lt;span class="kwrd"&gt;Event&lt;/span&gt; AddScriptComponentDescriptors(&lt;span class="kwrd"&gt;ByVal&lt;/span&gt; Descriptor &lt;span class="kwrd"&gt;As&lt;/span&gt; ScriptComponentDescriptor)
        &lt;span class="kwrd"&gt;Public&lt;/span&gt; &lt;span class="kwrd"&gt;Event&lt;/span&gt; AddScriptReferences(&lt;span class="kwrd"&gt;ByVal&lt;/span&gt; References &lt;span class="kwrd"&gt;As&lt;/span&gt; List(Of ScriptReference))
        &lt;span class="kwrd"&gt;Public&lt;/span&gt; &lt;span class="kwrd"&gt;Event&lt;/span&gt; AddLocalizedMessages(&lt;span class="kwrd"&gt;ByVal&lt;/span&gt; Messages &lt;span class="kwrd"&gt;As&lt;/span&gt; Dictionary(Of &lt;span class="kwrd"&gt;String&lt;/span&gt;, &lt;span class="kwrd"&gt;String&lt;/span&gt;))

&lt;span class="preproc"&gt;#Region&lt;/span&gt; &lt;span class="str"&gt;"Event Handlers"&lt;/span&gt;
        &lt;span class="rem"&gt;'Enable Control Callbacks for this module&lt;/span&gt;
        &lt;span class="rem"&gt;'We are passing in the second argument to ensure our callbacks reach this instance of our object&lt;/span&gt;
        &lt;span class="kwrd"&gt;Private&lt;/span&gt; &lt;span class="kwrd"&gt;Sub&lt;/span&gt; Page_Init(&lt;span class="kwrd"&gt;ByVal&lt;/span&gt; sender &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Object&lt;/span&gt;, &lt;span class="kwrd"&gt;ByVal&lt;/span&gt; e &lt;span class="kwrd"&gt;As&lt;/span&gt; System.EventArgs) &lt;span class="kwrd"&gt;Handles&lt;/span&gt; &lt;span class="kwrd"&gt;Me&lt;/span&gt;.Init
            ClientAPI.RegisterControlMethods(&lt;span class="kwrd"&gt;Me&lt;/span&gt;, &lt;span class="kwrd"&gt;Me&lt;/span&gt;.ClientID)
        &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;Sub&lt;/span&gt;

        &lt;span class="kwrd"&gt;Private&lt;/span&gt; &lt;span class="kwrd"&gt;Sub&lt;/span&gt; Page_PreRender(&lt;span class="kwrd"&gt;ByVal&lt;/span&gt; sender &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Object&lt;/span&gt;, &lt;span class="kwrd"&gt;ByVal&lt;/span&gt; e &lt;span class="kwrd"&gt;As&lt;/span&gt; System.EventArgs) &lt;span class="kwrd"&gt;Handles&lt;/span&gt; &lt;span class="kwrd"&gt;Me&lt;/span&gt;.PreRender
            &lt;span class="rem"&gt;'Tell DotNetNuke we need to use the ScriptManager&lt;/span&gt;
            DotNetNuke.Framework.AJAX.RegisterScriptManager()

            &lt;span class="rem"&gt;'Register our client-side Script Control&lt;/span&gt;
            ScriptManager.GetCurrent(&lt;span class="kwrd"&gt;Me&lt;/span&gt;.Page).RegisterScriptControl(&lt;span class="kwrd"&gt;Me&lt;/span&gt;)
            ScriptManager.GetCurrent(&lt;span class="kwrd"&gt;Me&lt;/span&gt;.Page).RegisterScriptDescriptors(&lt;span class="kwrd"&gt;Me&lt;/span&gt;)
        &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;Sub&lt;/span&gt;

&lt;span class="preproc"&gt;#End Region&lt;/span&gt;&lt;/font&gt;&lt;/pre&gt;
&lt;style type="text/css"&gt;
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;

&lt;p&gt;As you can see we have a class that inherits from PortalModuleBase and implements the IScriptControl interface.  We also are defining some important events that our usercontrols will trap and provide the necessary information (more on this in a bit).  In &lt;a href="http://www.dotnetnuke.com/Community/Blogs/tabid/825/EntryId/2066/Utilizing-the-Microsoft-AJAX-Framework-and-ClientAPI-to-Develop-Rich-Modules-Part-I.aspx"&gt;Part I&lt;/a&gt; we looked at how the client-side can invoke a server-side method using the ClientAPI's Control Methods.  Here we are getting our first look at how the methods are hooked up.  The earliest possible event needs to register that the module supports Control Methods.  Just prior to rendering we need to inform the DotNetNuke Framework that we will require the ScriptManager to be present.  This code is really not necessary anymore as DNN5 now requires MSAJAX to be present and thus the ScriptManager.   Finally, we need to tell the script manager that our control will supply ScriptControl goodness.&lt;/p&gt;

&lt;p&gt;It is not time to review our base class's implementation of the IScriptControl interface.&lt;/p&gt;

&lt;pre class="csharpcode"&gt;&lt;font size="1"&gt;&lt;span class="preproc"&gt;#Region&lt;/span&gt; &lt;span class="str"&gt;"IScriptControl"&lt;/span&gt;
        &lt;span class="kwrd"&gt;Private&lt;/span&gt; &lt;span class="kwrd"&gt;Function&lt;/span&gt; GetScriptReferences() &lt;span class="kwrd"&gt;As&lt;/span&gt; IEnumerable(Of ScriptReference) &lt;span class="kwrd"&gt;Implements&lt;/span&gt; IScriptControl.GetScriptReferences
            &lt;span class="kwrd"&gt;Dim&lt;/span&gt; refs &lt;span class="kwrd"&gt;As&lt;/span&gt; List(Of ScriptReference) = &lt;span class="kwrd"&gt;New&lt;/span&gt; List(Of ScriptReference)
            &lt;span class="kwrd"&gt;RaiseEvent&lt;/span&gt; AddScriptReferences(refs)
            &lt;span class="kwrd"&gt;Return&lt;/span&gt; refs
        &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;Function&lt;/span&gt;

        &lt;span class="kwrd"&gt;Private&lt;/span&gt; &lt;span class="kwrd"&gt;Function&lt;/span&gt; GetScriptDescriptors() &lt;span class="kwrd"&gt;As&lt;/span&gt; IEnumerable(Of ScriptDescriptor) &lt;span class="kwrd"&gt;Implements&lt;/span&gt; IScriptControl.GetScriptDescriptors
            &lt;span class="kwrd"&gt;Dim&lt;/span&gt; descs &lt;span class="kwrd"&gt;As&lt;/span&gt; List(Of ScriptDescriptor) = &lt;span class="kwrd"&gt;New&lt;/span&gt; List(Of ScriptDescriptor)
            &lt;span class="kwrd"&gt;Dim&lt;/span&gt; desc &lt;span class="kwrd"&gt;As&lt;/span&gt; ScriptComponentDescriptor = &lt;span class="kwrd"&gt;New&lt;/span&gt; ScriptComponentDescriptor(&lt;span class="str"&gt;"ClientNamespaceHere"&lt;/span&gt;)
            &lt;span class="kwrd"&gt;Dim&lt;/span&gt; jss &lt;span class="kwrd"&gt;As&lt;/span&gt; JavaScriptSerializer = &lt;span class="kwrd"&gt;New&lt;/span&gt; JavaScriptSerializer()
            &lt;span class="kwrd"&gt;Dim&lt;/span&gt; msgs &lt;span class="kwrd"&gt;As&lt;/span&gt; Dictionary(Of &lt;span class="kwrd"&gt;String&lt;/span&gt;, &lt;span class="kwrd"&gt;String&lt;/span&gt;) = &lt;span class="kwrd"&gt;New&lt;/span&gt; Dictionary(Of &lt;span class="kwrd"&gt;String&lt;/span&gt;, &lt;span class="kwrd"&gt;String&lt;/span&gt;)

            desc.AddScriptProperty(&lt;span class="str"&gt;"id"&lt;/span&gt;, &lt;span class="kwrd"&gt;String&lt;/span&gt;.Format(&lt;span class="str"&gt;"'{0}'"&lt;/span&gt;, &lt;span class="kwrd"&gt;Me&lt;/span&gt;.ClientID))

            &lt;span class="kwrd"&gt;RaiseEvent&lt;/span&gt; AddLocalizedMessages(msgs)
            desc.AddScriptProperty(&lt;span class="str"&gt;"msgs"&lt;/span&gt;, &lt;span class="kwrd"&gt;String&lt;/span&gt;.Format(&lt;span class="str"&gt;"'{0}'"&lt;/span&gt;, jss.Serialize(msgs))) 

            &lt;span class="kwrd"&gt;RaiseEvent&lt;/span&gt; AddScriptComponentDescriptors(desc)

            descs.Add(desc)
            &lt;span class="kwrd"&gt;Return&lt;/span&gt; descs
        &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;Function&lt;/span&gt;

&lt;span class="preproc"&gt;#End Region&lt;/span&gt;&lt;/font&gt;&lt;/pre&gt;
&lt;style type="text/css"&gt;
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;style type="text/css"&gt;
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;

&lt;p&gt;The GetScriptReferences method simply creates a generic list of ScriptReferences and delegates the responsibility of filling the list to the control that inherits from it by passing it as an argument for the AddScriptReferences event.  This is how our module's external javascript references will get added to our rendered page.  We will cover the consumption of this event when we review the module's code.&lt;/p&gt;

&lt;p&gt;The GetScriptDescriptors method has a bit more meat to it.  The purpose of this method is twofold:  to provide the MSAJAX Framework the information necessary to create our client-side object and to initialize its properties with values on the server.  The only piece of information the framework needs to create our object is the client-side object name, which gets assigned by our control inheriting from our base class via the Descriptor's Type property.   Properties are initialized by calling the AddScriptProperty method passing in the non-prefixed property names.  If you refer back to Part I you will remember that we prefixed our properties with get_ and set_.  If you have reviewed the code you may be asking why the javascript did not have a set_id method.  This method is unnecessary since the Sys.Component method already defines it, and in fact the component requires it.  Since it needs to be unique we will use an ID that is guaranteed by the ASP.NET runtime to be unique the ClientID.  &lt;/p&gt;

&lt;p&gt;There are two events left to discuss in our base class.  The AddLocalizedMessages simply passes a Dictionary of string/string to our module for additional messages to be sent down.  It then uses the JSON serializer included in the MSAJAX Framework to serialize the dictionary into a single property called msgs.  The AddScriptComponentDescriptors event allows for custom properties to be added.&lt;/p&gt;

&lt;p&gt;With the common base class defined, lets now turn our attention to the DotNetNuke module inheriting from it.  &lt;/p&gt;

&lt;pre class="csharpcode"&gt;&lt;font size="1"&gt;    &lt;span class="rem"&gt;'-------------------------------------------------------------------------------------------------------------&lt;/span&gt;
    &lt;span class="rem"&gt;'- The ControlMethodClass attribute identifies the class as supporting Control Methods&lt;/span&gt;
    &lt;span class="rem"&gt;'- The Friendly name parameter is usually named after server-side class namespace, but could be shortened if you like&lt;/span&gt;
    &lt;span class="rem"&gt;'- If you change this make sure you also change its client calling code found in EditDNNAjaxModule1.ascx.js&lt;/span&gt;
    &lt;span class="rem"&gt;'-   dnn.xmlhttp.callControlMethod('YourCompanyHere.Modules.DNNAjaxModule1.EditDNNAjaxModule1.' + this._ns, &lt;/span&gt;
    &lt;span class="rem"&gt;'-------------------------------------------------------------------------------------------------------------&lt;/span&gt;
    &lt;ControlMethodClass(&lt;span class="str"&gt;"YourCompanyHere.Modules.DNNAjaxModule1.EditDNNAjaxModule1"&lt;/span&gt;)&gt; _
    Partial &lt;span class="kwrd"&gt;Class&lt;/span&gt; EditDNNAjaxModule1
        &lt;span class="kwrd"&gt;Inherits&lt;/span&gt; AjaxPortalModuleBase&lt;/font&gt;&lt;/pre&gt;
&lt;style type="text/css"&gt;
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;

&lt;p&gt;The first thing that should stick out is we are decorating our class with the ControlMethodClass attribute which as the comment states identifies the class as supporting control methods.  Obviously we are inheriting from the base class we just covered.&lt;/p&gt;

&lt;pre class="csharpcode"&gt;&lt;font size="1"&gt;&lt;span class="preproc"&gt;#Region&lt;/span&gt; &lt;span class="str"&gt;"AjaxPortalModuleBase Events"&lt;/span&gt;
        &lt;span class="rem"&gt;'-------------------------------------------------------------------------------------------------------------&lt;/span&gt;
        &lt;span class="rem"&gt;'- This is where your client-side javascript that uses the MS AJAX framework needs to be registered&lt;/span&gt;
        &lt;span class="rem"&gt;'- Adding the reference here ensures that the MS AJAX script is run before our script which uses things like Type.registerNamespace run&lt;/span&gt;
        &lt;span class="rem"&gt;'-------------------------------------------------------------------------------------------------------------&lt;/span&gt;
        &lt;span class="kwrd"&gt;Protected&lt;/span&gt; &lt;span class="kwrd"&gt;Sub&lt;/span&gt; AjaxPortalModuleBase_AddScriptReferences(&lt;span class="kwrd"&gt;ByVal&lt;/span&gt; References &lt;span class="kwrd"&gt;As&lt;/span&gt; List(Of ScriptReference)) &lt;span class="kwrd"&gt;Handles&lt;/span&gt; &lt;span class="kwrd"&gt;MyBase&lt;/span&gt;.AddScriptReferences
            References.Add(&lt;span class="kwrd"&gt;New&lt;/span&gt; System.Web.UI.ScriptReference(&lt;span class="kwrd"&gt;Me&lt;/span&gt;.ModulePath &amp; &lt;span class="str"&gt;"EditDNNAjaxModule1.ascx.js"&lt;/span&gt;))
        &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;Sub&lt;/span&gt;

        &lt;span class="rem"&gt;'-------------------------------------------------------------------------------------------------------------&lt;/span&gt;
        &lt;span class="rem"&gt;'- Add any localized text needed on the client&lt;/span&gt;
        &lt;span class="rem"&gt;'-------------------------------------------------------------------------------------------------------------&lt;/span&gt;
        &lt;span class="kwrd"&gt;Protected&lt;/span&gt; &lt;span class="kwrd"&gt;Sub&lt;/span&gt; AjaxPortalModuleBase_AddLocalizedMessages(&lt;span class="kwrd"&gt;ByVal&lt;/span&gt; Messages &lt;span class="kwrd"&gt;As&lt;/span&gt; Dictionary(Of &lt;span class="kwrd"&gt;String&lt;/span&gt;, &lt;span class="kwrd"&gt;String&lt;/span&gt;)) &lt;span class="kwrd"&gt;Handles&lt;/span&gt; &lt;span class="kwrd"&gt;MyBase&lt;/span&gt;.AddLocalizedMessages
            Messages(&lt;span class="str"&gt;"SettingsSaved"&lt;/span&gt;) = Localization.GetString(&lt;span class="str"&gt;"SettingsSaved.Client"&lt;/span&gt;, LocalResourceFile)
        &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;Sub&lt;/span&gt;

        &lt;span class="rem"&gt;'-------------------------------------------------------------------------------------------------------------&lt;/span&gt;
        &lt;span class="rem"&gt;'- This is where you add your custom properties that are to be sent down to the client-side object&lt;/span&gt;
        &lt;span class="rem"&gt;'- By default we are passing the naming container ID (ns) and localized messages (msgs) &lt;/span&gt;
        &lt;span class="rem"&gt;'- If you add your own properties make sure you update your client code with those properties found in EditDNNAjaxModule1.ascx.js&lt;/span&gt;
        &lt;span class="rem"&gt;'-      get_ImagePath: function() {return this._imagePath;},&lt;/span&gt;
        &lt;span class="rem"&gt;'-      set_ImagePath: function(value) {this._imagePath = value;},&lt;/span&gt;
        &lt;span class="rem"&gt;'-------------------------------------------------------------------------------------------------------------&lt;/span&gt;
        &lt;span class="kwrd"&gt;Protected&lt;/span&gt; &lt;span class="kwrd"&gt;Sub&lt;/span&gt; AjaxPortalModuleBase_AddScriptComponentDescriptors(&lt;span class="kwrd"&gt;ByVal&lt;/span&gt; Descriptor &lt;span class="kwrd"&gt;As&lt;/span&gt; ScriptComponentDescriptor) &lt;span class="kwrd"&gt;Handles&lt;/span&gt; &lt;span class="kwrd"&gt;MyBase&lt;/span&gt;.AddScriptComponentDescriptors
            &lt;span class="rem"&gt;'IMPORTANT!  Enter Client Namespace + ObjectName as Type&lt;/span&gt;
            Descriptor.Type = &lt;span class="str"&gt;"YourCompanyHere.EditDNNAjaxModule1"&lt;/span&gt;

            &lt;span class="rem"&gt;'---------------------------------------------------------------------------------------------------------&lt;/span&gt;
            &lt;span class="rem"&gt;'Add custom properties here&lt;/span&gt;
            &lt;span class="rem"&gt;'   Descriptor.AddScriptProperty("ImagePath", String.Format("'{0}'", Me.ModulePath &amp; "images/"))&lt;/span&gt;

            &lt;span class="kwrd"&gt;If&lt;/span&gt; &lt;span class="kwrd"&gt;Not&lt;/span&gt; Settings &lt;span class="kwrd"&gt;Is&lt;/span&gt; &lt;span class="kwrd"&gt;Nothing&lt;/span&gt; &lt;span class="kwrd"&gt;Then&lt;/span&gt;
                &lt;span class="rem"&gt;'This sample uses the Module Settings collection as a custom property serialized to JSON&lt;/span&gt;
                &lt;span class="kwrd"&gt;Dim&lt;/span&gt; jss &lt;span class="kwrd"&gt;As&lt;/span&gt; JavaScriptSerializer = &lt;span class="kwrd"&gt;New&lt;/span&gt; JavaScriptSerializer()
                Descriptor.AddScriptProperty(&lt;span class="str"&gt;"settings"&lt;/span&gt;, &lt;span class="kwrd"&gt;String&lt;/span&gt;.Format(&lt;span class="str"&gt;"'{0}'"&lt;/span&gt;, jss.Serialize(Settings)))
            &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;If&lt;/span&gt;
            &lt;span class="rem"&gt;'---------------------------------------------------------------------------------------------------------&lt;/span&gt;
        &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;Sub&lt;/span&gt;
&lt;span class="preproc"&gt;#End Region&lt;/span&gt;&lt;/font&gt;&lt;/pre&gt;
&lt;style type="text/css"&gt;
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;style type="text/css"&gt;
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;

&lt;p&gt;The first event, AddScriptReferences, is rather straight forward.  We simply create a new ScriptReference passing in the javascript file location.  The AddLocalizedMessages event handler simply adds our localized message to the dictionary.  However, I do believe it worth spending a little time discussing this approach.  The Microsoft AJAX Framework &lt;a href="http://www.asp.net/AJAX/Documentation/Live/tutorials/LocalizeResourcesInScript.aspx"&gt;defines one method&lt;/a&gt; for localization of messages in javascript by creating multiple scripts, one for each locale.  I find this method a bit of a nuisance.  The method I am suggesting is to simply have a property called msgs on the client that gets a serialized dictionary of name value pairs.  Then in script use the dictionary to obtain each message.&lt;/p&gt;

&lt;pre class="csharpcode"&gt;&lt;font size="1"&gt;getMessage: &lt;span class="kwrd"&gt;function&lt;/span&gt;(key)
{
    &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;this&lt;/span&gt;._msgs[key];
},&lt;/font&gt;&lt;/pre&gt;
&lt;style type="text/css"&gt;
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;

&lt;p&gt;The final event is the AddScriptComponentDescriptors.  As mentioned earlier, we need to set the Type to the exact object defined in our javascript.  The next portion of code is where we can add any custom properties that we need on the client.  In this case we are serializing the entire Settings hashtable to json to read on the client.  If you remember we had client-side code in the setter that deserialized this value.&lt;/p&gt;

&lt;pre class="csharpcode"&gt;&lt;font size="1"&gt;set_settings: &lt;span class="kwrd"&gt;function&lt;/span&gt;(value) {&lt;span class="kwrd"&gt;this&lt;/span&gt;._settings = Sys.Serialization.JavaScriptSerializer.deserialize(value);},&lt;/font&gt;&lt;/pre&gt;
&lt;style type="text/css"&gt;
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;

&lt;p&gt;The final portion of code for our EditModule is to write our ControlMethod that is exposed to the client.&lt;/p&gt;

&lt;pre class="csharpcode"&gt;&lt;font size="1"&gt;&lt;span class="preproc"&gt;#Region&lt;/span&gt; &lt;span class="str"&gt;"Control Methods"&lt;/span&gt;
        &lt;span class="rem"&gt;'-------------------------------------------------------------------------------------------------------------&lt;/span&gt;
        &lt;span class="rem"&gt;'- Exposing methods to the client code is as simple as adding the ControlMethod attribute&lt;/span&gt;
        &lt;span class="rem"&gt;'- IMPORTANT!   ALWAYS SECURE YOUR CONTROL METHODS IF INTERACTING WITH SENSITIVE DATA&lt;/span&gt;
        &lt;span class="rem"&gt;'-------------------------------------------------------------------------------------------------------------&lt;/span&gt;
        &lt;ControlMethod()&gt; _
        &lt;span class="kwrd"&gt;Public&lt;/span&gt; &lt;span class="kwrd"&gt;Function&lt;/span&gt; UpdateSettings(&lt;span class="kwrd"&gt;ByVal&lt;/span&gt; Settings &lt;span class="kwrd"&gt;As&lt;/span&gt; Dictionary(Of &lt;span class="kwrd"&gt;String&lt;/span&gt;, &lt;span class="kwrd"&gt;Object&lt;/span&gt;)) &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Boolean&lt;/span&gt;
            &lt;span class="kwrd"&gt;If&lt;/span&gt; &lt;span class="kwrd"&gt;Me&lt;/span&gt;.EditMode &lt;span class="kwrd"&gt;Then&lt;/span&gt; &lt;span class="rem"&gt;'Making sure only those users with Edit Mode rights can call this method&lt;/span&gt;
                &lt;span class="kwrd"&gt;Dim&lt;/span&gt; modController &lt;span class="kwrd"&gt;As&lt;/span&gt; DotNetNuke.Entities.Modules.ModuleController = &lt;span class="kwrd"&gt;New&lt;/span&gt; DotNetNuke.Entities.Modules.ModuleController()
                &lt;span class="kwrd"&gt;For&lt;/span&gt; &lt;span class="kwrd"&gt;Each&lt;/span&gt; key &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;String&lt;/span&gt; &lt;span class="kwrd"&gt;In&lt;/span&gt; Settings.Keys
                    modController.UpdateModuleSetting(&lt;span class="kwrd"&gt;Me&lt;/span&gt;.ModuleId, key, Settings(key))
                &lt;span class="kwrd"&gt;Next&lt;/span&gt;
            &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;If&lt;/span&gt;
            &lt;span class="kwrd"&gt;Return&lt;/span&gt; &lt;span class="kwrd"&gt;True&lt;/span&gt;
        &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;Function&lt;/span&gt;
&lt;span class="preproc"&gt;#End Region&lt;/span&gt;&lt;/font&gt;&lt;/pre&gt;

&lt;p&gt;Unlike earlier versions of client-callbacks exposed in the ClientAPI, this one can accept any number of parameters and a variety of argument types. In this case we will accept the updated settings object we sent down during the initial rendering of the page.  The method needs to be decorated with the ControlMethod attribute and if it exposes or updates sensitive information it needs to be secured.  You may be wondering why did the ClientAPI invent such a thing as ControlMethods when the Microsoft AJAX Framework already has the ability to make AJAX calls into either a webservice or a PageMethod.  The answer is simple.  Neither WebServices nor PageMethods allow you to call into a specific instance of a module since a PageMethod must be defined as static/Shared and a webservice obviously has no context of a module as it is a different class entirely.&lt;/p&gt;

&lt;p&gt;That covers the basics of writing our server-side module that supports the creation of a client-side object.  Before I sign off I feel it necessary to contrast this form of AJAX development with the kind that the UpdatePanel offers.  The major difference is in what is sent between the client / server exchange.  For ControlMethods only the serialized settings object plus minimal identifiers (ClientID) is posted.  For UpdatePanel the entire form is posted.  On the server side, only the first few events in the ASP.NET event lifecycle are fired whereas the UpdatePanel needs nearly all events to fire.  Finally the response text of the ControlMethod contains a simple boolean, whereas the UpdatePanel contains a large portion of HTML including ViewState.  This is not to say that I do not think that the UpdatePanel has its place in the AJAX space.  I am only saying that its place should be used more with retro-fitting existing applications to AJAX, not new modules being developed from scratch.  The next entry in this series will showcase yet another advantage this approach has over the UpdatePanel:  Client-side Inter-Module Communication.&lt;/p&gt;

&lt;p&gt;Hopefully, this entry sheds some light on why the Microsoft AJAX Framework has some additional features than other client-side only frameworks.  If you still wish to learn more of the differences, especially relating to the client-side features compared to JQuery, which recently got integrated into DNN5, I suggest listening to &lt;a href="http://www.hanselminutes.com/default.aspx?showID=146"&gt;this podcast by Scott Hanselman&lt;/a&gt;.&lt;/p&gt;</description>
      <link>http://www.dotnetnuke.com/Community/Blogs/tabid/825/EntryId/2067/Utilizing-the-Microsoft-AJAX-Framework-and-ClientAPI-to-Develop-Rich-Modules-Part-II.aspx</link>
      <category domain="http://www.dotnetnuke.com/products/development/forge/componentwebcontrols/tabid/873/blogid/31/default.aspx">Core :: ClientAPI</category>
      <author>jon.henning@dotnetnuke.com</author>
      <comments>http://www.dotnetnuke.com/Community/Blogs/tabid/825/EntryId/2067/Utilizing-the-Microsoft-AJAX-Framework-and-ClientAPI-to-Develop-Rich-Modules-Part-II.aspx#Comments</comments>
      <guid isPermaLink="true">http://www.dotnetnuke.com/Community/Blogs/tabid/825/EntryId/2067/Utilizing-the-Microsoft-AJAX-Framework-and-ClientAPI-to-Develop-Rich-Modules-Part-II.aspx</guid>
      <pubDate>Tue, 11 Nov 2008 12:01:16 GMT</pubDate>
      <slash:comments>1</slash:comments>
      <trackback:ping>http://www.dotnetnuke.com/DesktopModules/Blog/Trackback.aspx?id=2067</trackback:ping>
    </item>
    <item>
      <title>Utilizing the Microsoft AJAX Framework and ClientAPI to Develop Rich Modules: Part I</title>
      <description>&lt;p&gt;With the release of DotNetNuke 5.0 drawing near, I figured it would be good to provide an introduction as to how nice client-side module development can be with the integration of the Microsoft AJAX Framework and the ClientAPI 4.0. This mini-series of blog entries will cover the basics of how to get started by creating a sample module that&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Utilizes client-side javascript objects to encapsulate our logic, easily allowing multiple instances of a module on a page without having our variables clash &lt;/li&gt;    &lt;li&gt;Utilizes the Microsoft AJAX Framework to allow for variables to be initialized in our client-side objects &lt;/li&gt;    &lt;li&gt;Utilizes the new ClientAPI ControlMethods to allow for communication of complex objects both to and from the server &lt;/li&gt;    &lt;li&gt;Enables localized messages to be sent down to the client-side javascript &lt;/li&gt;    &lt;li&gt;Enables client-side Inter-Module Communication (IMC) &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;If your new to javascript, you may be confused as to where to get started. As there are many frameworks out there, it can be overwhelming as to which one to choose. One of the advantages of using both the Microsoft AJAX Framework and the ClientAPI is they both have been written to allow for easy integration with the server-side logic, whereas other frameworks may have the ability to make AJAX calls, they do not have included ASP.NET server-side code to handle easy integration with your VB/C# code.&lt;/p&gt;  &lt;p&gt;Another vital piece of information that you should understand is that javascript is more of an emulation (prototype) language than a real language. It has the ability to morph itself to do common programming constructs like objects, events, inheritance, enumerators, etc. However, it does not have these things out of the box. Thus, a framework like Microsoft’s, is nice since it will provide a formalized way in which objects get defined and inheritance happens. For more information how this has been formalized see &lt;a href="http://www.asp.net/AJAX/Documentation/Live/tutorials/EnhancingJavaScriptTutorial.aspx"&gt;this document&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;Let’s assume you already have a sample module you are working on and it has a typical Edit Usercontrol associated called EditDNNAjaxModule1.ascx. A convention that I like to follow is to create my javascript file with the same name plus a .js extension (EditDNNAjaxModule1.ascx.js). This keeps the files near each other in the Solution Explorer.  Another assumption we will make is that we plan on creating a namespace for our controls using a company name which is a common practice in writing server-side modules that we will apply to the client. To do this, we simply declare our namespace at the top of the js file.&lt;/p&gt;  &lt;pre class="csharpcode"&gt;&lt;font size="1"&gt;Type.registerNamespace(&lt;span class="str"&gt;'YourCompanyHere'&lt;/span&gt;);&lt;/font&gt;&lt;/pre&gt;
&lt;style type="text/css"&gt;



.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;

&lt;p&gt;The next step is to define our class’s constructor. In javascript this is done by defining a function.&lt;/p&gt;

&lt;pre class="csharpcode"&gt;&lt;font size="1"&gt;YourCompanyHere.EditDNNAjaxModule1 = &lt;span class="kwrd"&gt;function&lt;/span&gt;()
{
    &lt;span class="rem"&gt;//Call Base Method&lt;/span&gt;
    YourCompanyHere.EditDNNAjaxModule1.initializeBase(&lt;span class="kwrd"&gt;this&lt;/span&gt;);
    &lt;span class="rem"&gt;//Member Variables&lt;/span&gt;
    &lt;span class="kwrd"&gt;this&lt;/span&gt;._myprop1 = &lt;span class="kwrd"&gt;null&lt;/span&gt;;
    &lt;span class="kwrd"&gt;this&lt;/span&gt;._msgs = {};
    &lt;span class="kwrd"&gt;this&lt;/span&gt;._settings = {};
    &lt;span class="kwrd"&gt;this&lt;/span&gt;._updateButton = &lt;span class="kwrd"&gt;null&lt;/span&gt;;

    &lt;span class="rem"&gt;//create delegates (MAKE SURE YOU CLEAN UP IN dispose!)&lt;/span&gt;
    &lt;span class="kwrd"&gt;this&lt;/span&gt;._delegates = {
        _updateSuccessDelegate: Function.createDelegate(&lt;span class="kwrd"&gt;this&lt;/span&gt;, &lt;span class="kwrd"&gt;this&lt;/span&gt;._updateSuccess),
        _updateFailDelegate: Function.createDelegate(&lt;span class="kwrd"&gt;this&lt;/span&gt;, &lt;span class="kwrd"&gt;this&lt;/span&gt;._updateFail),
        _onLoadDelegate: Function.createDelegate(&lt;span class="kwrd"&gt;this&lt;/span&gt;, &lt;span class="kwrd"&gt;this&lt;/span&gt;._onLoad)
        };

    &lt;span class="rem"&gt;//Event Hookup&lt;/span&gt;
    Sys.Application.add_load(&lt;span class="kwrd"&gt;this&lt;/span&gt;._delegates._onLoadDelegate);
}&lt;/font&gt;&lt;/pre&gt;
&lt;style type="text/css"&gt;
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;style type="text/css"&gt;



.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;style type="text/css"&gt;



.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;

&lt;p&gt;There are a couple things to note here. First, we are using a keyword this. If you are a C# developer this should be somewhat familiar, if your first language is VB then think of it as the same thing as Me. The first line makes a call to the constructor’s base class, ensuring its constructor gets initialized. This is similar to the keyword base for C# and MyBase in VB. Obviously, if we are calling a base class we must be inheriting from some class. One would expect to see which class we inherit from already, but, that is not possible in javascript for how it emulates inheritance. Our entire class must be processed before it gets defined, which is covered at the end of this entry.&lt;/p&gt;

&lt;p&gt;In the constructor we define and initialize our class’s member variables (_settings and _myprop1). These variables’ scope is limited to each EditDNNAjaxModule1 instance that is created. A common convention that Microsoft uses is to prefix all variables and methods that should be private with an underscore. While this does not stop developers from accessing them from the outside, it does help with clarifying intent, not to mention Visual Studio Intellisense.&lt;/p&gt;

&lt;p&gt;The next thing to note is that we are creating delegates and assigning it to an member variable. The _delegates variable is actually serving as a dictionary object.  Its syntax for initializing it is &lt;a href="http://www.json.org/"&gt;json&lt;/a&gt; which bears much similarity to .NET &lt;a href="http://msdn.microsoft.com/en-us/library/bb384062.aspx"&gt;object initializers&lt;/a&gt;. A delegate here, can be thought of in much the same way as &lt;a href="http://msdn.microsoft.com/en-us/library/system.delegate.aspx"&gt;delegates in .NET&lt;/a&gt;. The one difference however, is the need to assign it to a member variable. It is necessary to hold this so we can set it to null prior to the page unloading which will stop memory leaking from occurring in Internet Explorer. I will cover how this happens in a bit.&lt;/p&gt;

&lt;p&gt;Finally, we are adding our delegate (event handler) to the Framework’s load event. While this code may not seem like much, it is important to understand that this event will fire once all components on the page have been initialized.&lt;/p&gt;

&lt;p&gt;With our constructor done, it is not time to define the class’s methods. Javascript uses what it calls prototypes to extend objects. Those familiar with .NET’s &lt;a href="http://msdn.microsoft.com/en-us/library/bb383977.aspx"&gt;extension methods&lt;/a&gt; will find some similarities here. The prototype syntax is as follows&lt;/p&gt;

&lt;pre class="csharpcode"&gt;&lt;font size="1"&gt;YourCompanyHere.EditDNNAjaxModule1.prototype =
{
  &lt;span class="rem"&gt;//methods to extend our EditModule1 class&lt;/span&gt;
}&lt;/font&gt;&lt;/pre&gt;
&lt;style type="text/css"&gt;



.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;

&lt;p&gt;One unfortunate part of writing code to work with all browsers is that we have to code to the least common denominator. This is true when trying to associate code with our class’s properties. Ideally if our class had a property called selectedIndex we could set it like this&lt;/p&gt;

&lt;pre class="csharpcode"&gt;&lt;font size="1"&gt;control.selectedIndex = 1;&lt;/font&gt;&lt;/pre&gt;
&lt;style type="text/css"&gt;



.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;

&lt;p&gt;However, if we needed to associate code whenever this property was set or read, there is no way to do it, so we need another convention for accessing properties. The Microsoft Framework does this by defining methods prefixed with get_ or set_.&lt;/p&gt;

&lt;pre class="csharpcode"&gt;&lt;font size="1"&gt;get_myProp1: &lt;span class="kwrd"&gt;function&lt;/span&gt;() {&lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;this&lt;/span&gt;._myprop1;},
set_myProp1: &lt;span class="kwrd"&gt;function&lt;/span&gt;(value) {&lt;span class="kwrd"&gt;this&lt;/span&gt;._myprop1 = value;},
get_settings: &lt;span class="kwrd"&gt;function&lt;/span&gt;() {&lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;this&lt;/span&gt;._settings;},
set_settings: &lt;span class="kwrd"&gt;function&lt;/span&gt;(value) {&lt;span class="kwrd"&gt;this&lt;/span&gt;._settings = Sys.Serialization.JavaScriptSerializer.deserialize(value);},&lt;/font&gt;&lt;/pre&gt;
&lt;style type="text/css"&gt;



.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;

&lt;p&gt;This actually serves two purposes. First it helps to establish a common convention to make code look uniform. But the second is something we will cover in another entry in this blog series. It has to do with how we can initialize our properties from our server side ASP.NET code.&lt;/p&gt;

&lt;p&gt;With our properties covered it’s not time to write our event handlers.&lt;/p&gt;

&lt;pre class="csharpcode"&gt;&lt;font size="1"&gt;initialize: &lt;span class="kwrd"&gt;function&lt;/span&gt;() 
{
  &lt;span class="rem"&gt;//Call Base Method&lt;/span&gt;
  YourCompanyHere.EditDNNAjaxModule1.callBaseMethod(&lt;span class="kwrd"&gt;this&lt;/span&gt;, &lt;span class="str"&gt;'initialize'&lt;/span&gt;);
  
  &lt;span class="rem"&gt;//hookup event handlers&lt;/span&gt;
  &lt;span class="kwrd"&gt;this&lt;/span&gt;._updateButton = $get(&lt;span class="kwrd"&gt;this&lt;/span&gt;.get_ns() + &lt;span class="str"&gt;'cmdUpdate'&lt;/span&gt;);
  $addHandlers(&lt;span class="kwrd"&gt;this&lt;/span&gt;._updateButton, {&lt;span class="str"&gt;"click"&lt;/span&gt;: &lt;span class="kwrd"&gt;this&lt;/span&gt;._onUpdate}, &lt;span class="kwrd"&gt;this&lt;/span&gt;);
},

_onLoad: &lt;span class="kwrd"&gt;function&lt;/span&gt;(src, args)
{
  &lt;span class="kwrd"&gt;this&lt;/span&gt;._updateControls();
},

_onUpdate: &lt;span class="kwrd"&gt;function&lt;/span&gt;(src, arg)
{
  &lt;span class="kwrd"&gt;this&lt;/span&gt;._displayWait(&lt;span class="kwrd"&gt;true&lt;/span&gt;); 
  &lt;span class="kwrd"&gt;this&lt;/span&gt;._updateSettings();
  dnn.xmlhttp.callControlMethod(&lt;span class="str"&gt;'YourCompanyHere.Modules.DNNAjaxModule1.EditDNNAjaxModule1.'&lt;/span&gt; + &lt;span class="kwrd"&gt;this&lt;/span&gt;.get_id(), 
      &lt;span class="str"&gt;'UpdateSettings'&lt;/span&gt;, {Settings:&lt;span class="kwrd"&gt;this&lt;/span&gt;._settings}, &lt;span class="kwrd"&gt;this&lt;/span&gt;._delegates._updateSuccessDelegate, &lt;span class="kwrd"&gt;this&lt;/span&gt;._delegates._updateFailDelegate);
},&lt;/font&gt;&lt;/pre&gt;
&lt;style type="text/css"&gt;



.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;style type="text/css"&gt;



.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;

&lt;p&gt;The first event we have is an override on our base class’s initialize event. This event is fired the instant our object is initialized. It is common practice to hook up your object’s event handlers with any DOM elements.  The next event is the _onload we talked about earlier. At first glance you may wonder what the difference is between onload and initialize. Onload fires only after all objects on the page have been initialized. This is useful if we ever need to reference other objects on the page which we will cover in a later blog entry when we tackle client-side IMC. More information on the event lifecycle can be found &lt;a href="http://www.asp.net/Ajax/Documentation/Live/overview/AJAXClientEvents.aspx"&gt;here&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;The final method we have is the event handler that gets triggered when the update link is pressed. As you may be able to surmise, the code will show a wait graphic, call an update to our settings object and invoke a callback to the server, using the new ClientAPI ControlMethod. Further detail into how this will hook into the server-side will be covered later in this blog series.&lt;/p&gt;

&lt;p&gt;So far all our methods were internal event handlers. Here is an example of a normal method&lt;/p&gt;

&lt;pre class="csharpcode"&gt;&lt;font size="1"&gt;getSetting: &lt;span class="kwrd"&gt;function&lt;/span&gt;(key, def)
{
  &lt;span class="kwrd"&gt;if&lt;/span&gt; (&lt;span class="kwrd"&gt;this&lt;/span&gt;._settings[key])
    &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;this&lt;/span&gt;._settings[key];
  &lt;span class="kwrd"&gt;return&lt;/span&gt; def;
},&lt;/font&gt;&lt;/pre&gt;
&lt;style type="text/css"&gt;



.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;

&lt;p&gt;This method allows the caller to retrieve the settings Dictionary’s value, or if not present a default passed in value.&lt;/p&gt;

&lt;p&gt;The final method we wish to cover is the dispose method. Those familiar with the .NET &lt;a href="http://msdn.microsoft.com/en-us/library/system.idisposable.aspx"&gt;IDisposable interface&lt;/a&gt; will be right at home here. Though one may be confused as to why we need this in a language such as javascript. It has to do with the dangers of memory leaks and delegates. We need to clean up all delegates attached to DOM elements. Typical code for this my look like this&lt;/p&gt;

&lt;pre class="csharpcode"&gt;&lt;font size="1"&gt;dispose: &lt;span class="kwrd"&gt;function&lt;/span&gt;()
{
  $clearHandlers(&lt;span class="kwrd"&gt;this&lt;/span&gt;._updateButton);    
  &lt;span class="kwrd"&gt;this&lt;/span&gt;._updateButton = &lt;span class="kwrd"&gt;null&lt;/span&gt;;
  &lt;span class="kwrd"&gt;this&lt;/span&gt;._delegates = &lt;span class="kwrd"&gt;null&lt;/span&gt;;
  YourCompanyHere.EditDNNAjaxModule1.callBaseMethod(&lt;span class="kwrd"&gt;this&lt;/span&gt;, &lt;span class="str"&gt;'dispose'&lt;/span&gt;);
}&lt;/font&gt;&lt;/pre&gt;
&lt;style type="text/css"&gt;



.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;

&lt;p&gt;Notice that we are using a $clearHandlers on the same object we did the $addHandlers. These methods exposed by the Microsoft Framework are covered in &lt;a href="http://www.asp.net/AJAX/Documentation/Live/ClientReference/Global/default.aspx"&gt;their documentation&lt;/a&gt; and outside the scope of this entry. For our purposes just note that we can attach event handlers and remove them easily. &lt;/p&gt;

&lt;p&gt;The final portion of code we will cover is the defining of our class. As mentioned earlier we need the entire class defined before we can extend it with our new entries. The Microsoft Framework has defined the following convention to the defining of classes along with inheritance&lt;/p&gt;

&lt;pre class="csharpcode"&gt;&lt;font size="1"&gt;YourCompanyHere.EditDNNAjaxModule1.registerClass(&lt;span class="str"&gt;'YourCompanyHere.EditDNNAjaxModule1'&lt;/span&gt;, Sys.Component);&lt;/font&gt;&lt;/pre&gt;
&lt;style type="text/css"&gt;



.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;

&lt;p&gt;As you can see we are inheriting from one of the objects defined in the Sys namespace (which is similar to System in .NET land). I will cover more of the specifics on why I chose this class in an upcoming blog. For those of you interested in reading more &lt;a href="http://www.asp.net/AJAX/Documentation/Live/tutorials/EnhancingJavaScriptTutorial.aspx"&gt;this site&lt;/a&gt; provides some useful information. &lt;/p&gt;

&lt;p&gt;One final note is that I will be soon releasing the next version of my DotNetNuke AJAX Module Templates to codeplex. The current version has a bunch of requirements that will be removed that deter developers from getting up and running easily. There is also a video available there covering much of the same content found here, though it is slightly dated. Look for the update soon at &lt;a href="http://www.codeplex.com/codeendeavortemplate"&gt;http://www.codeplex.com/codeendeavortemplate&lt;/a&gt;&lt;/p&gt;</description>
      <link>http://www.dotnetnuke.com/Community/Blogs/tabid/825/EntryId/2066/Utilizing-the-Microsoft-AJAX-Framework-and-ClientAPI-to-Develop-Rich-Modules-Part-I.aspx</link>
      <category domain="http://www.dotnetnuke.com/products/development/forge/componentwebcontrols/tabid/873/blogid/31/default.aspx">Core :: ClientAPI</category>
      <author>jon.henning@dotnetnuke.com</author>
      <comments>http://www.dotnetnuke.com/Community/Blogs/tabid/825/EntryId/2066/Utilizing-the-Microsoft-AJAX-Framework-and-ClientAPI-to-Develop-Rich-Modules-Part-I.aspx#Comments</comments>
      <guid isPermaLink="true">http://www.dotnetnuke.com/Community/Blogs/tabid/825/EntryId/2066/Utilizing-the-Microsoft-AJAX-Framework-and-ClientAPI-to-Develop-Rich-Modules-Part-I.aspx</guid>
      <pubDate>Mon, 10 Nov 2008 14:46:29 GMT</pubDate>
      <slash:comments>3</slash:comments>
      <trackback:ping>http://www.dotnetnuke.com/DesktopModules/Blog/Trackback.aspx?id=2066</trackback:ping>
    </item>
    <item>
      <title>New Video Available Demonstrating New CSS Capabilites in DNNMenu v2.0</title>
      <description>&lt;p&gt;With the launch of DotNetNuke 5 getting closer, I figured it was a good time to put together a quick video on some of the new functionality that will be found within the webcontrols.  This video will introduce you to the new ways you can customize version 2 of the DotNetNuke Menu by simply tweaking your css.  It starts out giving a brief overview of where we came from in earlier releases and how we are making strides to improve the ability for both a DotNetNuke skinner and end portal administrator.  Enjoy!&lt;/p&gt;&lt;a href=http://www.dotnetnuke.com/Community/Blogs/tabid/825/EntryId/1874/New-Video-Available-Demonstrating-New-CSS-Capabilites-in-DNNMenu-v2-0.aspx&gt;More...&lt;/a&gt;</description>
      <link>http://www.dotnetnuke.com/Community/Blogs/tabid/825/EntryId/1874/New-Video-Available-Demonstrating-New-CSS-Capabilites-in-DNNMenu-v2-0.aspx</link>
      <author>jon.henning@dotnetnuke.com</author>
      <comments>http://www.dotnetnuke.com/Community/Blogs/tabid/825/EntryId/1874/New-Video-Available-Demonstrating-New-CSS-Capabilites-in-DNNMenu-v2-0.aspx#Comments</comments>
      <guid isPermaLink="true">http://www.dotnetnuke.com/Community/Blogs/tabid/825/EntryId/1874/New-Video-Available-Demonstrating-New-CSS-Capabilites-in-DNNMenu-v2-0.aspx</guid>
      <pubDate>Thu, 19 Jun 2008 06:00:00 GMT</pubDate>
      <slash:comments>13</slash:comments>
      <trackback:ping>http://www.dotnetnuke.com/DesktopModules/Blog/Trackback.aspx?id=1874</trackback:ping>
    </item>
    <item>
      <title>Introducing DNNMultiStateBox</title>
      <description>&lt;p&gt;One of the new features coming in Cambrian is an update in the permissions grid.  The current grid supports two states, Allow and Null (not assigned).  The new grid will support three states (Allow, Deny, and Null).  The obvious question here is how do you present this to the user?  The current design allows for a nice compact way to set the permissions within a grid utilizing checkboxes.  The new way will use a new DotNetNuke WebControl that supports multiple states and mimics a checkbox.  The original name I came up with for the control was DNNTriStateCheckbox.  However, while developing this control I soon realized there was no reason I needed to only support 3 states and saw the opportunity to support any number of states and not necessarily look like a checkbox.  So the control is now called DNNMultiStateBox.  It is probably the simplest of all the controls in the &lt;a href="http://webcontrols.dotnetnuke.com/&amp;&lt;a href=http://www.dotnetnuke.com/Community/Blogs/tabid/825/EntryId/1835/Introducing-DNNMultiStateBox.aspx&gt;More...&lt;/a&gt;</description>
      <link>http://www.dotnetnuke.com/Community/Blogs/tabid/825/EntryId/1835/Introducing-DNNMultiStateBox.aspx</link>
      <category domain="http://www.dotnetnuke.com/products/development/forge/componentwebcontrols/tabid/873/blogid/56/default.aspx">Core :: WebControls</category>
      <comments>http://www.dotnetnuke.com/Community/Blogs/tabid/825/EntryId/1835/Introducing-DNNMultiStateBox.aspx#Comments</comments>
      <guid isPermaLink="true">http://www.dotnetnuke.com/Community/Blogs/tabid/825/EntryId/1835/Introducing-DNNMultiStateBox.aspx</guid>
      <pubDate>Mon, 12 May 2008 06:00:00 GMT</pubDate>
      <slash:comments>10</slash:comments>
      <trackback:ping>http://www.dotnetnuke.com/DesktopModules/Blog/Trackback.aspx?id=1835</trackback:ping>
    </item>
    <item>
      <title>Silverlight + PageMethods</title>
      <description>&lt;p&gt;Having attending this year's MVP Summit, I have to say I am even more interested in writing some &lt;a href="http://www.silverlight.net/"&gt;Silverlight&lt;/a&gt; applications.  One of the questions I am trying to answer is just how to get Silverlight to talk to the server, especially when it comes to &lt;a href="http://www.dotnetnuke.com/"&gt;DotNetNuke&lt;/a&gt; integration.  Some quick searching yielded this &lt;a href="http://wilcob.com/Wilco/News/silverlight-interoperability.aspx"&gt;excellent blog&lt;/a&gt; on how Silverlight and javascript can interact.  I thought it may be helpful to some people to see how to allow Silverlight to call into a &lt;a href="http://asp.net/ajax/documentation/live/tutorials/ExposingWebServicesToAJAXTutorial.aspx"&gt;PageMethod&lt;/a&gt; and pass and return a rich object.  I admit this may not be the best option, as I still need to do some research, but at a bare minimum this approach should&lt;a href=http://www.dotnetnuke.com/Community/Blogs/tabid/825/EntryId/1813/Silverlight-PageMethods.aspx&gt;More...&lt;/a&gt;</description>
      <link>http://www.dotnetnuke.com/Community/Blogs/tabid/825/EntryId/1813/Silverlight-PageMethods.aspx</link>
      <author>jon.henning@dotnetnuke.com</author>
      <comments>http://www.dotnetnuke.com/Community/Blogs/tabid/825/EntryId/1813/Silverlight-PageMethods.aspx#Comments</comments>
      <guid isPermaLink="true">http://www.dotnetnuke.com/Community/Blogs/tabid/825/EntryId/1813/Silverlight-PageMethods.aspx</guid>
      <pubDate>Mon, 21 Apr 2008 06:00:00 GMT</pubDate>
      <slash:comments>2</slash:comments>
      <trackback:ping>http://www.dotnetnuke.com/DesktopModules/Blog/Trackback.aspx?id=1813</trackback:ping>
    </item>
    <item>
      <title>MSBuild Packaging</title>
      <description>&lt;p&gt;One of the things I have been doing lately with my projects like the &lt;a href="http://www.codeplex.com/codeendeavortemplate"&gt;DotNetNuke CodeEndeavors AJAX templates&lt;/a&gt; along with the ClientAPI and WebControls is to use a custom MSBuild script to package the code up as part of the project's compilation.  Since a csproj/vbproj file is already a MSBuild script this is rather simple.  The problem I had was that the editing of these files within Visual Studio was cumbersome.  Having to right-click on the project in Solution Explorer and choose Unload Project, then right-click again and choose Edit xxxxx.vbproj, then make my modifications, then right-click again to reload the project was getting annoying. &lt;/p&gt;&lt;a href=http://www.dotnetnuke.com/Community/Blogs/tabid/825/EntryId/1802/MSBuild-Packaging.aspx&gt;More...&lt;/a&gt;</description>
      <link>http://www.dotnetnuke.com/Community/Blogs/tabid/825/EntryId/1802/MSBuild-Packaging.aspx</link>
      <author>jon.henning@dotnetnuke.com</author>
      <comments>http://www.dotnetnuke.com/Community/Blogs/tabid/825/EntryId/1802/MSBuild-Packaging.aspx#Comments</comments>
      <guid isPermaLink="true">http://www.dotnetnuke.com/Community/Blogs/tabid/825/EntryId/1802/MSBuild-Packaging.aspx</guid>
      <pubDate>Mon, 14 Apr 2008 06:00:00 GMT</pubDate>
      <slash:comments>0</slash:comments>
      <trackback:ping>http://www.dotnetnuke.com/DesktopModules/Blog/Trackback.aspx?id=1802</trackback:ping>
    </item>
    <item>
      <title>Minor Perf Optimization to Caspian Release</title>
      <description>&lt;p&gt;While sitting at the airport waiting for my plane to depart to the &lt;a href="https://www.mvpsummit2008.com/"&gt;MVP Summit&lt;/a&gt;, I decided to spend a little time optimizing the new ClientAPI (codenamed Caspian) for the Cambrian release.  One of the new features for this release was to allow the output of the ClientAPI and Webcontrols to emit compliant markup (more detail mentioned in &lt;a href="http://www.dotnetnuke.com/Community/Blogs/tabid/825/EntryID/1532/Default.aspx"&gt;this blog&lt;/a&gt;).  There was two areas that this affected my code.&lt;/p&gt;&lt;a href=http://www.dotnetnuke.com/Community/Blogs/tabid/825/EntryId/1801/Minor-Perf-Optimization-to-Caspian-Release.aspx&gt;More...&lt;/a&gt;</description>
      <link>http://www.dotnetnuke.com/Community/Blogs/tabid/825/EntryId/1801/Minor-Perf-Optimization-to-Caspian-Release.aspx</link>
      <category domain="http://www.dotnetnuke.com/products/development/forge/componentwebcontrols/tabid/873/blogid/31/default.aspx">Core :: ClientAPI</category>
      <author>jon.henning@dotnetnuke.com</author>
      <comments>http://www.dotnetnuke.com/Community/Blogs/tabid/825/EntryId/1801/Minor-Perf-Optimization-to-Caspian-Release.aspx#Comments</comments>
      <guid isPermaLink="true">http://www.dotnetnuke.com/Community/Blogs/tabid/825/EntryId/1801/Minor-Perf-Optimization-to-Caspian-Release.aspx</guid>
      <pubDate>Mon, 14 Apr 2008 06:00:00 GMT</pubDate>
      <slash:comments>0</slash:comments>
      <trackback:ping>http://www.dotnetnuke.com/DesktopModules/Blog/Trackback.aspx?id=1801</trackback:ping>
    </item>
    <item>
      <title>Javascript Global Namespaces (the dreaded $ function)</title>
      <description>&lt;p&gt;&lt;em&gt;The whole idea of the $ function and who "owns" that "namespace" has become quite muddy.  When I first learned of the use of $ and found that MS was adopting the same notation, I decided to do it as well.  For at the time, I felt that all frameworks simply used it as a quick way to get the reference to a DOM element.  Soon afterwards I learned that frameworks like prototyle use it for much more.&lt;/em&gt;&lt;/p&gt;&lt;a href=http://www.dotnetnuke.com/Community/Blogs/tabid/825/EntryId/1776/Javascript-Global-Namespaces-the-dreaded-function.aspx&gt;More...&lt;/a&gt;</description>
      <link>http://www.dotnetnuke.com/Community/Blogs/tabid/825/EntryId/1776/Javascript-Global-Namespaces-the-dreaded-function.aspx</link>
      <category domain="http://www.dotnetnuke.com/products/development/forge/componentwebcontrols/tabid/873/blogid/31/default.aspx">Core :: ClientAPI</category>
      <author>jon.henning@dotnetnuke.com</author>
      <comments>http://www.dotnetnuke.com/Community/Blogs/tabid/825/EntryId/1776/Javascript-Global-Namespaces-the-dreaded-function.aspx#Comments</comments>
      <guid isPermaLink="true">http://www.dotnetnuke.com/Community/Blogs/tabid/825/EntryId/1776/Javascript-Global-Namespaces-the-dreaded-function.aspx</guid>
      <pubDate>Mon, 24 Mar 2008 08:00:00 GMT</pubDate>
      <slash:comments>3</slash:comments>
      <trackback:ping>http://www.dotnetnuke.com/DesktopModules/Blog/Trackback.aspx?id=1776</trackback:ping>
    </item>
    <item>
      <title>ClientAPI / WebControls 2.0 Public Beta</title>
      <description>&lt;p&gt;The ClientAPI and WebControls Beta codenamed Caspian and DawnTreader are now being released to the general public. Features of this release include:&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;Tweening&lt;/li&gt;
    &lt;li&gt;Control Methods&lt;/li&gt;
    &lt;li&gt;Conversion of entier ClientAPI and WebControls to utilize MS AJAX Framework&lt;/li&gt;
    &lt;li&gt;Embedded and Compressed scripts&lt;/li&gt;
    &lt;li&gt;XHTML Compliant output&lt;/li&gt;
    &lt;li&gt;and much &lt;a href="http://www.dotnetnuke.com/Community/Blogs/tabid/825/EntryID/1532/Default.aspx"&gt;more&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;An additional incentive to try out this new functionality is being offered by the recently released &lt;a href="http://www.codeplex.com/codeendeavortemplate"&gt;DotNetNuke Module Templates&lt;/a&gt; on CodePlex:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;DotNetNuke Compiled AJAX Module&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;This Template offers the skeleton structure for creating highly efficient AJAX templates. It encourages the developer to encapsulate logic within client-side objects to minimize naming conflicts. It also demonstrates how to use the new AJAX callback framework (ControlMethods) in the new ClientAPI. Additionally, it offers a solution to manage localization of messages in your javascript along with allowing modules to communicate safely on the client-side. Finally, it comes with a MSBuild script that automatically versions, packages, and deploys your module during a compile.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;DotNetNuke Compiled SilverLight Module&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The Silverlight Template allows the developer to quickly integrate SilverLight into DotNetNuke. The method used insulates the client-side logic from conflicts with other modules on the page, including multiple instances of the same module.  It also comes with a MSBuild script that automatically versions, packages, and deploys your module during a compile.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;But Wait, Theres More!&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;In order to get you up to speed on installing, customizing, and using the templates, I have created several videos that walk you through the specifics of installing and using the templates.  Videos can be obtained from the CodePlex project page .&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Please Remember&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The ClientAPI and WebControls are still beta.  Do &lt;strong&gt;not&lt;/strong&gt; install on production servers.  There is no known issues with the code, however, the amount of testing in the community has been minimal.  If you care about backwards compatibility please take some time and test.  The simple steps to install are outlined in the Using the DotNetNuke Module Templates video.  Please post any feedback on your testing in the &lt;a href="http://www.dotnetnuke.com/Community/Forums/tabid/795/forumid/76/scope/threads/Default.aspx"&gt;ClientAPI forum&lt;/a&gt;.&lt;/p&gt;</description>
      <link>http://www.dotnetnuke.com/Community/Blogs/tabid/825/EntryId/1675/ClientAPI-WebControls-2-0-Public-Beta.aspx</link>
      <author>jon.henning@dotnetnuke.com</author>
      <comments>http://www.dotnetnuke.com/Community/Blogs/tabid/825/EntryId/1675/ClientAPI-WebControls-2-0-Public-Beta.aspx#Comments</comments>
      <guid isPermaLink="true">http://www.dotnetnuke.com/Community/Blogs/tabid/825/EntryId/1675/ClientAPI-WebControls-2-0-Public-Beta.aspx</guid>
      <pubDate>Wed, 12 Dec 2007 18:27:18 GMT</pubDate>
      <slash:comments>3</slash:comments>
      <trackback:ping>http://www.dotnetnuke.com/DesktopModules/Blog/Trackback.aspx?id=1675</trackback:ping>
    </item>
  </channel>
</rss>