Programming Microsoft ASP.NET 英文翻译

Chapter 3: ASP.NET Core Server Controls

Overview

It does not matter how slowly you go so long as you do not stop.
                                         -Confucius

ASP.NET pages are made of code, markup tags, literal text, and server controls. Based on the request, the server controls generate the right markup language. The ASP.NET runtime combines the output of all controls and serves the client a page to display in a browser.

The programming richness of ASP.NET springs from the wide library of server controls that covers the basic tasks of HTML interaction—for example, collecting text through input tags—as well as more advanced functionalities such as grid-based data display. In the ASP.NET world, more advanced and very specific controls ensure all basic tasks and common functionalities are available. The AdRotator and Calendar controls are two illustrious examples.

Key to ASP.NET control programming is the runat attribute. If a control is declared without the runat attribute, it is considered plain text and is output verbatim. If a control contains the runat attribute set to the value of "server", ASP.NET creates and handles an instance of the control while processing the page on the server. All this happens transparently to the user and the programmer as part of the ASP.NET runtime infrastructure.

In Chapter 1, we identified two main families of server controls—HTML server controls and Web server controls. In ASP.NET, these controls are typically referred to as HTML controls and Web controls. HTML controls map to HTML tags and are implemented through server-side classes whose programming interface faithfully represents the standard set of attributes for the corresponding HTML tag. Web controls, in turn, are a more abstract library of controls in which adherence to HTML syntax is much less strict. As a result, Web and HTML controls share a large common subset of functionalities and, in spite of a few exceptions, we could say that Web controls, functionally speaking, are a superset of HTML controls. Web controls also feature a richer development environment with a larger set of methods, properties and events.

As we'll see in more detail in the following pages, a second and more thoughtful look at the characteristics of the server controls in ASP.NET reveals the existence of more than just two families of controls. In real-world ASP.NET applications, you'll end up using controls from at least the following categories: HTML controls, Web controls, validation controls, data-bound controls, user controls, mobile controls, and custom controls. Validation controls are a special subset of Web controls and deserve to be treated in a separate section. Data-bound controls are not a category per se, with features that make them different from HTML or Web controls. Data-binding, instead, refers to the control's capability of connecting some of its properties to particular data sources. Hence, data-bound controls fall into any of the previously listed groups of server controls, but deserve a section of their own because of their importance and frequent use. User controls—also referred to as pagelets in relatively outdated literature—are visual aggregates of existing Web and HTML controls that appear as individual, encapsulated, programmable controls to external callers. Mobile controls are used when creating Web applications that target mobile devices. Custom controls refer to server controls you create that derive from a base control class.

In this chapter, we'll cover HTML controls, Web controls, validation controls, and data-bound controls. We'll cover user controls in Chapter 10, mobile controls in Chapter 11, and custom controls in Chapter 18 through Chapter 20.






Generalities of ASP.NET Server Controls

All ASP.NET server controls, including HTML and Web controls plus any custom controls you create or download, descend from the Control class. The class is defined in the System.Web.UI namespace and, as we discussed in Chapter 2, also represents the foundation of all ASP.NET pages. The Control class is declared as follows:

public class Control : IComponent, IDisposable, IParserAccessor,
IDataBindingsAccessor

The IComponent interface defines the way in which the control interacts with the other components running in the common language runtime (CLR), whereas IDisposable implements the common pattern for releasing unmanaged resources. The IParserAccessor interface enables the control to work as the container of child controls. Finally, the IDataBindingsAccessor interface makes the control capable of supporting data-binding expressions at design time. The IDataBindingsAccessor interface defines a read-only collection—the DataBindings property—that contains all the data bindings for the controls available to rapid application development (RAD) designers such as Microsoft Visual Studio .NET. Note that the collection of data bindings exist only at design time and, as such, is useful only if you write a RAD designer for the control. (Design-time features are discussed further in Chapter 21.)

Properties of the Control Class

The properties of the Control class have no user interface–specific features. The class, in fact, represents the minimum set of functionalities expected from a server control. The list of properties for the Control class is shown in Table 3-1.

Table 3-1: Properties of a Server Control

Property

Description

ClientID

Gets the ID assigned to the control in the HTML page. The string is a slightly different version of the UniqueID property. UniqueID can contain the colon symbol (:), but this symbol is not allowed in ClientID and is replaced with the underscore (_).

Controls

Gets a collection filled with references to all the child controls.

EnableViewState

Gets or sets whether the control should persist its view state—and the view state of any child controls across multiple requests—to the configured location (for example, HTML hidden field, Web server memory, server-side databases or files).

ID

Gets or sets the name that will be used to programmatically identify the control in the ASP.NET page.

NamingContainer

Gets a reference to the control's naming container. A naming container is the namespace to which the control belongs. If the control doesn't define its own naming space, a reference to the parent control (or the page) is returned.

Page

Gets a reference to the Page instance that contains the control.

Parent

Gets a reference to the parent of the control in the page hierarchy.

TemplateSourceDirectory

Gets the virtual directory of the host page.

UniqueID

Gets a hierarchically qualified ID for the control.

Visible

Gets or sets whether ASP.NET has to render the control.

The Control class is the ideal base class for new controls that have no user interface and don't require style information.

Identifying a Server Control

The client ID of a control is generated from the value of the UniqueID property—the truly server-side identifier that ASP.NET generates for each control. The contents of the ClientID property differ from UniqueID simply in that all occurrences of the colon symbol (:) are replaced with the underscore (_). Colons in the UniqueID string are possible only if the control belongs to a naming container different than the current one—typically, the page.

ASP.NET generates the value for the UniqueID property based on the value of the ID property that the programmer indicates. If no ID has been specified, ASP.NET autogenerates a name such as _ctlX, where X is a progressive 0-based index. If the control's naming container is the host page, UniqueID simply takes the value of ID. Otherwise, the value of ID is prefixed with the string representing the naming container and the result is assigned to UniqueID.

Note 

For performance reasons, ASP.NET caches into a static array defined on the Control class the strings ranging from _ctl0 to _ctl127. These autogenerated and cached IDs will be used for the first 128 controls in the page defined with an empty ID string. If you have more than 128 controls with an empty ID, the ID string is generated on the fly for each control instance.

Visibility of a Server Control

If you set Visible to false, ASP.NET doesn't generate any HTML code for the control. However, having Visible set to false doesn't really mean the control's code can't output text. The control is still an active object that exposes methods and handles events. If a method, or an event handler, sends text directly to the output console through Response.Write, this text will be displayed to the user anyway. A control with the Visible attribute set to false is still part of the page and maintains its position in the control tree.

Methods of the Control Class

The methods of the Control class are listed and described in Table 3-2.

Table 3-2: Methods of a Server Control

Method

Description

DataBind

Fires the OnDataBinding event and then invokes the DataBind method on all child controls

Dispose

Gives the control a chance to perform clean-up tasks before it gets released from memory

FindControl

Looks for the specified control in the collection of child controls. Child controls belonging to a different naming container are not sought.

HasControls

Indicates whether the control contains any child controls

RenderControl

Generates the HTML output for the control

ResolveUrl

Resolves a relative URL to an absolute URL based on the value passed to the TemplateSourceDirectory property

At the Control class level, the DataBind method works recursively and simply loops through all the child controls and calls DataBind on each of them. On derived data-bound controls, the method resolves all data-binding expressions and updates the status of the control itself.

Events of the Control Class

The Control class also defines a set of base events that all server controls in the .NET Framework support, as described in Table 3-3.

Table 3-3: Events of a Server Control

Event

Description

DataBinding

Occurs when the DataBind method is called on a control and the control is binding to a data source

Disposed

Occurs when a control is released from memory—the last stage in the control life cycle

Init

Occurs when the control is initialized—the first step in the life cycle

Load

Occurs when the control is loaded into the page. Occurs after Init.

PreRender

Occurs when the control is about to render its content

Unload

Occurs when the control is unloaded from memory

All server controls are rendered to HTML using the RenderControl method and, when this happens, the PreRender event is fired.




HTML Controls

In ASP, HTML tags inserted in the layout of the server page were treated as opaque text and output to the client verbatim. This behavior has been entirely maintained in ASP.NET. A big difference, though, is that in ASP.NET, by simply adding the runat attribute with a value of "server", you can bring to life otherwise-dead HTML text. Once transformed into a living instance of a server-side component, the original tag can be configured programmatically using an object-oriented approach. By design, HTML controls expose a set of methods and properties that carefully reflect the HTML syntax. For example, to set the default text of an input form field, you use a property named Value—case does matter in C# but not in Microsoft Visual Basic .NET—instead of the more expressive Text. The name of the server control is determined by the value of the id attribute. The following code snippet shows how to define a server-side input tag named lastName:

<input runat="server" id="lastName" type="text" />

The tag declaration does not include an explicit and static value for the Value attribute, which can be configured programmatically as follows:

void Page_Load(object sender, EventArgs e)
{
lastName.Value = "Esposito";
}

After being processed by the ASP.NET runtime, the preceding declaration generates the following HTML code:

<input name="myName" id="myName" type="text" value="Esposito" />

Notice that a server-side id attribute expands to a pair of HTML attributes—name and id. Be aware that this happens for browser compatibility. In no way, does this mean that on the server name and id can be interchangeably used to name the server instance of the control. The name of the server control instance is given by id. If you specify both name and id on a server-side tag, the value assigned to name will be silently overridden.

Generalities of HTML Controls

The .NET Framework provides predefined server controls for commonly used HTML elements such as <form>, <input>, and <select>, as well as for tables, images, and hyperlinks. All the predefined HTML server controls inherit from the same base class—the HtmlControl class. In addition, each control then provides its own set of specific properties and its own events.

Controls typically supply properties that allow you to manipulate the HTML attributes programmatically from within server code. HTML controls integrate well with data-binding and the ASP.NET state maintenance, and they also provide full support for postback events and client scripting. For example, for a button that gets clicked, you can have some JavaScript code running on the client responding to the onclick event as well as some code that handles the event on the server if the page posts back as the result of that event.

HTML controls are defined in the System.Web.UI.HtmlControls namespace. As mentioned, most HTML tags have a direct class counterpart in the .NET Framework, but not all do. HTML elements that don't map to a made-to-measure class are rendered through the HtmlGenericControl class and have attributes set using generic collections rather than direct properties. Generic controls include <div>, <iframe>, <span>, <hr>, <font>, and <body>. In general, you should bear in mind that every element that can appear in an HTML page can be marked as runat="server" and programmed and styled on the server.

The HtmlControl Base Class

The HtmlControl class inherits from Control and defines the methods, properties, and events common to all HTML controls. Actually, many properties and all methods and events are simply inherited from the base class. Table 3-4 shows the list of properties specific to HTML controls.

Table 3-4: Specific Properties of an HTML Control

Property

Description

Attributes

Gets a collection object representing all the attributes set on the control with the corresponding value

Disabled

Gets or sets a Boolean value, which indicates whether the HTML control is disabled

Style

Gets a collection object representing all CSS properties applied to the control

TagName

Gets the name of the HTML tag behind the control

A disabled HTML server control is visible and always gets generated as HTML code. If the Disabled property is set to true, the disabled HTML attribute is inserted in the HTML output for the control. As mentioned earlier, if the Visible property is set to false, HTML is not generated for the control.

Working with HTML Attributes

Each HTML control features more properties than those listed in Table 3-4. Properties of HTML server controls map to HTML attributes, and the values assigned to the properties are replicated in the HTML output. For controls that don't have an HTML direct counterpart, the Attributes collection is used to set attributes on the resulting HTML tag. This collection can also be used to set properties not mapped by the control's interface and, if needed, to define custom HTML attributes. Any content of the Attributes collection is managed as a string.

Given the following HTML code snippet, let's see how to programmatically set some attributes on the <body> tag:

<script>
function Init() {
alert("Hello");
}
</script>
<script runat=server language="C#">
void Page_Load(object sender, EventArgs e) {
theBody.Attributes["onload"] = "Init()";
}
</script>
<html>
<body runat="server" id="theBody">
</body>
</html>

You bind a JavaScript script to the onload attribute of the <body> tag. The resulting HTML code that the browser displays is as follows:

<script>
function Init() {
alert("Hello");
}
</script>
<html>
<body id="theBody" οnlοad="Init()">
</body>
</html>

The Attributes property is rendered through a special type of class named AttributeCollection. In spite of the name, the content of the class is not enumerable using the for...each statement because the IEnumerable interface is not supported. The content is instead stored in a StateBag object—the same class used for the ASP.NET view state—which is enumerable. However, the enumerability of the internal data container is exposed to the world. The AttributeCollection class provides ad hoc methods to render attributes of a text writer object and to add and remove elements. Interestingly, if you add an attribute named Style, the class is smart enough to reroute the assigned content to the Style collection.

Hierarchy of HTML Controls

HTML controls can be grouped into two main categories—container and input controls. One control, though, cannot be easily catalogued in either of the two groups—the HtmlImage control, which is the ASP.NET counterpart of the <img> tag. Figure 3-1 shows the tree of HTML controls.


Figure 3-1: A diagram that groups all HTML controls.

Notice that the controls in the figure are not grouped based on discretionary and perhaps arguable rules; instead they are grouped simply by looking at the base class of each control. The HtmlImage control forms a group of its own because it inherits directly from HTMLControl without any other intermediary class.

The input controls category includes all possible variations of the <input> tag, from submit buttons to check boxes and from text fields to radio buttons. The container controls category lists anchors, tables, forms, and in general, all HTML tags that might contain child elements.

HTML Container Controls

The base class for container controls is the HtmlContainerControl class, which descends directly from HtmlControl. The HTML elements addressed by this tag are elements that must have a closing tag—that is, forms, selection boxes, and tables, as well as anchors and text areas. Compared to the HtmlControl class, a container control features a couple of additional string properties—InnerHtml and InnerText.

Both properties manipulate the reading and writing of literal content found between the opening and closing tags of the tag. Note that you cannot get the inner content of a control if the content includes server controls. InnerHtml and InnerText work only in the presence of all literal content. The tag itself is not considered for the output. Unlike InnerText, though, InnerHtml lets you work with HTML rich text and doesn't automatically encode and decode text. In other words, InnerText retrieves and sets the content of the tag as plain text, whereas InnerHtml retrieves and sets the same content but in HTML format.

Table 3-5 lists the HTML container controls defined in ASP.NET 1.1.

Table 3-5: HTML Container Controls

Class

Description

HtmlAnchor

Represents an HTML anchor—specifically, the <a> tag.

HtmlButton

Represents the HTML <button> tag. The <button> element is defined in the HTML 4.0 specification and supported only in Internet Explorer version 4.0 and later.

HtmlForm

Represents the <form> tag, but can be used only as a container of interactive server controls on a Web page. Cannot really be used to create HTML forms programmable on the server.

HtmlGenericControl

Represents an HTML tag for which the .NET Framework does not provide a direct class. Sample tags include <span>, <font>, <div>, <hr>, <link>, and <iframe>. You program these controls using the Attributes collection and set attributes indirectly.

HtmlSelect

Represents the <select> tag—that is, an HTML selection box.

HtmlTable

Represents an HTML table—specifically, the <table> tag.

HtmlTableCell

Represents the <td> HTML tag—that is, a cell in a table.

HtmlTableRow

Represents the <tr> HTML tag—that is, a row in a table.

HtmlTextArea

Represents a multiline text box, and maps the <textarea> HTML tag.

Note that the HtmlButton control is different than HtmlInputButton, which represents the button variation of the <input> tag. We'll say more about buttons in the next section while discussing the Web controls. Server-side forms play a key role in the economy of ASP.NET applications, as they are the means for implementing postbacks and guaranteeing state maintenance. For this reason, the HtmlForm control is not simply a form element you can program on the server. In particular, the HtmlForm hides the Action property and cannot be used to post content to a page different than the content that generated the HTML for the browser. We will cover HTML forms in great detail in Chapter 4.

Navigating to a URL

The HtmlAnchor class is the programmatic way of accessing and configuring the <a> tag. With respect to the other container controls, the HtmlAnchor class provides a few extra properties, such as HRef, Name, Target, and Title. The HRef property sets the target of the hyperlink and can be used to navigate to the specified location. The Name property names a section in the ASP.NET page that can be reached from anywhere on the same page through #-prefixed HRefs. The following code demonstrates a bookmarked anchor named MoreInfo:

<a name="MoreInfo" />

This anchor can be reached using the following hyperlink:

<a href="#MoreInfo">Get More Info</a>

The Target property identifies the target window or the frame where the linked URL will be loaded. Common values for Target are _self, _top, _blank, and _parent, as well as any other name that refers to a page-specific frame. Although the feature is mostly browser dependent, you should always consider these special names as lowercase. Finally, the Title property contains the text that is displayed as a ToolTip when the mouse hovers over the anchor's area.

Handling Events on the Server

In addition to being used for navigating to a different page, the anchor control—as well as the HtmlButton control—can be used to post back the page. Key to this behavior is the ServerClick event, which lets you define the name of the method that will handle, on the server, the event generated when the user clicks the control. The following code demonstrates an anchor in which the click event is handled on both the client and server:

<a runat=server οnclick="Run()" onserverclick="DoSomething">Click</a>

The onclick attribute defines the client-side event handler written using JavaScript; the onserverclick attribute refers to the server-side code that will run after the page posts back. Of course, if both event handlers are specified, the client-side handler executes first before the post back occurs.

The HtmlSelect Control

The HtmlSelect control represents a list of options from which you choose one or more. You control the appearance and behavior of the control by setting the Size and Multiple properties. The Size property specifies the number of rows to be displayed by the control, whereas the Multiple property indicates whether more than one item can be selected in the control. Internal items are grouped in the Items collection, and each element is represented by a ListItem object. Interestingly, the ListItem class is not defined in the HtmlControls namespace but lives instead in the WebControls namespace. To specify the text for each selectable item, you can either set the Text property of the ListItem or simply define a series of <option> tags within the opening and closing tags of the <select> element.

By default, the HtmlSelect control shows up as a drop-down list. However, if multiple selections are allowed or the height is set to more than one row, the control is displayed as a list box. The index of the selected item in a single-selection control is returned through the SelectedIndex property. If the multiple selection is enabled, you just loop through the Items collection and check the Selected property on individual list items.

The HtmlSelect control supports data binding through additional properties. The DataSource property lets you set the data source, which can be any .NET object that implements the ICollection interface. If the data source contains multiple bindable tables (for example, a DataSet object), by using the DataMember property you can choose a particular one. Finally, the DataTextField and DataValueField properties are used to bind the list item's Text and Value properties to columns in the data source.

HTML Tables

In ASP.NET, HTML tables provide a minimum set of functions when rendered using the HtmlTable control. In most cases, you don't need to use server-side tables because you typically rely on richer list and grid controls to do the job of displaying tables or records. So you resort to tables when you need to define a fixed layout for graphical elements of the page, but this is not a feature that requires a server-side table.

However, server-side tables are not as powerful as pure HTML tables—which are created by using the <table> tag. The main limitation is that rich and complex tables are not supported. The HtmlTable class does not support HTML elements such as <caption>, <col>, <colgroup>, <tbody>, <thead>, .and <tfoot> If you use these elements in your ASP.NET code, no run-time exception or compile error is ever thrown. Nevertheless, those elements are silently removed from the HTML code being generated. For example, let's consider the following code:

<table runat="server">
<thead><th>Name</th><th>Last Name</th></thead>
<tr><td>Joe</td><td>Users</td></tr>
<tr><td>Bob</td><td>Whosthisguy</td></tr>
</table>

As you can see in the following code, the HTML output that is generated by the preceding example does not include the <thead> element:

<table>
<tr><td>Joe</td><td>Users</td></tr>
<tr><td>Bob</td><td>Whosthisguy</td></tr>
</table>

By design, an HtmlTable control can have only children of the HtmlTableRow class. Any attempt to programmatically add other table elements, such as a <thead> or a <tfoot>, will generate an exception.

The HtmlTextArea Control

The HtmlTextArea control corresponds to the <textarea> HTML element and allows you to programmatically create and configure a multiline text box. The HtmlTextArea class provides the Rows and Cols properties to control the number of rows and columns of the text box. The Value property can be used to assign some text to display in the control area.

The HtmlTextArea class also provides a ServerChange event that fires during a postback and allows you to validate on the server the data contained in the control. Note that the HtmlTextArea control does not fire the event itself and does not directly cause the page to post back. Rather, when the page posts back in response to a click on a link or submit button, the HtmlTextArea control intervenes in the server-side chain of events and gives the programmer a chance to run some code if the internal content of the control is changed between two successive postbacks.

All ASP.NET controls that, like HtmlTextArea, implement the IPostBackDataHandler interface can invoke user-defined code when the control's internal state changes. In particular, controls can fire custom events by overriding the RaisePostDataChangedEvent method on the aforementioned interface. The following pseudocode shows what happens in the method's implementation of HtmlTextArea:

void System.Web.UI.IPostBackDataHandler.RaisePostDataChangedEvent() {
this.OnServerChange(EventArgs.Empty);
}

Finally, note that the control raises the event only if the state has changed between two successive posts. To determine whether that has happened, the control needs to track the content it had the time before. This value can be stored only in the view state. Of course, the ServerChange won't even fire if you disable the view state for the host page or the control.

HTML Input Controls

In HTML, the <input> element has several variations and can be used to provide a submit button as well as a check box or text box. In ASP.NET, each possible instance of the <input> element is mapped to a specific class. All input classes derive from the HtmlInputControl class. HtmlInputControl is the abstract class that defines the common programming interface for all input controls. The class inherits from HtmlControl and simply adds three custom properties to the inherited interface: Name, Type, and Value.

The Name property returns the name assigned to the control. In ASP.NET, this property is peculiar because, although marked as read/write, it actually works as a read-only property. The get accessor returns the control's UniqueID property, while the set accessor is just void. As a result, whatever value you assign to the property, either programmatically or declaratively, is just ignored and no exception or compile error is ever thrown.

The Type property mirrors the type attribute of the HTML input elements. The property is read-only. Finally, the Value property is read/write and represents the content of the input field.

Table 3-6 lists the HTML input controls defined in ASP.NET 1.1.

Table 3-6: HTML Input Controls

Class

Description

HtmlInputButton

Represents the various flavors of a command button supported by HTML. Feasible values for the Type attribute are button, submit, and reset.

HtmlInputCheckBox

Represents an HTML check box—that is, the <input> tag with a type equal to checkbox.

HtmlInputFile

Represents the file uploader—that is, the <input> tag with a type equal to file.

HtmlInputHidden

Represents a hidden buffer of text data—that is, the <input> tag with a type equal to hidden.

HtmlInputImage

Represents a graphic button—that is, the <input> tag with a type equal to image. Note that this tag is supported by all browsers.

HtmlInputRadioButton

Represents a radio button—that is, the <input> tag with a type equal to radio.

HtmlInputText

Represents a text field—that is, the <input> tag with a type of either password or text.

The hidden and text-input controls are nearly identical, and the contents of both are posted back. They basically differ only in that hidden fields are not displayed and, subsequently, don't provide some UI-related properties such as MaxLength and Size.

Command Buttons

The HtmlInputButton class is the most flexible button class in the .NET Framework. It differs from the HtmlButton class we encountered earlier in that it renders through the <input> tag rather than the Internet Explorer–specific <button> tag. This fact ensures for the control much wider support from browsers.

The HTML input button controls support the ServerClick event, which allows you to set the code to run on the server after the button is clicked. Note that if you set the button type to Button and the ServerClick event handler is specified, the control automatically adds the postback script code to the onclick HTML attribute. In this way, any click causes the page to post back and the code to execute. Let's consider the following ASP.NET code:

<input runat="server" type="button" id="btn" value="Click"
onserverclick="buttonClicked" />

The corresponding HTML code is as follows:

<input language="javascript" οnclick="__doPostBack('btn','')" name="btn"
type="button" value="Click" />

The client-side __doPostBack script function is the standard piece of code generated by ASP.NET to implement the postback. The code is actually emitted through a call to the RegisterPostBackScript method of the Page class. If the button type is set to Submit—that is, a value that would always cause a postback—no client-side script code is generated and the onclick attribute is not set.

Note 

The HtmlInputImage control supports a nearly identical pattern for handling server-side events and validation. The HtmlInputImage control features a few more properties specific to the image it shows. In particular, you can set the alternate text for the image, the border, and the alignment with respect to the rest of the page. The ServerClick event handler has a slightly different form and looks like the following:

void ImageClickEventHandler(object sender,
            ImageClickEventArgs e);

When an image button is clicked, the coordinates of the click are determined by using the X and Y properties of the ImageClickEventArgs data structure.

Controlling Validation

The HtmlInputButton class, as well as the HtmlButton class, support a Boolean property named CausesValidation. The property indicates whether the content of the input fields should be validated when the button is clicked. By default, the property is set to true, meaning the validation always takes place. We'll examine data validation later in the chapter. For now, it suffices to say, you can programmatically enable or disable the validation step by using the CausesValidation property.

Typically, you might want to disable validation if the button that has been clicked doesn't perform a concrete operation but simply clears the user interface or cancels an ongoing operation. By design, in fact, server-side page validation takes place just before the ServerClick event handler is executed. Setting the CausesValidation property to false is the only means you have to prevent an unnecessary validation.

Detecting State Changes of Controls

Earlier in this chapter, while discussing the features of the HtmlTextArea control, we ran into the ServerChange event and described it as the mechanism to detect and validate changes in the control's state between two successive postbacks. The ServerChange event is not an exclusive feature of the HtmlTextArea control but is also supported by other input controls such as HtmlInputCheckBox, HtmlInputRadioButton, HtmlInputHidden, and HtmlInputText. Let's look at an example in which we use the ServerChange event to detect which elements have been checked since last time the control was processed on the server.

We build a page with a list of check boxes and a button to let the user post back to the server when finished. Notice, in fact, that neither the HtmlInputCheckBox control nor any other input control except buttons, post back to the server when clicked. For this reason, you must provide another control on the Web page that supports posting to the server—for example, an HtmlButton or an HtmlInputButton control. The following code implements the page shown in Figure 3-2:


Figure 3-2: The ServerChange event fires only if the status of the control has changed since the last time the control was processed on the server.
<%@ Page Language="C#" %>
<html>
<script runat="server">
public void DetectChange(object sender, EventArgs e) {
HtmlInputCheckBox cb = (HtmlInputCheckBox) sender;
Response.Write("Control <b>" + cb.UniqueID + "</b> changed<br>");
}
</script>
<body>
<form runat="server">
<input runat="server" type="checkbox" id="one"
OnServerChange="DetectChange">One<br>
<input runat="server" type="checkbox" id="two"
OnServerChange="DetectChange">Two<br>
<input runat="server" type="checkbox" id="three"
OnServerChange="DetectChange">Three<br>
<input runat="server" type="submit" value="Submit" />
</form>
</body>
</html>

The ServerChange event is fired only if the state of the control results changed after two postbacks.

By implementing the IPostBackDataHandler interface, each server control takes a chance to update its current state with data posted by the client. The ASP.NET runtime invokes LoadPostData on each control that implements the interface.

public bool LoadPostData(string postDataKey,
NameValueCollection postCollection);

The first argument of LoadPostData is the client ID of the control; the second argument is a name-value collection that contains the posted data. Posted data can either be Request.Form or Request.QueryString depending on the form's method. Each control compares the value posted by an HTML element with the same ID with the contents of a particular property. It is Value for text boxes and Checked for check boxes. The posted value is obtained using the postDataKey string as a key to access the values stored in the collection.

Controls that implement the IPostBackDataHandler interface use a boilerplate piece of code to implement the LoadPostData method. Basically, the method updates the key property of the control with the posted value. The following code shows how LoadPostData works for the HtmlInputText control:

bool LoadPostData(string postDataKey, NameValueCollection postColl) {
string oldValue;
string postedValue;
// At this point, the view state has been restored
oldValue = this.Value;
// Get the posted value for the HTML element with the same
// ID as the control
postedValue = postColl[postDataKey];
// Compare the posted value with Text and updates if needed
if (oldValue != postedValue) {
this.Value = postedValue;
return true;
}
// Return a Boolean value denoting whether the state has changed
return false;
}

LoadPostData returns true if the state of the control changes as a result of the post back—that is, if the user generated a new state for the control. For this infrastructure to work, it is key that the value of the server control's UniqueID property be assigned to the name attribute of the HTML element. Otherwise, the ASP.NET runtime will not be able to handle postback data for that control.

The ASP.NET runtime tracks all the controls that return true to LoadPostData and then invokes the RaisePostDataChangedEvent method for each of them—the second method on the IPostBackDataHandler interface. The following code snippet reports what that method does for the HtmlInputText control:

// System.Web.UI.IPostBackDataHandler
void RaisePostDataChangedEvent() {
this.OnServerChange(EventArgs.Empty);
}

For the HtmlInputCheckBox control in the preceding sample, a change of state occurs whenever the Checked property changes. Note that a nearly identical mechanism exists for Web controls.

Uploading Files

The HtmlInputFile control is the HTML tool for uploading files from a browser to the Web server. Note that file upload requires Internet Explorer version 3.0 or newer. To exploit the HtmlInputFile control in a form, you should first set the server form's Enctype property to multipart/form-data.

<form runat="server" enctype="multipart/form-data">
<input runat="server" type="file" id="upLoader" >
<input runat="server" type="submit" value="Upload..." />
</form>

The way in which the HtmlInputFile control is rendered to HTML is browser- specific, but it normally consists of a text box and a Browse button. The user selects a file from the local machine and then clicks the button to submit the page to the server. When this occurs, the browser uploads the selected file to the server. Prior to ASP.NET, a server-side process—the posting acceptor—was required to run in the background to handle multipart/form-data submissions. In ASP.NET the role of the posting acceptor is no longer necessary as it is carried out by the ASP.NET runtime itself.

On the server, the file is parked into an object of type HttpPostedFile and stays there until explicitly saved to disk. The HttpPostedFile object provides properties and methods to get information on an individual file and to read and save the file. The following code shows how to save a posted file to disk:

upLoader.PostedFile.SaveAs(serverFile);

You can also use the InputStream property of the HttpPostedFile object to read the posted data without creating a disk file. The HtmlInputFile control also allows you to restrict the file types that can be uploaded to the server. You do this by setting the Accept property with a comma-separated list of MIME types.

Caution 

When you use the SaveAs method, you should pay attention to specify the full path to the output file. If a relative path is provided, ASP.NET attempts to place the file in the system directory. This practice might result in an access-denied error. Furthermore, make sure to provide write permission for the account used by ASP.NET for the directory where you want to store the file.

ASP.NET exercises some control on the amount of data being uploaded. The maxRequestLength attribute in the <httpRuntime> section of the configuration file sets the maximum allowable file size. An error is generated in the browser when the file exceeds the specified size—4 MB by default. Uploading large files might also generate another runtime error due to an excessive consumption of system memory. As we've seen in Chapter 2, when more than 60% of the available RAM is consumed the ASP.NET runtime recycles the worker process (aspnet_wp.exe). Of course, this fact breaks the upload process. To avoid this error, you should increase the value of the memoryLimit attribute in the <processModel> element of the configuration file for the application.

The HtmlImage Control

The HtmlImage class is the ASP.NET counterpart of the <img> tag. You can use it to configure on the server the display of an image. Possible parameters you can set are the size of the image, the border, and the alternate text. An instance of the HtmlImage is created only when the runat attribute is added to the <img> tag. If you simply need to display an image within a page, and the image is not dynamically determined or configured, there is no need to resort to the HtmlImage control, which would add unnecessary overhead to the page. The following code snippet shows how to configure a server-side <img> tag called to display an image whose name is determined based on run-time conditions.

theImg.Width = 100;
theImg.Height = 100;
theImg.Src = GetImageUrl(Request);

The HtmlImage control should be used to programmatically manipulate the image to change the source file, the width and height, or the alignment of the image relative to other page elements. The majority of properties of the HtmlImage control are implemented as strings, including Src—the URL of the image—and Align. Feasible values of Align are only a small set of words such as left, right, top, and so forth. These words would have been more appropriately grouped in a custom-enumerated type, thus providing for a strongly typed programming model. If you think so, too, you just grabbed the gist of the difference between HTML and Web server controls! HTML controls just mirror HTML tags; Web controls attempt to provide a more consistent and effective programming interface by exploiting the characteristics of the .NET Framework.







Conclusion

In ASP.NET pages, server controls are vital components. Server-side controls alone—no matter their capabilities and flavors—constitute a huge difference between ASP and ASP.NET. Server-side controls transform the programming model of ASP.NET from a mere factory of HTML strings to a more modern and effective component-based model.

ASP.NET features a long list of control classes. Looking at the namespaces involved, we should conclude that only two families of controls exist—HTML and Web controls. Controls in the former group simply mirror the set of elements in the HTML syntax. Each constituent control has as many properties as there are attributes in the corresponding HTML tag. Names and behavior have been kept as faithful to the originals as possible. The ultimate goal of the designers of HTML controls is to make the transition from ASP to ASP.NET as seamless as possible—just add runat="server" and refresh the page.

The overall design of Web controls is more abstract and much less tied to HTML. In general Web controls do not provide a strict one-to-one correspondence between controls and HTML tags. However, the capabilities of Web and HTML controls overlap. All ASP.NET server controls render in HTML, but Web controls render to more complex HTML representation than HTML controls.

In the family of Web controls, we can identify interesting and powerful subsets of controls—for example, validators, list controls, and iterative controls. Data- bound controls, including list and iterative controls, represent a key enhancement in the ASP.NET programming model. The ability to bind data sources to controls—especially to disconnected and in-memory sources—adds spice to an already powerful model and significantly increases speed and productivity. Just consider the following example. Do you remember the typical check box and radio button code that countless ASP pages implemented? The code walks its way through all the records in a result set and generates a check box or radio button at each step. With this old model, state maintenance is in the care of the programmer, code has to be written over and over again, and extensibility and reusability is a mere dream. In ASP.NET—thanks to server controls—control list generation is as easy as using ad hoc data- bound list controls.

转载于:https://www.cnblogs.com/GavinCome/archive/2007/05/22/754964.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值