Introduction
The key words to describe what's new in the overall ASP.NET 4.0 platform are "more control." ASP.NET 4.0 is neither a revolutionary change nor a refactoring of its existing architecture. It consists, instead, of a good number of small-scale changes that together provide developers with much more control of certain frequently used features of the existing framework.
For example, ASP.NET 4.0 Web Forms give developers more control over viewstate management, generation of IDs in the context of data-bound controls, and HTML generated by some template-based controls. In addition, you'll find new families of pluggable components for features that weren't supporting the provider 2009 model in earlier versions of ASP.NET and a finer control over the linking of external script files through the ScriptManager control. Let's start with viewstate management.
More Control Over the Viewstate
I say nothing new by stating that the viewstate has been one of the most controversial features of ASP.NET since the advent of the platform. Too many developers are still convinced that the viewstate is a waste of bandwidth and an unacceptable burden for each and every ASP.NET page. Nearly the same set of developers eagerly welcomed ASP.NET MVC because of its complete absence of viewstate. Recently, while teaching an ASP.NET MVC class, I discussed a master/detail scenario in which the user could select a customer from a list to see more details. I populated the list during the loading of the page, as expected. Next, while handling the selection-changed event, I showed how to fill in the customer's details. However, to have the list available for another selection, I also had to explicitly repopulate it.
Students promptly noted the extra work required to fill in the list at every server action. Couldn't this be automatically filled as in Web Forms? Well, in ASP.NET Web Forms you don't need to refill data-bound controls over a postback just because of the viewstate.
In short, the viewstate is not there only to reduce your bandwidth. The viewstate is functional to the Web Forms model, as it caches some of the content for the controls in the page. Next, the ASP.NET infrastructure takes care of reading that information from the viewstate to restore the last known good state for each control within the page.
As widely known, but also largely overlooked, the viewstate is an optional feature. The viewstate support is turned on for each page by default, but developers have a Boolean property available to change the default setting and do without it. The property is named EnableViewState and is defined on the System.Web.UI.Control class. It should be noted that the System.Web.UI.Page class inherits from the Control class. As far as the viewstate is concerned, an individual control and the page are one and the same.
For any ASP.NET page, turning off the viewstate couldn't be easier. You set EnableViewState to false either declaratively or programmatically during the page's life cycle, as follows:
void Page_Load(object sender, EventArgs e)
{
Figure 1 The ViewStateMode Enumeration
msdn magazine
2
Cutting Edge
// Disable viewstate for the page
// and ALL of its child controls
this.EnableViewState = false;
...
}
The EnableViewState property indicates whether the control is allowed to cache its own UI-related state. Be reminded that the viewstate setting in ASP.NET has a hierarchical nature, which means that if the viewstate is enabled on the parent control, it cannot be disabled on any of its child controls. The following code has no effect on the behavior of the text box if the viewstate is enabled at the page or container level:
protected void Page_Load(object sender, EventArgs e)
{
TextBox1.EnableViewState = false;
}
The IsViewStateEnabled property -- a protected property indeed -- reports about the current state of the viewstate for a control. But what does all of this mean to developers?
If the viewstate is enabled on the page (which is the default setting), you have no means to keep the state of individual controls off the storage. To gain some control over it in ASP.NET 3.5, you need to disable the viewstate at the page level and then re-enable it where needed, but also keep in mind the hierarchical nature of it. Any container control that has the viewstate enabled will inevitably push its setting down to the list of its children. This fact leads to somewhat of a paradox: it is possible for the same control to have the property IsViewStateEnabled set to true and the property
EnableViewState set to false!
The viewstate is a fundamental piece of the ASP.NET Web Forms architecture, and dropping it entirely from the platform in the name of a performance gain is arguably not the best option. Years of experience has proved that a more sustainable option is having the viewstate disabled by default on the page. Even better than that is the change coming up with ASP.NET 4.0: enabling viewstate control over individual controls.
In ASP.NET 4.0, the System.Web.UI.Control class exposes a new property named ViewStateMode:
public virtual ViewStateMode ViewStateMode { get; set; }
The property takes its feasible values from the ViewStateMode enumerated type, shown in Figure 1.
To preserve compatibility, the default value of the property is Inherit. However, this property gives developers the possibility of controlling the viewstate setting for individual controls, regardless of the viewstate option of any parent page or containers.
Only a few of the controls in ASP.NET pages really need viewstate. For example, all text boxes you use to simply gather text don't need viewstate at all. If Text is the only property you use on the control, then the value of the Text property would be preserved by cross-page postbacks because of posted values. Any value stored in the viewstate, in fact, will be regularly overwritten by the posted value. In this case, the viewstate is really unnecessary. But there's more to notice. Any side properties that are set to a given non-default value on creation, but remain unchanged during postbacks (such as ReadOnly, BackColor and so on), have no need to go to the viewstate. For example, a Button control that retains the same caption all the time doesn't need the viewstate at all. Up until ASP.NET 4.0, turning off the viewstate for individual controls was problematic. Things change in the next version. This is the key takeaway of the ViewStateMode property.
More Control Over Auto-Generated IDs
In ASP.NET pages, using the same ID for two server controls isn't allowed. If this happens, the page won't compile -- period. In HTML, though, it is possible for two or more elements to share the same ID. In this case, when you make a search for an element via document.getElementById, you'll simply get an array of DOM elements. What about nested ASP.NET controls?
Most data-bound, template-based controls generate their output by repeating an HTML template for every data-bound item. This means that any child control defined with a unique ID in the template is being repeated multiple times. The original ID can't just be unique. For this reason, since the beginning, the ASP.NET team defined an algorithm to ensure that every HTML element emitted by an ASP.NET control could be given a unique ID. The ID resulted from the concatenation of the control ID with the ID of the naming container. Furthermore, in case of repeated controls (i.e., templates), a numeric index was added for disambiguation. For years, nobody really cared about the readability of the auto-generated ID, and strings like the following became fairly common:
ctl00$ContentPlaceHolder1$GridView11$TextBox1
Looking at this, the first issue that may come to mind is the potential length of the string, which, repeated for several elements, makes the download larger. More important, such an approach is problematic from a client script perspective. Predicting the ID of a given control you want to script from the client is difficult, and leads straight to hard-to-read code. In the first place, you need to know the detailed name being generated for a given HTML element that is buried in the folds of a grid or any other naming container controls. Second, this name is subject to change as you rename one of the server controls along the hierarchy. A frequently used trick is the following:
var btn = document.getElementById("<% =Button1.ClientID %>");
The trick consists in using ASP.NET code blocks to insert in the HTML source code being generated for the real client ID of a given control. When master pages or template-based controls are used, the trick is a real lifesaver, because in this case, the naming container of a plain control ends up being quite a complex hierarchy of controls that developers often leave unnamed. The actual name of the control, therefore, is subject to a few auto-generated IDs.
In addition to using code blocks, ASP.NET 4.0 supports another option: more control over the algorithm that generates the client ID of a server control.
The System.Web.UI.Control class now features a brand new property named ClientIDMode. The property can assume a few predefined values as detailed in Figure 2.
Admittedly, the ID-generation algorithm, especially when master pages are involved, is not easy to understand. It is guaranteed to generate unique IDs, but ends up with strings that are really hard to predict. A more predictable option has been introduced primarily to be used with data-bound controls so that developers can easily guess the ID of, say, a Label control used to render a given property on the nth data item. In this case, you want the ID to reflect the hierarchy of the control (simplifying the naming container structure to the parent controls) but also a particular key value, such as the primary key. Consider the following code:
<asp:GridView ID="GridView1" runat="server"
ClientIDMode="Predictable"
RowClientIdSuffix="CustomerID">
...
</asp:GridView>
In this case, each row of the grid is identified by one or more columns in the data source with a trailing index. Here's an example:
The GridView is the sole control to support multiple columns. If you have multiple columns to concatenate, then you use the comma to separate names. The ListView will accept only one column, whereas the Repeater control will limit to trail a 0-based index and accept no column name.
Finally, note that the ClientIDMode property affects only the ID attribute of the resulting HTML element. By design, the name attribute remains unchanged.
HistoryPart 1
part 2(upcoming)