Building JavaScript Custom Controls in ASP.NET

Building a rich and highly interactive browser experience in a componentized fashion is easy with .NET Custom Controls. In this abstract we will show how to build a custom control where we have full control over the HTML and javascript generated as well as how to use that javascript to generate events in server side code. This article explores these concepts by creating a simple Social Security Number custom control that formats the data entry of the Social Security Number and fires a server side event to check the database for duplicate entries.

Benefits of Custom Controls
The two major benefits of developing custom controls are rich design time support and a component model that can be compiled into a sharable DLL. In addition to these two major benefits, custom controls can be far more efficient at producing controls that generate a large number of fields dynamically.

Custom Controls provide us many methods to define how our component should behave when in design view including the ability to create custom property editors. The design time support is a huge win for companies that depend on UI design teams that are separate from the development teams. Once the development team has completed a new custom control, they can provide that control to the UI team in a way they can easily use to create mockups in popular applications such as Dream weaver to develop future mockups for the development team.

If we are building a very large web application or if we need to develop controls that can be used in multiple web projects the only effective way of sharing controls is to use a Custom Control. Most developers choose to develop User Controls (.ascx) files because they are easier in many ways to develop, they support visual authoring and we can build them basically like we build a normal. ASPX page. This ascx control, however, must be copied to each of our web projects where we want to use it. As a result, we will have the same source code in multiple places and the strong possibility of code fragmentation creeps into view.

Adding JavaScript to Custom Controls
Now that we've got a reliable way of naming our elements in the HTML we generate within our custom control, we can now apply javascript to it. In order to format the Social Security Number to automatically add the hyphens at the appropriate location a simple check is done any time a key is pressed to see if the hyphen is present in the correct location. Although the javascript algorithm used in this article is simple, it covers most situations. This javascript code is added in code behind file.

<?xml:namespace prefix = v ns = "urn:schemas-microsoft-com:vml" />
protected override void CreateChildControls()


{


                base.CreateChildControls ();


                StringBuilder sb = new StringBuilder(1000);


                sb.Append(" ");


                Page.RegisterClientScriptBlock("FormatSSN", sb.ToString());


}

The second item of note in the code above is the use of Page.RegisterClientScriptBlock. Utilizing this function will insure that no matter how many times our control is used on a page, our function will be declared once and only once. To do it any other way would likely cause our function to be included twice causing an embarrassing javascript error to every user that accesses our page.

Finally, please note that the Page.RegisterClientScriptBlock call is done in the CreateChildControls() method. This method is called fairly early in the control initialization process (Definitely before our control's render method is called). If we were to write out our javascript in the render method or even to call Page.RegisterClientScriptBlock in our render method we would definitely find the results to be unreliable at best. It might work sometimes, but under certain conditions our control would misbehave badly.

 

Generating a Server-Side Event from Javascript

To declare you object's ability to process PostBack events, all we have to do is implement the IPostBackEventHandler and implement the RaisePostBackEvent method. The RaisePostBackEvent method is called any time a postback is called that references your control's ID as the target. What you do with the eventArg passed to it is up to you. Generally for clean coding purposes, it's nice to generate a real event although it's not necessary if you can do what you want inside of the RaisePostBackEvent method itself.

public void RaisePostBackEvent(string eventArgument)


{


                if(eventArgument=="CHECKDB")


                {


                                SelectedSSN = Page.Request[""+ this.ClientID +"_SSN"];


                                /* Check the database for duplicates of this SSN


                                 * To keep this example focused, this code was eliminated.


                                 */


                }


}

If you're trying to do something more complicated inside of your control such as pass a value to your event handler, try utilizing a known prefix followed by your value. For example, if you'd like to pass the number "2" back to the server with the action "Load", try something like:

if(eventArgument.Substring(0,4)=="Load")
{
                String lookupVal = eventArgument.Substring(5);
}

The second half of generating the server side event is to generate the javascript that will cause the postback to happen and the event to fire. The Page.GeneratePostBackEventReferance() method takes the ClientID of your control and the eventArgument you would like to pass back to the server as an argument.

protected override void Render(HtmlTextWriter output)

{


                output.Write("

                output.Write("cellpadding=\"0\">");

                output.Write("

");

                output.Write("

");

                output.Write("

");

                output.Write("

");

                output.Write("

                output.Write("onkeyup=\"FormatSSN('"+ this.ClientID +"')\" ");

                output.Write("id=\""+ this.ClientID +"_SSN\" name=");

                output.Write("\""+ this.ClientID +"_SSN\" ");

                output.Write("value=\"");

                output.Write(SelectedSSN);

                output.Write("\">

                output.Write("value=\"Check For Duplicates\" onclick=\"");

                output.Write(Page.GetPostBackEventReference(this, "CHECKDB"));

                output.Write("; return false;");

                output.Write("\">

");

}

Performance Considerations using Custom Controls

If you're creating a control that is a grid of 5 text boxes per row formatted inside of a table with 10 rows. In terms of object allocation that is:

·          1 Table Object.
·          10 Row Objects.
·          50 Table Column objects.
·          50 TextBox objects.

That's over 100 object creation calls to render what is a fairly simple table. In addition to instantiating those objects, those objects also instantiate many more objects to perform their function of getting the table rendered. This leads to an order of magnitude problem that my profiler shows over 500 objects being allocated for a fairly simple operation. It is well known in both .NET and in Java that excessive object creation leads to excessive garbage collection, which in turn can cause tremendous problems for overall performance.

Rendering the same basic structure as a custom control where you take responsibility for rendering out your table and the related texboxes and produce dramatically fewer objects overall.

Conclusion

.NET Custom Controls provide the level of control required to develop rich client side behavior while maintaining a clean server side component model that is easily sharable among different web projects.

Hide comments

Comments

  • Allowed HTML tags: <em> <strong> <blockquote> <br> <p>

Plain text

  • No HTML tags allowed.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Lines and paragraphs break automatically.
Publish