Request/Response Programming
The server control architecture is built on top of a more fundamental processing architecture, which may be called request/response. Understanding request/response is important to solidify our overall grasp of ASP.NET. Also, in certain programming situations request/response is the natural approach.
HttpRequest Class
The System.Web namespace contains a useful class HttpRequest that can be used to read the various HTTP values sent by a client during a Web request. These HTTP values would be used by a classical CGI program in acting upon a Web request, and they are the foundation upon which higher level processing is built. Table 141 shows some of the public instance properties of HttpRequest. If you are familiar with HTTP, the meaning of these various properties should be largely self-explanatory. Refer to the .NET Framework documentation of the HttpRequest class for full details about these and other properties.
TABLE 141 Public Instance Properties of HttpRequest
Property |
Meaning |
AcceptTypes |
String array of client-supported MIME accept types |
Browser |
Information about client's browser capabilities |
ContentLength |
Length in bytes of content sent by the client |
Cookies |
Collection of cookies sent by the client |
Form |
Collection of form variables |
Headers |
Collection of HTTP headers |
HttpMethod |
HTTP transfer method used by client (e.g., GET or POST) |
Params |
Combined collection of QueryString, Form, ServerVariables, andCookies items |
Path |
Virtual request of the current path |
QueryString |
Collection of HTTP query string variables |
ServerVariables |
Collection of Web server variables |
The Request property of the Page class returns a HttpRequest object. You may then extract whatever information you need, using the properties of HttpRequest. For example, the following code determines the length in bytes of content sent by the client and writes that information to the Response object.
Dim length As Integer = Request.ContentLength Response.Write("ContentLength = " & length & "<br>")
COLLECTIONS
A number of useful collections are exposed as properties of HttpRequest. The collections are of type NamedValueCollection (in System.Collec-tions.Specialized namespace). You can access a value from a string key. For example, the following code extracts values for the QUERY_STRING and HTTP_USER_AGENT server variables using the ServerVariables collection.
Dim strQuery As String = _ Request.ServerVariables("QUERY_STRING") Dim strAgent as String = _ Request.ServerVariables("HTTP_USER_AGENT")
Server variables such as these are at the heart of classical Common Gateway Interface (CGI) Web server programming. The Web server passes information to a CGI script or program by using environment variables. ASP.NET makes this low-level information available to you, in case you need it.
A common task is to extract information from controls on forms. In HTML, controls are identified by a name attribute, which can be used by the server to determine the corresponding value. The way in which form data is passed to the server depends on whether the form uses the HTTP GET method or the POST method.
With GET, the form data is encoded as part of the query string. The QueryString collection can then be used to retrieve the values. With POST, the form data is passed as content after the HTTP header. The Forms collection can then be used to extract the control values. You could use the value of the REQUEST_METHOD server variable (GET or POST) to determine which collection to use (the QueryString collection in the case of GET and the Forms collection in case of POST).
With ASP.NET you don't have to worry about which HTTP method was used in the request. ASP.NET provides a Params collection, which is a combination (union in the mathematical sense) of the ServerVariables, Que-ryString, Forms, and Cookies collections.
EXAMPLE PROGRAM
We illustrate all these ideas with a simple page Squares.aspx that displays a column of squares.
<!-- Squares.aspx --> <%@ Page Language="VB" Trace="true"%> <script runat="server"> Sub Page_Init(sender As Object, e As EventArgs) Dim strQuery As String = _ Request.ServerVariables("QUERY_STRING") Response.Write("QUERY_STRING = " & strQuery & "<br>") Dim strAgent as String = _ Request.ServerVariables("HTTP_USER_AGENT") Response.Write("HTTP_USER_AGENT = " & strAgent & "<br>") Dim length As Integer = Request.ContentLength Response.Write("ContentLength = " & length & "<br>") Dim strCount As String = Request.Params("txtCount") Dim count As Integer = Convert.ToInt32(strCount) Dim i As Integer For i = 1 To count Response.Write(i*i) Response.Write("<br>") Next End Sub </script>
How many squares to display is determined by a number submitted on a form. The page GetSquares.aspx submits the request using GET, and PostSquares.aspx submits the request using POST. These two pages have the same user interface, illustrated in Figure 1411.
Figure 14-11 Form for requesting a column of squares.
Here is the HTML for GetSquares.aspx. Notice that we are using straight HTML. Except for the Page directive, which turns tracing on, no features of ASP.NET are used.
<!-- GetSquares.aspx --> <%@ Page Trace = "true" %> <html> <head> </head> <body> <P>This program will print a column of squares</P> <formmethod="get" action = Squares.aspx
> How many: <INPUT type=text size=2 value=5name=txtCount
> <P></P> <INPUT type=submit value=Squaresname=cmdSquares
> </form> </body> </html>
The form tag has attributes specifying the method (GET or POST) and the action (target page). The controls have a name attribute, which will be used by server code to retrieve the value.
Run GetSquares.aspx and click Squares. You will see some HTTP information displayed, followed by the column of squares. Tracing is turned on, so details about the request are displayed by ASP.NET. Figure 1412 illustrates the output from this GET request.
Figure 14-12 Output from a GET request.
You can see that form data is encoded in the query string, and the content length is 0. If you scroll down on the trace output, you will see much information. For example, the QueryString collection is shown.
Now run PostSquares.aspx and click Squares. Again you will then see some HTTP information displayed, followed by the column of squares. Tracing is turned on, so details about the request are displayed by ASP.NET. Figure 1413 illustrates the output from this POST request.
Figure 14-13 Output from a POST request.
You can see that now the query string is empty, and the content length is 29. The form data is passed as part of the content, following the HTTP header information. If you scroll down on the trace output, you will see that now there is a Form collection, which is used by ASP.NET to provide access to the form data in the case of a POST method.
By comparing the output of these two examples, you can clearly see the difference between GET and POST, and you can also see the data structures used by ASP.NET to make it easy for you to extract data from HTTP requests.
HttpResponse Class
The HttpResponse class encapsulates HTTP response information that is built as part of an ASP.NET operation. The Framework uses this class when it is creating a response that includes writing server controls back to the client. Your own server code may also use the Write method of the Response object to write data to the output stream that will be sent to the client. We have already seen many illustrations of Response.Write.
REDIRECT
The HttpResponse class has a useful method, Redirect, that enables server code to redirect an HTTP request to a different URL. A simple redirection without passing any data is trivialyou need only call the Redirect method and pass the URL. An example of such usage would be a reorganization of a
Web site, where a certain page is no longer valid and the content has been moved to a new location. You can keep the old page live by simply redirecting traffic to the new location.
It should be noted that redirection always involves an HTTP GET request, like following a simple link to a URL. (POST arises as an option when submitting form data, where the action can be specified as GET or POST.) A more interesting case involves passing data to the new page. One way to pass data is to encode it in the query string. You must preserve standard HTTP conventions for the encoding of the query string. The class HttpUtility provides a method UrlEncode, which will properly encode an individual item of a query string. You must yourself provide code to separate the URL from the query string with a "?" and to separate items of the query string with "&".
The folder Hotel provides an example of a simple Web application that illustrates this method of passing data in redirection. The file default.aspx provides a form for collecting information to be used in making a hotel reservation. The reservation itself is made on the page Reservation1.aspx. You may access the starting default.aspx page through the URL
http://localhost/Chap14/Hotel/
As usual, we provide a link to this page in our home page of example programs. Figure 1414 illustrates the starting page of our simple hotel reservation example.
Figure 14-14 Starting page for making a hotel reservation.
Here is the script code that is executed when the Make Reservation button is clicked.
e As EventArgs) Dim query As String = "City=" & _ HttpUtility.UrlEncode(txtCity.Text) query += "&Hotel=" & _ HttpUtility.UrlEncode(txtHotel.Text) query += "&Date=" & _ HttpUtility.UrlEncode(txtDate.Text) query += "&NumberDays=" & _ HttpUtility.UrlEncode(txtNumberDays.Text) Response.Redirect("Reservation1.aspx?" + query) End Sub
We build a query string, which gets appended to the Reservation1.aspx URL, separated by a "?". Note the ampersand that is used as a separator of items in the query string. We use the HttpUtility.UrlEncode method to encode the individual items. Special encoding is required for the slashes in the date and for the space in the name San Jose. Clicking the button brings up the reservation page. You can see the query string in the address window of the browser. Figure 1415 illustrates the output shown by the browser.
Figure 14-15 Browser output from making a hotel reservation
Our program does not actually make the reservation; it simply prints out the parameters passed to it.
<%@ Page language="VB" Debug="true" Trace="false" %> <script runat="server"> Sub Page_Load(sender As Object, e As EventArgs) Response.Write("Making reservation for ...") Response.Write("<br>") Dim city As String = Request.Params("City") Response.Write("City = " & city) Response.Write("<br>") Dim hotel As String = Request.Params("Hotel") Response.Write("Hotel = " & hotel) Response.Write("<br>") Dim strDate As String = Request.Params("Date") Response.Write("Date = " & strDate) Response.Write("<br>") Dim strDays As String = Request.Params("NumberDays") Response.Write("NumberDays = " & strDays) Response.Write("<br>") End Sub </script> <HTML> <body> </body> </HTML>
You can turn on tracing (in the file Reservation1.aspx), and the trace output should serve to reinforce the ideas we have been discussing about request/response Web programming. In particular, you should examine the QueryString collection, as illustrated in Figure 1416.
Figure 14-16 The query string is used for passing parameters in redirection