IT professionals agree that input is a big source of trouble.

Input ultimately determines how applications work and wrong or malicious input may cause serious damage. It is extremely important that developers have this fact firmly in mind and consequently apply adequate countermeasures. Starting from the perspective that all input is evil is a good approach. Reasoning in terms of a whitelist instead of a blacklist is another excellent strategy. Working with strongly typed data is the third pillar of secure applications. This article discusses the role of input data and related attacks in the context of ASP.NET applications.

In software as in everyday life, any dangerous items require special care and often some special equipment. What’s so treacherous and scary in software that could be labeled as a dangerous item? Code is rarely harmful on its own, because it is (or should be) extensively tested before reaching the production stage. Of course, this doesn’t mean that code is always perfect; more simply, it is normally safe to assume that a lot of effort has been made to ensure that the code works as expected. Even after this statement, can one stay quiet and relaxed and let the software run? Unfortunately, no.

The quality and correctness of a piece of software is double-linked to the quality and correctness of the tests it goes through. In the imperfect world in which we live, code normally works except in some statistically irrelevant number of situations. We all call these situations “bugs.” Should you consider a bug a dangerous item? I’d say no, although a bug can sometimes have a disruptive effect on the application and any infrastructure or machinery it controls. A bug in a function can lead to a serious crash; but would you say that a function call is dangerous per se?

Instead, input data is a treacherous companion item to most software applications. A piece of software may work correctly, except when it receives certain data. Bad data becomes dangerous only if it starts a flow of execution that ends in anomalies and if you cannot detect and properly handle those anomalies.

Every professional involved with software agrees that input data is a potential enemy and should be handled with extreme care.

All Input Is Evil, Eugene

The importance of software security has grown significantly with the rapid success of Web applications. Anybody can connect to a site and practice entering any sort of data. The site should be safe enough to detect and reject any incongruous data. If this doesn’t happen, an otherwise perfect and functioning application starts misbehaving and may eventually cause serious damage.

Over the years, practicing with data on sensitive and alluring Web sites has become a new profession; subsequently, developers had to implant a harsh defense. In general, I assume all input is evil until proven otherwise.

Developers nowadays design most Web applications (and other applications) following this guideline. On this topic, you might want to read about the habits of an authentic guru of security: Michael Howard (see sidebar, “Michael Howard’s Secure Habits”).

However, some developers are led to assume that any incoming data is in the right format, or in a small number of possible wrong formats. Basically those developers tend to assume that data is correct until proven otherwise. I think a complete turnaround is required to clinch security.

OK-What’s Input for a Web Application?

Input data is just any data that users and/or external sources bring inside of an application. The list includes, of course, configuration and helper files, databases (why not?), as well as user interface controls that directly interact with the end user.

Note that the list is even longer (and subtler, to some extent) for Web applications. For a Web application, user input comes from any form fields displayed in the page such as text boxes, check boxes, list boxes, and their combinations. Combinations? Yes. How would you otherwise define custom ASP.NET controls that combine together, say, text boxes and drop-down lists?

In this way is the list complete? No. Consider arguments in the query string. And what about cookies? Cookies are not what some urban legends claim-some sort of executable code that may format your hard drive on the next full moon. Cookies are text files that become legal input for a Web application. For example, a Web application uses cookies to transmit the ID of the current session and the encrypted credentials for an authenticated user of a site. Cookies are a form of input for applications and, as such, you should carefully verify their content before use.

Now consider HTTP headers. HTTP headers are chunks of information that qualify an HTTP request, for example, to tell the browser about the type of resource being downloaded. You can define custom HTTP headers to move custom data, that is, input for the application.

In general, you should carefully monitor and examine any source of information for an application, including data you retrieve from a database query or receive from a Web service, read out of an e-mail message, or get through an FTP connection. You should carefully verify everything before use. But why? What could happen if you fail to check input data?

Last September, MITRE Corp-a company founded to provide engineering and technical services to the U.S. federal government-reported that attackers are now changing their preferences and paying much more attention to application flaws that allow for code injection. MITRE maintains a list of standardized names and descriptions for publicly known IT security vulnerabilities and exposures. (For more information, visit http://cve.mitre.org.) According to their latest statistics, more than 20% of attacks discovered in 2006 fall under the umbrella of cross-site scripting (XSS) and 14% can be classified as SQL injection. About 10% of attacks are due to PHP “includes” and less than 8% to buffer overflows. You can see the full statistics at http://www.attrition.org/pipermail/vim/attachments/20060914/42b97c1d/attachment-0001.obj.

Given these numbers, a couple of considerations spring up quite naturally. The prevalence of XSS and SQL injection attacks indicates clearly and neatly that Web applications are definitely an easy place for attackers. However, with more than 34% of discovered attacks, can you really conclude that one attacker out of every three is planning XSS or SQL injection attacks as you read this? Of course not. Likewise, you can’t determine that one third of Web sites have vulnerabilities.

For an attacker today, it’s easier to find XSS or SQL exploits than overflows and such exploits are easier to find for two reasons. A Web site has more likelihood of being vulnerable (than a desktop application) and its databases may contain sensitive and, therefore, attractive information.

But why is a Web site inherently more at risk than a desktop application? Because the nature of the application-open to any user with an Internet connection-makes it easy to reach and exposed to attacks. And because most Web developers overlook security issues. A managed platform like .NET significantly reduces the attack surface for buffer overflows; the same doesn’t happen for SQL injection and XSS attacks.

In ASP.NET, a first line of defense is built into the framework, but it is not sufficient for you to sleep easy. It still requires that you change your programming habits.

Script Injection

Cross-site scripting (XSS) is an attack that manifests itself when untrusted input is echoed to the HTML page. XSS owes most of its power to the fact that HTML is a markup language. For this reason, in any HTML page some characters are given a special meaning and prepare the ground for special browser behavior. For instance, some characters are inserted to require a particular formatting or command the execution of some script code. The most typical example is the “<” character. There’s nothing wrong with this fact as long the page author consciously inserts any special characters.

What if, instead, an attacker silently and sneakily injects markup characters into a regular page and the user’s browser processes them? What if the user is then directed to view a malicious page just crafted to steal information or execute code on the local machine? This is more or less the typical effect of an XSS attack.

How could a hacker incorporate external text into a page? There’s just one way actually-via input data.

To reliably avoid XSS vulnerabilities, you must HTML encode any text that you display programmatically. In this way, you neutralize any malicious script embedded in user-provided data and display the HTML as plain text instead of letting the browser interpret and execute it.

The drawback is that this approach also leads to ignore any benign HTML formatting that users legally apply. This is not necessarily a problem for most Web applications; however, forums, most portals, and news-driven applications may have the need to host user-provided rich text. Now what?

If your application needs to display user-provided HTML markup, you should use whitelists. A whitelist consists of a list of valid and authorized characters and expressions. Hence, your code will just parse the input and strip off any text that doesn’t appear in the whitelist. Period.

Security specialists generally consider the whitelist approach to be more secure than the opposite blacklist approach. A blacklist designates characters and expressions that you know to be potentially malicious and dangerous. A blacklist may get quickly outdated and, more importantly, beyond your control. In fact, attackers are generally quick to find new ways to encode malicious code to make it appear safe and innocuous.

What could a hacker gain out of an XSS attack? Frequently, they could steal your cookies, including session and authentication cookies. A hacker who happens to hold your authentication cookie may use the application as if they were you. At the very minimum, he or she could change your user settings; depending on the type of the application, they could gain access to your private and likely sensitive stuff. On the average less dangerous, but still quite annoying, is when they steal your session cookie. In this case, the attacker controls your session data. Again, what they could do depends on what the application does with session data.

Due to XSS, an application that relies on cookies to implement some of its features may receive poisoned data that affects the behavior and maybe the user. False advertising is another possible effect of an XSS exploit. But there’s more. XSS can lead to exploit vulnerabilities in Web sites in a sort of anonymous way. The hacker may inject code in an unaware application so that whenever a user performs an innocuous action (i.e., sending a mail or viewing a report) it also triggers a denial-of-service attack against another site. More in general, being a victim of an XSS exploit may mean little to you and your application. XSS holes leave a door opened to uninvited guests to come in and exploit other security bugs that may exist in the application, the browser and, worse yet, the server. Though most of the time the highest costs of XSS holes are represented by damaged reputation.

What can you do as a user to fight XSS? Ideally, you should disable JavaScript and raise your security settings to high. However, a good defense consists also in following links only within the same Web site. Links pointing to external services and Web sites may be dangerous; likewise, clicking links from unknown senders is dangerous, especially when the link is not a plain http://www.somewebsite.com.

What can you do, instead, as a developer? You should never trust any user input and always encode meta-characters such as the notorious < and >, but also round parentheses, the sharp symbol (#) and the ampersand (&). Table 1 lists the safe representation for these HTML meta-characters.

SQL Injection

A SQL injection attack forces an unaware application to execute database code not planned and not intended by the authors. Stated in this way, I bet that most developers would hardly believe it is ever possible. However, it is possible; and the problem has the same origin as XSS attacks-unsanitized and/or unverified user input.

The execution of external SQL commands is possible when commands are built programmatically mixing user input with predefined stubs. Here’s the typical scenario:

string cmd = "SELECT * FROM table WHERE id=";
cmd += Request["id"].ToString();

The preceding code works great as long as correct input is provided through the id query string or form field. If the parameter contains invalid data, quite likely the execution of the command fails and is communicated to the outside world as an HTTP 500 error (internal server error). It may mean little to you and end users; however, it is a sort of invitation for a potential attacker. Worse yet, the code above accepts just any data, including data that results in correct SQL but executes commands not originally intended by the developer.

Sanitizing user input is the primary way to fight and mitigate SQL injections. Here sanitizing means two correlated actions: check the type of data you’re receiving and remove any unnecessary characters to allow only those that are absolutely needed.

Back to the previous code snippet, if the id field refers to an integer column, you should guarantee that an integer value is used to compose the final database command. The most effective way to ensure this is using SQL parameters rather than composing the final command text as a plain string:

string cmd = "SELECT * FROM table WHERE id=@id";
SqlCommand c = new SqlCommand();
c.CommandText = cmd;
c.Parameters.AddWithValue("id", Request["id"]);

In this case, if the id query string parameter doesn’t evaluate to an integer, an exception is thrown and the database command never executes. The ADO.NET layer makes the check for you if you use explicit parameters.

This approach works great for numbers, dates, and Booleans; but it may be insufficient for arrays or strings. For arrays, you need a type-safe way to pass arrays to a SQL command or stored procedure; arrays, in fact, are not a native type for SQL dialects. Here you can find an answer on how to pass parameters to stored procedures: http://www.codeproject.com/useritems/TSQLIntegerArrays.asp. For strings, the problem is: how can you make sure that the content of the string is legal? Filtering undesired characters in a whitelist approach is the only safe way out.

It goes without saying that SQL injection is a cross-database problem that affects more bad programming habits than database servers. Both SQL Server and Oracle databases, and any other database, may suffer from SQL injection attacks through a number of their modules.

As you may guess, the results of an SQL exploit may be much more disruptive than an XSS hack. A SQL hole, in fact, may unveil the database and all of its contents to the attacker.

The end user is in no way responsible for SQL exploits; the responsibility, in this case, belongs entirely to the programmer and database administrator. Good forms of mitigation include input sanitization as well as database configuration. Sanitizing input includes using bound parameters and data clean-up removing undesired characters and escaping quotes. Using stored procedures instead of plain SQL commands is another good move, provided that the stored procedure is written properly (see sidebar, “Are Stored Procedures Safe Against SQL Injection?”). Database configuration entails using a database connection with the least set of rights possible and isolating the host Web server in a demilitarized zone (DMZ), so that even when getting full control of an individual machine an intruder can’t easily proceed further (see sidebar, “Demilitarized Zones”).

A frequent objection to most security considerations around SQL injection is the following: “How can the attacker guess my table scheme and field naming?” Quite correctly, the average developer devoid of strong security skills would wonder how a “blind” attack against an unknown database might ever succeed. How could a hacker armed with a text box crack a whole system?

The text box lets the attacker send arbitrary data down to the server; admittedly, without much hope. But the server’s reply might sound quite encouraging and informative. Arbitrary text in a SQL query will likely fail. What’s the response for the end user then? A response that contains technical information such as the type of the database or table and column names will greatly simplify the attacker’s life. A generic error page won’t stop the attack but will contribute to raise the security bar higher. Pay attention to the error messages displayed to end users in case of internal errors. ASP.NET allows you to hook up the error page mechanism-do that and let technical details show in the view only for local calls from 127.0.0.1. Note though that an attacker can still grab data by sending a sequence of SQL statements built around questions with a True/False answer.

ASP.NET Built-in Barriers

ASP.NET has taken security seriously from the beginning. Do you remember last-minute changes back in 2002 just a few weeks before the official launch of ASP.NET 1.0? Among other things, the ASP.NET worker process runs on the weakest possible account and impersonation is turned off by default.

From a more developer-oriented perspective, it should be noted that with version 1.1 ASP.NET introduced a first line of defense against XSS. Called Input Request Validation (IRV), the feature automatically enables a static filter that matches the contents of input fields against a number of fixed potentially dangerous patterns. You can control the filter programmatically through the ValidateRequest attribute on the @Page directive. The attribute accepts a Boolean value and is set to true by default. If the filter detects that cookies or form fields are carrying potentially unsafe data, it throws an exception and stops the page execution.

Does this mean that a typical ASP.NET application is completely secured from XSS attacks?

Unfortunately, the ValidateRequest attribute-like analogous tools and programming language features-is far from being a silver bullet. It certainly helps but doesn’t solve all security issues with its sole presence; more importantly, it can’t be the sole replacement for an effective validation layer.

As a matter of fact, you have to disable IRV in order to allow formatted input in your pages. You do this as follows:

<%@ Page ValidateRequest="false" %>

When you use this technique, bear in mind that you have to replace that barrier with other, possibly high and resistant barriers.

Also related to the prevention of XSS attacks is the ViewStateUserKey property. Introduced with ASP.NET 1.1, it is a string property defined on the Page class. The default value is the empty string. What’s the purpose of this key?

A variation of XSS is known as the one-click attack. Basically, it consists of the submission of a spoofed form to a Web page. It is assumed that the attacker knows a lot about the page and application and can make reasonable guesses about how each posted field is used. This information can be part of the attacker’s background (i.e., a former employee) or it might have been obtained from messages in error pages, observing ongoing HTTP packets, and so on. In addition, the attacker might need a (stolen) authentication cookie so that his malicious request can be recognized and processed by the ASP.NET HTTP pipeline.

At this point, all that he has to do is prepare a local HTML page, set the action URL to the target site, and populate the form’s fields. Hey, wait a moment. ASP.NET pages have the viewstate, don’t they? The fact is, a viewstate that is valid at time 0 is still valid at time 1. Sure, the contents may be different at different times, but still the ASP.NET runtime is capable of decoding it correctly. To make it simple, the same viewstate that is downloaded when you connect anonymously to the page you plan to attack is good enough to use for the attack. Unless, the viewstate is bound to a hard-to-repeat key. Take a look at the following code snippet:

void Page_Init(object sender, EventArgs e)
{
    if (User.Identity.IsAuthenticated)
        ViewStateUserKey = User.Identity.Name;
}

In this way, you tell the ASP.NET runtime to add the specified key-for example, the user name-to the hash that protects the viewstate against tampering. What’s the net effect?

If the spoofed request doesn’t have a matching authentication cookie attached, the viewstate can’t be decoded and an exception is thrown. In other words, the ViewStateUserKey property binds the viewstate to a particular user. In this way, the attack is successful only if the attacker can impersonate the exact user that the encoded viewstate refers to. In a one-click attack scenario, this is all but unlikely. The one-click attack, in fact, does use some social engineering techniques to steal information to plan the attack. Once again, the moral of the story is that the ViewStateUserKey property, like other security techniques, can only raise the bar higher. As mentioned, the ViewStateUserKey property is set to an empty string-which means that the feature is turned off. You obtain a real benefit out of it only if you set the property to a user-specific value, such as the user name. Setting ViewStateUserKey to a constant string will make the decoding of the viewstate more complex from a performance perspective without adding protection.

ASP.NET 2.0 introduces yet another built-in barrier to fight back XSS attacks-event validation. When turned on, event validation saves to an encoded hidden field all known good values it can receive from posted fields. If among posted values any incompatibilities are detected, a security exception is thrown (Figure 1).

Figure 1: Event validation exception.

More precisely, event validation is a feature that ASP.NET server controls and the host page implement together. During the loading stage, for each input control that declares to support event validation, the page checks if the posted value is any of the values stored in the event validation hidden field. Suppose that a drop-down list at rendering time contains strings like “High” and “Medium”. On the client, the end user is expected to make a selection from the list of provided values. A user that posts back through the displayed page from the browser can only select “High” or “Medium”. But what if an attacker prepares a tailor-made form where it passes “Low” through the drop-down list? If “Low” is a value that the code behind the page understands, the attack is successful. With event validation turned on, each control is asked to render the list of allowed values to a hidden field. When back from the client, the page infrastructure matches the input value against the list of allowed values and throws an exception in case of unknown values.

Event validation is enabled by default and can be disabled on a page or application basis. For example, here’s how to disable it on a particular ASP.NET page:

<%@ Page EnableEventValidation="false" %>

You use the <pages> section in the configuration file to disable validation for all pages in the application. Event validation works only for server controls that explicitly declare to support it. Control developers turn event validation on through the SupportEventValidation attribute. Most built-in server controls support event validation. When you create a custom control, you have to explicitly enable the attribute, because the attribute is not inheritable:

[SupportsEventValidation]
public class MyDropDownList: DropDownList
{
    :
}

Each control implements event validation differently. In fact, text box validation doesn’t do much because the control is designed to accept any data the user types. A drop-down list, instead, ensures that only listed values are posted.

Event validation raises another level of protection around posted data by preventing unknown data to be posted. A side effect of event validation is that dynamically created controls may not be allowed to post back or options dynamically and legitimately added to a drop-down list may raise an exception. There’s no workaround for this issue, other than disabling the feature altogether. ASP.NET AJAX controls, in fact, run with event validation disabled.

Finally, it is worth noting that event validation can’t be programmatically disabled for individual controls. The feature applies to all controls in a page, all pages in an application, or even all classes of a certain type used in pages or applications.

Validating Input Data

Most ASP.NET pages are made of controls. More often than not, pages are built just dropping controls onto the Visual Studio 2005 designer without much additional work of configuration. So what kind of stuff should you be adding then? The quick answer is: anything that can limit the user’s freedom in typing fuzzy characters. For example, a text box control should have a maximum length and, more importantly, this parameter must be checked before using the typed text.

Likewise, if a text box has to return data of a given known type (number, date), you should ensure that valid and legitimate data comes out of the text box in all cases.

Strings representing special data such as an e-mail address, a Social Security number (SSN), a phone number, and strings must be parsed and verified before use. In all cases, potentially dangerous and unnecessary characters should be stripped off. Always.

If you have to be serious about security (let’s say it-not all applications need the same level of security), you should be harsh and define strict rules even at the cost of annoying users. For example, a valid and significant e-mail address can be written with only letters, digits, and a few punctuation marks. Why enable users to type more than just this?

Event and request validation, viewstate protection barriers, and validation controls are all framework tools that form a first line of defense against possible attacks. You should never rely on them alone. If it helps you, write your code as if they were not there. I don’t usually suggest disabling built-in features, but if you’re going to take security seriously and replace them with your own layer, it may be acceptable.

Whatever set of automatic barriers you use, it’s you and only you who is ultimately responsible for the data your code parses and processes. A back-end validation layer is an absolute necessity. You typically place it on top of the business layer where you prepare your entities with input data and safe default values.

ASP.NET Validation Controls

ASP.NET provides a fair number of validation controls to help you check input data before data is posted and processed on the server. Validation controls provide an easy-to-use mechanism to perform a variety of validation tasks, including testing for valid types, values within a given range, or required fields. Each validation control references an input control located somewhere in the ASP.NET page.

A validator may have a client- and server-side engine to process input data. When the page is ready for submission, the current contents of the monitored control is passed to the validator for further processing. If the validator has a client-side engine, the post won’t happen until the validator says it’s all right. If there’s no client-side engine active, the page posts back but no postback event is ever fired if the input doesn’t match expectations.

Each validator performs a different type of verification. Table 2 shows the types of validation controls supported by ASP.NET 2.0.

You can apply multiple validation controls to an input control in order to validate it according to a variety of different criteria. For example, you can apply two validators to a text box to make sure that the user doesn’t leave it empty and that its content matches, for example, the typical format of a Social Security number. In this case, you use a RequiredFieldValidator combined with a RegularExpressionValidator.

All validators inherit from a common base class-BaseValidator-which in turn inherits from Label. Table 3 lists the properties shared by all validator controls. Listing 1 shows some validators in action in a sample page.

All validators inject some script code in the client page if client script support is enabled for the validator-EnableClientScript property. The code prevents the page from posting in case any of the conditions are not met. It is essential to know that client-side validation is never enough. Any serious application should not presume to receive valid and verified data if it only relies on client-side validation. Why is it so? Because attackers could view the page with a browser with JavaScript disabled and elegantly bypass any security checks you implemented on the client. For this reason, having JavaScript validation is fine and recommended as long as it only represents a way to save a few server postbacks if manifestly wrong data has been typed or selected. No application should feel secure unless it has validated its data on the server. Hence, a validation layer is a must to work with safe and clean data; validation controls help significantly to build a nice and user-friendly interface around your input forms.

In Table 3 you see two similar looking properties-ErrorMessage and Text. What’s the purpose of each?

The ErrorMessage property sets the official message that each validation control displays in case it detects an error. If the Text property is also set, it would take precedence over ErrorMessage. However, the goal of Text is slightly different.

The Text property is designed to display an inline message exactly where the validator is located. Instead, the ErrorMessage property is designed to display in the validation summary. What’s the validation summary then?

The ValidationSummary control is a label that displays a summary of all validation errors occurring on a Web page. The summary collects error messages from all validators in the page and displays them according to the selected display mode: list, bulleted list, or plain text. Whatever the format is, the summary can be displayed as text in the page or in a pop-up message box. Note that the output of the ValidationSummary control is not displayed until the page posts back. Here’s an example:

<asp:ValidationSummary ID="ValidationSummary1"
   runat="server"
   ShowMessageBox="true"
   ShowSummary="true"
   HeaderText="The following errors occurred:"
   DisplayMode="BulletList" />

It should be noted that error messages are displayed as HTML, so they can contain any HTML formatting attribute.

By default, validation occurs in an all-or-nothing kind of way. This means, for example, that if you have two groups of input fields and two submit buttons, clicking either button will always validate all controls in both groups. You have to explicitly define custom validation groups if you want to validate some controls when one button is clicked and some others when the other button is clicked. You use the ValidationGroup property to define custom validation groups. Here’s an example:

<asp:TextBox runat="server" id="TextBox3" />
<asp:RequiredFieldValidator
    ID="RequiredFieldValidator3" runat="server"
    ValidationGroup="Group1"
    ControlToValidate="TextBox1"
    ErrorMessage="TextBox1 is mandatory" />
<asp:TextBox runat="server" id="TextBox4" />
<asp:RequiredFieldValidator
    ID="RequiredFieldValidator4" runat="server"
    ValidationGroup="Group2"
    ControlToValidate="TextBox2"
    ErrorMessage="TextBox2 is mandatory" />
<asp:Button ID="Button1" runat="server"
    Text="Check Group1"
    ValidationGroup="Group1" />
<asp:Button ID="Button2" runat="server"
    Text="Check Group2"
    ValidationGroup="Group2" />

In the code snippet, you find two validators each belonging to a distinct group: Group1 and Group2. The code snippet also contains two buttons each with the ValidationGroup property set. Guess what happens?

Quite simply, a button click validates all and only the controls belonging to the same validation group. In this way, you can make the validation process as granular as needed. Note that validation groups are not a supported feature in ASP.NET 1.x.

What About ASP.NET AJAX?

To make sure that input is always of the expected type, validators are definitely helpful, but they should not be the only tool you use. By design, a validator just “validates” a value meaning that it returns a Boolean answer to indicate whether the value is coherent with the rules set. An error message appears in the page to explain what is wrong. In a fair number of cases, you could make checks on the client without refreshing the page. As mentioned, though, client-side validation represents a potential risk because an attacker might be able to try the page with JavaScript disabled, thus bypassing all controls. To be effective, validation must be done on the server and optionally on the client.

To validate on the server, though, you need to post back the page. Refreshing real-world pages may be problematic from a user perspective due to possible flickering and latency. ASP.NET AJAX and out-of-band, lightweight postbacks may offer the best of both worlds-server-side validation and easy postbacks.

The simplest way to add AJAX capabilities to validators is wrapping the form in an UpdatePanel control. For example, the fragment of a page in Listing 1 needs only the following changes to be AJAX-ified:

<asp:ScriptManager runat="server"
     ID="ScriptManager1" />
<asp:UpdatePanel runat="server"
     ID="UpdatePanel1">
   <ContentTemplate>
      <table>
           :
      </table>
   </ContentTemplate>
</asp:UpdatePanel>

The UpdatePanel control is installed as part of the ASP.NET AJAX Extensions framework. It wraps any block of traditional ASP.NET 2.0 markup and makes sure that any postbacks that originates from that markup are handled out-of-band and without fully refreshing the page. Only the wrapped markup is refreshed over the postback-everything else in the page is left intact. From where does the postback originate?

UpdatePanel intercepts any classic postbacks that originate from any of the contained controls or from controls designated as triggers. To illustrate, consider the link button that submits the contents of the form in Listing 1. You can choose to put it inside or outside the updatable panel. If included in the panel, each click on the button is captured and served with an AJAX-style postback. If not included, a click on the button originates a traditional postback with a full page refresh. However, you can either declaratively or programmatically choose to define the button as a trigger for the updatable panel. In this case, whenever a user clicks the button the panel is updated, even if the button is placed outside the panel:

<asp:ScriptManager runat="server"
     ID="ScriptManager1" />
<asp:UpdatePanel runat="server" ID="UpdatePanel1">
   <ContentTemplate>
      <table>
           :
      <table>
   </ContentTemplate>
   <Triggers>
      <asp:AsyncPostBackTrigger
           ControlID="LinkButton1"
           EventName="Click" />
   </Triggers>
</asp:UpdatePanel>

Wrapped up in this way, a page can perform server-side validation without fully refreshing the page, which results in a significantly better user experience. Also, in this way the observable behavior of the page is the same whether you enable client validation or not.

Summary

Input data is a serious thing for all applications and for Web applications in particular. Most of the issues are solved if you could ensure that data you receive is strongly typed and its contents verified on a character basis. On the Web, most of the input arrives as a plain string. Mapping the string to the right type and stripping off undesired characters is up to you. ASP.NET validators do help, but they provide mostly a first barrier against patently wrong data. More is needed and designed in the perspective of the application. For this reason, a validation layer that serves the business logic layer strongly typed (and clean) data is essential for any serious application.

The theme of validating input data is cross-platform and cross-version. However, the advent of ASP.NET AJAX helps in making the user interface a bit more responsive and prompt to signal any incongruous data to the end user. Aside from this, all input is evil. It’s up to you-the developer-to demonstrate the opposite.