[ Team LiB ] |
16.3 Collections ReferenceThe Request object in ASP.NET supports seven collections, four of which were supported in ASP (Cookies, Forms, QueryString, and ServerVariables), and three of which are new (Files, Headers, and Params). The collections of the Request class support the following common set of properties:
In addition, each collection class exposes the following methods:
With the exception of the Cookies collection, the code used to access keys and values in the collections the Request class exposes is nearly identical in every case. This similarity makes it simple to create your own reusable classes or methods for manipulating the values from these collections, regardless of which collection you are working with.
The Cookies collection returns an instance of the HttpCookieCollection class containing all cookies sent as a part of the current request. The HttpCookieCollection class contains an instance of the HttpCookie class for each cookie passed as part of the client request. The properties of these HttpCookie instances can be used to access information about the cookie(s). As in classic ASP, the Cookies collection is still implemented as a collection (in fact, the HttpCookieCollection inherits from the .NET NameObjectCollectionBase class), but rather than a collection of string keys and string values, the ASP.NET implementation is a collection of string keys and objects (instances of the HttpCookie class). Individual cookies are retrieved into variables of type HttpCookie, providing access to the cookies' values through class properties. Dictionary-style cookies (cookies with more than one value) are accessible through the Values property of the HttpCookie class, which returns a NameValueCollection containing the cookie subkeys and values. You can also retrieve individual values by their key with the following syntax: HttpCookie.Values("keyname") Parameter
ExampleThe example retrieves the collection of cookies from the Cookies property and writes out the key and value of each, along with any subkeys of dictionary cookies: Sub Page_Load( ) Dim Counter1, Counter2 As Integer Dim Keys( ), SubKeys( ) As String Dim CookieColl As HttpCookieCollection Dim Cookie As HttpCookie ' Get Cookie collection CookieColl = Request.Cookies ' Get Cookie keys Keys = CookieColl.AllKeys ' Get cookies by index For Counter1 = 0 To Keys.GetUpperBound(0) Cookie = CookieColl(Keys(Counter1)) Message.Text = "Cookie: " & Cookie.Name & "<br/>" Message.Text &= "Expires: " & Cookie.Expires & "<br/>" ' Get keys for dictionary cookie into an array SubKeys = Cookie.Values.AllKeys ' Write dictionary cookie values to the browser For Counter2 = 0 To SubKeys.GetUpperBound(0) Message.Text &= "Key " & CStr(Counter2) + ": " & _ SubKeys(Counter2) & "<br/>" Message.Text &= "Value " & CStr(Counter2) + ": " & _ Cookie.Values(Counter2) & "<br/>" Next Counter2 Message.Text &= "<br/>" Next Counter1 End Sub NotesThe ASP implementation of the Cookies collection and the HttpCookieCollection class returned by the Cookies property expose a common set of properties; these properties are described in Section 16.3. While it is still possible in ASP.NET to retrieve an individual cookie by its text key as well as its numerical index, the differences in the operation make wholesale migration of ASP cookie-handling code to ASP.NET impractical without significant changes. For example, the following code will raise exceptions: For Each strKey In Request.Cookies Response.Write strKey & " = " & Request.Cookies(strKey) & _ "<br/>" If Request.Cookies(strKey).HasKeys Then For Each strSubKey In Request.Cookies(strKey) Response.Write "->" & strKey & "(" & strSubKey & _ ") = " & Request.Cookies(strKey)(strSubKey) & "<br/>" Next End If Next Apart from the fact that this code does not explicitly declare its variables or their types (both of which are required by default in ASP.NET), the previous code fails because the Request.Cookies(key) property returns an instance of HttpCookie, rather than a string, and the HttpCookie instance cannot be implicitly converted to a string for the Response.Write statement, which expects a string. Additionally, the call to Request.Cookies(key) does not get the subkeys for a dictionary cookie. Fortunately, the modifications necessary to make the previous code work are fairly simple and are shown here: For Each strKey In Request.Cookies Message.Text = strKey & " = " & _ Request.Cookies(strKey).ToString( ) & "<br/>" If Request.Cookies(strKey).HasKeys Then For Each strSubKey In Request.Cookies(strKey).Values Message.Text = "->" & strKey & "(" & strSubKey & _ ") = " & Request.Cookies(strKey)(strSubKey).ToString( ) _ & "<br/>" Next End If Next To solve the first issue, we use the HttpCookie's Value method to get the value of the cookie as a string. The solution to the second issue is to call the Values property of the HttpCookie instance, which allows us to retrieve the subkeys of a dictionary cookie. Another quirk of the change from the mostly text-based manipulation of cookie keys and values in ASP to class-based manipulation in ASP.NET is that the Expires property of the HttpCookie class is available whether you read or write to a cookie. In ASP, however, attempting to read the Expires property of a cookie would result in an error. Unfortunately, at the time of this writing, the Expires property of HttpCookie does not actually return the expiration of the cookie. Instead, it returns the value 12:00:00 AM, which suggests that despite its readability, the property is not designed to be read from. Finally, unlike classic ASP, the collections in ASP.NET are zero-based, so the first element in any collection or array is 0, not 1. This is especially important to remember when retrieving values by their index.
The Files collection, which is new to ASP.NET, returns a collection of type HttpFileCollection that contains any files uploaded by the user's current request. This collection is especially useful in combination with the HtmlInputFile Server Control, which provides the basic plumbing necessary to upload files via an HTTP POST request. When a user submits one or more files (one per HtmlInputFile control on the submitting page), you can retrieve the files by using the Files collection. Parameter
ExampleThe example uses two HtmlInputFile server controls and a server-side <script> block to upload files and process them. The example shows both the <form> section of the page and its controls and the <script> block containing the UploadBtn_OnClick method called by the onServerClick event of the HtmlInputButton control: <!--Place between the <head> and </head> tags --> <script runat="server"> Sub UploadBtn_Click(Sender as Object, e as EventArgs) UploadForm.Visible = False If InStr(Request.ContentType, "multipart/form-data") Then Dim Counter1 As Integer Dim Keys( ) As String Dim Files As HttpFileCollection ' Load File collection Files = Request.Files ' Get names of all files into an array Keys = Files.AllKeys For Counter1 = 0 To Keys.GetUpperBound(0) Message.Text &= "File ID: " & Keys(Counter1) & "<br/>" Message.Text &= "File Name/Path: " & _ Files(Counter1).FileName & "<br/>" Next Counter1 Else Message.Text = "Wrong content type!" End If End Sub </script> <!-- This section resides between the <body> and </body> tags --> <form id="UploadForm" enctype="multipart/form-data" runat="server"> Select File To Upload to Server: <br/> <%-- MyFile and MyFile2 are HtmlInputFile controls --%> <%-- note the runat attribute --%> <input id="MyFile" type="file" runat="server"> <br/> <input id="MyFile2" type="file" runat="server"> <br/> <input id="Submit1" type="submit" value="Upload!" onserverclick="UploadBtn_Click" runat="server" > </form> <asp:label id="Message" runat="server"/> NotesIn classic ASP, file uploading was a painful process that usually involved finding and purchasing a third-party upload control to use on the receiving ASP page to parse and save uploaded files. Thanks to the Files collection, you no longer need to locate and learn how to use third-party controls to upload files. This is bad for the control developers (although we suspect they'll more than make up for the loss by writing new Server Controls), but great for ASP.NET developers. Two important points to remember about the Files collection to successfully upload files:
The upload will succeed only if you take both steps. Note that the code example checks to see if the incoming request is multipart/form-data before attempting to retrieve the files. It is not necessary to use the HtmlInputFile control to upload files that can be retrieved via the Files collection. As long as the submitting page uses the POST method and the multipart/form-data enctype attribute, you can use the standard HTML file input tags: <input type="file" id="myFile" name="myFile"> Note the use of the name attribute, without which the files collection will not contain the uploaded file for the control.
The Form collection returns an instance of the NameValueCollection class containing all form fields passed along with an HTTP POST request. This collection will contain data only when the Content-Type of the HTTP request is either application/x-www-form-urlencoded or multipart/form-data. The Form collection is one of two ways to retrieve data, depending on the HTTP method used to submit the data. The Form collection retrieves data submitted by an HTML form whose method attribute is set to POST, while the QueryString collection (covered later in this section) retrieves values submitted by HTML forms whose method attribute is set to GET. Parameter
ExampleThe example demonstrates how ASP.NET allows a single page to be used to submit values via HTTP POST and retrieve and display the values to the user. The example uses the IsPostBack property of the Page class to determine whether the request is a result of the form being submitted. If the request is not a postback, the form fields are displayed to allow the user to enter values. If the request is a postback, the page retrieves the Form collection and displays the name and value of each field in the browser. Sub Page_Load( ) If IsPostBack Then Form1.Visible = False If Request.HttpMethod = "POST" Then Dim Counter1 As Integer Dim Keys( ) As String Dim FormElements As NameValueCollection ' Get Form keys/elements FormElements=Request.Form ' Get names of form fields into array Keys = FormElements.AllKeys For Counter1 = 0 To Keys.GetUpperBound(0) Message.Text &= "Form " & Counter1 & " name: " & _ Keys(Counter1) & "<br/>" Message.Text &= "Form " & Counter1 & " value: " & _ FormElements(Counter1) & "<br/>" Next Counter1 End If Else Form1.Visible = True End If End Sub <!-- This section resides between the <body> and </body> tags --> <form id="Form1" runat="server"> First Name: <br/> <asp:Textbox id="txtFName" runat="server"/> <br/> Last Name: <br/> <asp:Textbox id="txtLName" runat="server"/> <br/> <asp:Button id="Submit" Text="Submit" runat="server"/> </form> <asp:label id="Message" runat="server"/> NotesThe Form collection exposes the same properties and methods described in Section 16.3 and adds the following methods:
The Headers collection returns an instance of the NameValueCollection class containing all HTTP headers sent with the current request. This collection provides the same information that is returned by calling the Request.ServerVariables collection with the ALL_HTTP key. Parameter
ExampleThe example writes the HTTP headers passed with the request to the browser, first by using the ServerVariables("ALL_HTTP") method and then by using the Headers collection: Sub Page_Load( ) Dim AllHttp As String ' Get a String with all the HTTP headers AllHttp = Request.ServerVariables("ALL_HTTP") ' Use Replace to format the String AllHttp = Replace(AllHttp, "HTTP", "<br/>HTTP" Message.Text &= AllHttp & "<br/><br/>" Dim Counter1, Counter2 As Integer Dim Keys( ), subKeys( ) As String Dim HeaderColl As NameValueCollection ' Load Headers into NameValueCollection HeaderColl=Request.Headers ' Get keys into an array Keys = HeaderColl.AllKeys For Counter1 = 0 To Keys.GetUpperBound(0) Message.Text &= "Key: " & Keys(Counter1) & "<br/>" ' Get all values under this key subKeys = HeaderColl.GetValues(Counter1) For Counter2 = 0 To subKeys.GetUpperBound(0) Message.Text &= "Value " & CStr(Counter2) & ": " & _ subKeys(Counter2) & "<br/>" Next Counter2 Next Counter1 End Sub NotesThe Headers collection returns only the HTTP headers that were sent as a part of the current request, as opposed to the ServerVariables collection (described later in this section), which contains keys for every HTTP header, regardless of whether a value was passed. If all you need to do is write the HTTP headers to a file or display them in the browser, it may be simpler to use the ServerVariables collection. In cases when you need to access a specific HTTP header by name or loop through the collection, the Headers collection is the way to go.
The Params collection returns an instance of the NameValueCollection class containing key/value pairs for the QueryString, Form, ServerVariables, and Cookies collections. You can use the Params collection to dump all of these collections to a file or to the browser and to troubleshoot an application or track the form values your application receives, regardless of whether they come via GET (QueryString collection) or POST (Form collection). Parameter
ExampleThe example writes the keys and values contained in the Params collection to the browser: Sub Page_Load( ) Dim Counter1, Counter2 As Integer Dim Keys( ), subKeys( ) As String Dim ParamColl As NameValueCollection ' Load Params into NameValueCollection ParamColl=Request.Params ' Get keys into an array Keys = ParamColl.AllKeys For Counter1 = 0 To Keys.GetUpperBound(0) Message.Text &= "Key: " & Keys(Counter1) & "<br/>" ' Get all values under this key subKeys = ParamColl.GetValues(Counter1) For Counter2 = 0 To subKeys.GetUpperBound(0) Message.Text &= "Value " & CStr(Counter2) & ": " & _ subKeys(Counter2) & "<br/>" Next Counter2 Message.Text &= "<br/>" Next Counter1 End Sub The following code can be used to post to the example page: <html> <head> <title>Submit a named parameter via POST</title> </head> <body> <form id="form1" action="Params.aspx" method="POST"> <h3>Name:</h3> <input type="text" name="name"> <input type="submit"> </form> </body> </html> NotesThe collections are listed in the following order:
While it is possible to have both the Form and QueryString collections populated (for example, if a query string name/value pair is added to the URL for the action attribute of a form by using the POST method), you will normally see one or the other, not both.
The QueryString collection returns an instance of the NameValueCollection class containing all the keys and values passed as a part of the query string (typically by submitting an HTML form that uses the GET method instead of POST). Parameters
ExampleThe example writes the contents of the QueryString collection to the browser: Sub Page_Load( ) Dim Counter1, Counter2 As Integer Dim Keys( ), subKeys( ) As String Dim QSColl As NameValueCollection ' Load QS into NameValueCollection QSColl=Request.QueryString ' Get keys into an array Keys = QSColl.AllKeys For Counter1 = 0 To Keys.GetUpperBound(0) Message.Text &= "Key: " & Keys(Counter1) & "<br/>" subKeys = QSCol1.GetValues(Counter1) 'Get all values under this key For Counter2 = 0 To subKeys.GetUpperBound(0) Message.Text &= "Value " & CStr(Counter2) & ": " & _ subKeys(Counter2) & "<br/>" Next Counter2 Message.Text &= "<br/>" Next Counter1 End Sub The following code can be used to post to the example page (note that the form method attribute has been set to GET, which is required for the form value to be sent as part of the query string): <html> <head> <title>Submit a named parameter via POST</title> </head> <body> <form id="form1" action="QueryString.aspx" method="GET"> <h3>Name:</h3> <input type="text" name="name"> <input type="submit"> </form> </body> </html> NotesOne advantage that the QueryString collection has over the Form collection is that you do not always need to have the user submit a form to use it. Because the query string values are appended to the URL, it is relatively simple to statically add query strings to links within pages or dynamically create anchor tags with query string values appended. In fact, many online stores use this method to drive their catalog pages (by passing a product ID appended onto a link to the page designed to display the product). That page can then retrieve the ID by using the QueryString collection. Because query string values are passed as plain text appended to the URL, they are more vulnerable to tampering than values passed as a result of a POST operation. If you need to pass important data or data that, if tampered with, could create problems for your application, you should consider encrypting values before adding them to the query string or using another method to pass the values. Certain characters used in query string processing, including &, ?, %, and +, must be encoded to avoid confusion between their use in your key/ value pair and their role as special characters in a query string. The following table lists the encoding for each of these special characters:
Rather than memorizing these values, you could make your life easier by simply using the UrlEncode method provided by the HttpServerUtility class (covered in Chapter 18), which automatically substitutes the appropriate encoding for any special characters in a string passed to it.
Parameter
ExampleThe example, as in the previous collection-related examples, writes the contents of the ServerVariables collection to the browser: Sub Page_Load( ) Dim Counter1, Counter2 As Integer Dim Keys( ), subKeys( ) As String Dim SVarsColl As NameValueCollection ' Load ServerVariables into NameValueCollection SVarsColl=Request.ServerVariables ' Get keys into an array Keys = SVarsColl.AllKeys For Counter1 = 0 To Keys.GetUpperBound(0) Message.Text &= "Key: " & Keys(Counter1) & "<br/>" subKeys = SVarsColl.GetValues(Counter1) ' Get all values under this key For Counter2 = 0 To subKeys.GetUpperBound(0) Message.Text &= "Value " & CStr(Counter2) & ": " & _ subKeys(Counter2) & "<br/>" Next Counter2 Message.Text &= "<br/>" Next Counter1 End Sub NotesIn addition to retrieving all the values by looping through the keys, you can access individual values if you know their key. The following list shows the available keys for the ServerVariable collection:
|
[ Team LiB ] |