ASP.NET VERSIONS: 2.0
More on Cross-page Postbacks
Create Page-to-Page logical links in ASP.NET
By Dino Esposito
One of the signs that proves beyond any reasonable doubt the success of a magazine column or a breakout session is when readers and attendees ask you about the topic you re going to cover next. Last month I covered cross-page postings from within ASP.NET 2.0 pages (see Cross-page Postbacks). A few weeks later, while I was looking around for a good follow-up topic, I got an e-mail from an asp.netPRO reader. I doubt the reader had a chance to read last month s column, but his set of questions brought me back to cross-page postings from within ASP.NET 2.0 pages. I realized that in my September column I limited coverage to the fundamentals of cross-page postbacks and missed an opportunity to offer a real-world perspective of the feature, as well as some interesting internals.
I ll try to make up for it this month. In this column, along with my apologies for the omissions (ever heard about space constraints?), you ll find more about the internal implementation of page validation when cross-page postings are used, as well as a discussion of some real-world scenarios where cross-page postings compete with HTML forms and Web services to create page-to-page logical links in ASP.NET applications.
I asked a rhetorical question in my last column: What happens if the caller page contains validators? Think of the following scenario. The current page contains a button that links to another page through the cross-page postback mechanism. At the same time, the current page contains some input fields controlled by a handful of validator controls. Functionally speaking, you expect that current page to remain up if any of the input fields contain invalid data. How would you validate the contents of the input fields? Can you do that entirely on the client or is a trip to the server required to ascertain the validity of the input data?
How do regular postback pages deal with this factor? If client-side validation is disabled, or if a server-side validator is employed, the page posts back as usual and the burden of checking the validity of the input is moved to the server. Code-beside methods and event handlers will check the IsValid property of the page class, which in turn causes all the registered validators to be evaluated. The IsValid property returns true only if all validators are committed to the new request. Checking the value of the IsValid property is ultimately left to the page author and is a behavior that must be explicitly coded.
It would be reasonable that the same pattern be applied also to cross-page postbacks. On the other hand, there s no difference between regular postback pages and cross-page postback pages except for the target page to serve the request. With this pattern applied to pages that use cross-page postings, the transition to the target page occurs anyway, regardless of the results of the validation process. It s then up to the target page to ensure that the input coming from the caller is entirely valid and safe to use. Figure 1 shows some sample code that illustrates how a target page can verify whether the input it receives is entirely valid.
protected void Page_Load(object sender, EventArgs e)
if (PreviousPage == null)
Response.Write("Sorry, you can only invoke me
through cross-page posting.");
Response.Write("Sorry, the original page
contains invalid input.");
Figure 1: Validating the input from within a target page.
All you have to do is check the IsValid property on the PreviousPage object. Needless to say, in the target page you can check not only the overall status (IsValid) but also the status of individual validators.
It is essential to remark again that the check occurs on the target page when the original page is lost. What if the input contains invalid data? How would you let users know about that? The approach shown in Figure 1 is oversimplified and not adequate to a real-world application. In Figure 1, the code simply ends the request and displays an error message. Users will receive a blank page with a message; not exactly a friendly approach, is it?
Ideally, you should return users to the original page and display any error message in the originally requesting page. On the other hand, if the error is with the input data, it makes sense that you display error messages near the related input fields. Actually, there s not much you can do to return to the original page if you re not using a redirect and some custom trick to pass back error messages (session state or some error message ID over the query string).
A Better Approach to Cross-page Validation
By design, server-side validation has to post back, give code-beside methods a chance to validate, then arrange a proper user interface for the page. This is not that bad as long as it happens in the context of the same page as it is for regular postback pages. But when the postback moves users to another page, redirection is the only chance to return users to the original page. An alternative approach consists of using an out-of-band call to validate input data on the server.
While we wait for ASP.NET Atlas to provide a well-done validation framework, let s review some of the routes you can take today to post to different pages while validating input data on the server. As a first option, you can place a Validate button in the page and bind it to an ASP.NET callback method. An out-of-band call occurs while the page remains up, and the server method receives a package with current values and control details and proceeds with the validation. Next, the server method prepares a boolean response for the client page. Based on that, the page decides what to do; for example, showing the user an error message. This description deliberately skips details that developers might want to code in different ways. The format of the data to be sent and received is up to the developer. Likewise, you can decide to validate all input controls in the page and just one particular control. You can decide to return a simple boolean value (valid or invalid) or a more articulated response that includes the error message to show to the user. An example of this technique is illustrated in an article I wrote for MSDN Magazine; see http://msdn.microsoft.com/msdnmag/issues/05/01/CuttingEdge.
true, "", "targetpage.aspx", false,
false))" id="Button1" />
Out-of-band calls, though, suggest other approaches to connect an ASP.NET page to another page in the same application, which is one of the possible goals of cross-page postbacks.
Using HTML Forms
Cross-page postbacks mainly serve the purpose of having a page at work based on the input captured by another page. This mechanism has been at the core of HTML since the beginning, and finds its most natural implementation in HTML forms. The fact is, multiple server forms are not supported in ASP.NET, but classic HTML forms are well accepted. The code in Figure 2 works just fine. What s so special about it?
<%@ Page Language="C#" AutoEventWireup="true"
CodeFile="HtmlForms.aspx.cs" Inherits="HtmlForms" %>
Figure 2: Mixing an ASP.NET server form and an HTML form.
The code mixes a single ASP.NET server form with a classic HTML form. The good news is that, in this way, you can post input data to another page (search.aspx) without resorting to cross-page postbacks (see Figure 3). What s the deal?
Figure 3: Using HTML Forms in an ASP.NET page.
In the first place, the action page doesn t receive any viewstate, which is good news and bad news. It s good because it makes for faster processing; it s bad because it forces you to retrieve code in the action page using the Form collection instead of direct page controls. Here s how the search page in Figure 3 retrieves the posted keyword:
string textToSearch = Request.Form["Keyword"].ToString();
Server validation still occurs on the target page except that you can t rely on the IsValid property because of the lack of viewstate. HTML forms are helpful when you need to post data to a classic ASP page or when you don t need validation and have simple data to pass to the target page.
HTML forms require a roundtrip and switch the page. This approach is viable if you want the target page to take care of the rendering and become the new page displayed to the user. The richness of most of today s browsers, though, opens up a new opportunity.
Using AJAX-enabled Functions
In situations in which you don t want to leave the current page but want to execute code outside the current page, you can better create a (Web) service. The code is encapsulated in a known interface and deployed to any machine in the network. You can invoke this service from within the page, pass parameters, receive a response, and then incorporate the response in the current page.
Implementing out-of-band calls manually is still possible simply check out the documentation for the XmlHttpRequest object for Internet Explorer and Mozilla. However, using an AJAX-enabled framework is largely preferable because the framework will shield you from a lot of details and often provide additional features and capabilities. Using AJAX frameworks, however, is another article which we ll save for another time.
The sample code referenced in this article is available for download.
Dino Esposito is a Solid Quality Learning mentor and the author of Programming Microsoft ASP.NET 2.0 Core Reference and Programming Microsoft ASP.NET 2.0 Applications-Advanced Topics, both from Microsoft Press. Based in Italy, Dino is a frequent speaker at industry events worldwide. Join the blog at http://weblogs.asp.net/despos.