ASP.NET AJAX has many helpful features that make developing
ASP.NET applications asynchronous. Sometimes though, with the out-of-the-box
controls in the ASP.NET framework, it is hard to tap into the existing control
architecture to add custom JavaScript capabilities. Oftentimes, creating your
own custom control just to perform those actions on the client-side is what is
needed. To understand how to add AJAX to an existing ASP.NET control requires a
thorough understanding that the various paths server controls can take through
the process. What I mean by that is some server controls render different HTML
markups based upon the input settings. One instance is the Textbox control: in
single line mode, it renders an <input type="text"> element, in
multi line mode, it renders a <textarea> element, and in password mode it
renders an <input type="password"> element.
In this article, I am focusing more on building additional
features of an existing ASP.NET web site to incorporate some new AJAX features. The idea for these new features is to prevent as many postbacks as possible,
and to create a richer user experience.
So why create a richer experience, and prevent posting back?
Preventing post backs reduces the amount of binding that often takes place. A
.NET application may often bind data to a GridView or ListView just to refresh
the user interface, for the purposes of changing display modes, sorting, paging,
or the like. All of the data gets rebound only to change modes or because of
the possibility that some other user or process modified or added data to the
system. This approach provides more of an instantaneous response than posting
back to the server can do. In addition, it reduces the payload of pushing HTML
to the client, which increases the payload being transferred across the wire.
The key to performing work on the client is to do two kinds
of work: sending the data to the server, and manipulate the client. In a
server-only approach without AJAX, the data that the user manipulates gets
posted back along with the action that occurred, letting the underlying control
know that an insert or update occurred and re-render its interface by binding
again.
On the client, all of the work to create or refresh the user
interface must occur on the client; simply binding again does not refresh the
user interface. There are many other nuances to be aware of when shifting logic
from the server to the client. So while the server approach is easy, and it is
easy to use an UpdatePanel, it may often be better to use a client-side
scripting approach to generating the user interface.
When shifting logic from the server to the client, be aware
of some initial problems. First, any control marked as
Visible="false" does not render in markup. The underlying HTML
element rendered is not in the document object model, and thus cannot be
manipulated and may cause client-side scripting errors. The better alternative
would be to add null checks in JavaScript code, or set the style="display:none"
property on the server control (which maps over to the client correctly for
most controls).
Another complexity can come from understanding how the
server control renders. I mentioned this before, but I will mention another
example that can happen with the CheckBoxList control. The list can render in
vertical or horizontal modes, and can repeat depending on the settings of the
RepeatLayout, RepeatDirection, and RepeatColumns properties. Depending on the
RepeatLayout property, the underlying structure can render as a table or in
flow mode. In flow mode, the actual text is not inside the checkbox tag, but
rendered in a label element (not to be confused with the label server control).
Another issue to be aware of is dynamically generated ID's. Always
provide an ID, because a null ID does not generate the id attribute on the
client side, and this does not jive with Firefox. Firefox needs the id to use
document.getElementById, while Internet Explorer will use the name attribute as
well.
With that said, let us begin to look at how we are going to
improve upon the process.