The .NET event model enables sophisticated server-based processing, but it leaves developers to struggle with specific client issues like presenting dialog boxes and setting control focus. To help mitigate issues where server-based functionality is unsuitable for the desired interface interaction, .NET offers a series of methods for generating client-side scripts to invoke browser functionality. Here I will discuss the details of these rendering routines as well as other .NET mechanisms for controlling browser behavior.

How it works
.NET programming revolves around the server and server-side event handling. Every server control has a series of events that trigger event handlers written in application code and executed on the server. Also, .NET Web systems maintain most data structures and extended state information on the server. This offers many advantages over traditional Web scripting, including better debugging, easier application program support, and superior error handling.

Where is the logic in .NET?

Numerous browser versions make client-side scripting a tedious task, but .NET aims to solve the problem with Web controls. Read this article to find out about some of the difficulties associated with this approach.

Certain user interactions, however, are not supported by the server-centric programming approach offered by .NET. In these cases, the Web developer must embed logic in the client script and utilize a browser to process certain user requests. While contrary to the spirit of .NET server-based programming, browser-based scripting is a mainstay of traditional Web development, offering distinct advantages in terms of functionality, bandwidth requirements, and speed.

While embedding client script in a .NET application can be as simple as adding script tags using Visual Studio’s HTML editor, more common scenarios include:

  • Combining persistent server information with client scripted actions.
  • Raising and handling server control events on the client, which requires more complex development.

In the first case, we must determine a mechanism for accessing server variables while executing a client script block. The second case requires a manual method for rendering additional, specialized HTML along with the automatically rendered JavaScript of the server control.

Accessing server state from client script
Addressing the first case, you’ll quickly discover that accessing stateful information directly from the server during client script execution is not possible within the .NET framework. Client script executes within the document object model (DOM) framework of the browser, and variables declared in session variables, application variables, or code-behind pages are server based and out of scope (for client script) at run time. While client-side programmers have faced this problem with many different application server technologies over the years, .NET’s support of page-level variables and its server-side bias exacerbates the problem.

For example, let’s say that you want to pop up a dialog that displays the user’s name, which is currently stored in a session variable. Retrieving session information in .NET is very straightforward but is strictly a server-side operation. However, presenting a dialog box is a client-side operation and can only be initiated through client script. How do we pass our retrieved session information from the server directly to the client script block?

The solution lies in an inelegant technique very familiar to Microsoft VB developers and traditional ASP developers—the hidden form control. By placing a text field or label on a form, the data becomes accessible through the control’s value. The control is then hidden using a visibility attribute. The .NET version of this solution uses a hidden server control placed on the form so server-side code can set the control’s value. Since simple server controls are rendered as HTML to the browser with their unique IDs intact, a client script block will be able to read the value of the control as set by the server. Using hidden form variables in .NET, rather than hidden server controls, will yield the same results and render similar HTML to the client.

Generating client-side events from server controls
For the second scenario, executing client script from a server control event, you must trigger a client-side event and handle it with client code. Remember, the power of .NET and the advantage of server controls stems from the server event model. To avoid post-back latencies and handling user interactions that are solely client based, execute a client as well as (or instead of) a server event.

You cannot specify a client-side event handler for most events in the HTML syntax for a Web server control. Instead, an event attribute specifying the client function must be added to the control through application code during the initialization phase of the Web form. With a client function event attribute added to the control, a triggering event will cause execution of the client function. Note that the client event fires first and the usual server events follow.

There are a few server controls, which have an intrinsic onchange event for triggering client-side actions and do not require adding an attribute specifying the client event handler. For example, the CheckBox control will raise the onchange event whenever the box is checked or unchecked. Intrinsic events are designed to simplify client-side event handling for common user actions on certain controls.

Manually rendering client script
Whether triggered by an intrinsic event or through an added event attribute, the actual client script must be created for execution of the desired action, once the event is captured. Creating a dynamic client event handler requires programmatically building (concatenating) client script from the server and rendering it to the page. The .NET libraries supply two methods in the namespace System.Web.UI.Page that does the job.

The method used depends on where on the client page the script is required; although in each case, the script block uses a key to ensure that it is not rendered more than once per page. The RegisterClientScriptBlock method is used to render client script at the top of the page. This is useful when you want to render a script block that contains some general functions, which are invoked later in the page. A second method, RegisterStartupScript, emits the script at the end of the page. RegisterStarupScript creates startup scripts that typically reference the other elements on the page and are often executed just before page display.

Not all client event handlers require emitting client script through application methods. In some cases, the client script can simply be added to the page using the HTML editor at design time. The RegisterClientScriptBlock or RegisterStartupScript methods are required, however, for row-level events triggered in DataGrids or whenever the control ID is unknown at design time. These methods are also useful for creating complex script blocks with embedded server values and as alternatives to the hidden form control technique.

Like the hidden form field, manually rendering script on the server for output to the client page is a common technique well familiar to Web programmers. However, it is notoriously difficult to debug and violates best practices for strongly partitioned application and presentation code. Additionally, various scripting tags and syntax must be incorporated into the output string requiring complex string concatenation with escape characters and embedded punctuation. Ironically, in most cases, Web server controls greatly reduce the requirement for manual script generation from the server. But highly interactive user interfaces may be the exception to the rule.

Higher hopes
Creating engaging user interfaces is a primary goal of Web programming. Engaging the user has many facets, but at the least, simple feedback mechanisms such as control focus pop-up dialogs and mouseovers are necessary. While offering a vast new environment for event handling and server-side programming, .NET still relies on timeworn and inelegant mechanisms for some very simple user interactions. Hidden form fields and manually rendered scripts are sufficient for the task but seem less than optimal compared to the sophistication and precision of the rest of .NET. This may be inconsequential for Web site developers without requirements for highly interactive experiences. But for those tasked with creating all the bells and whistles found in finely crafted client-centric sites, .NET development may leave you feeling left in the past.