POST
|
POST
Issuing a POST request is similar to issuing an HTTP GET request. One difference is that the request stream is retrieved from the HttpWebRequest object to send the post data. The general steps for issuing a POST request are:
The following code sample illustrates issuing a POST request and receiving the response:
C#
HttpWebRequest httpRequest; HttpWebResponse httpResponse; BinaryReader httpResponseStream;
try { // Create HTTP Web request httpRequest = (HttpWebRequest) WebRequest.Create("http://www.microsoft.com" ); // Change method from the default "GET" to "POST" httpRequest.Method = "POST"; // Posted forms need to be encoded so change the content type httpRequest.ContentType = "application/x-www-form-urlencoded"; // Data to POST string postData = "sl=foo&s2=bar"; // Retrieve a byte array representation of the data byte [ ] postBytes = Encoding.UTF8.GetBytes(postData.ToString() ); // Set the content length httpRequest.ContentLength = postBytes.Length; // Retrieve the request stream so we can write the POST data Stream httpPostStream = httpRequest.GetRequestStream(); // Write the POST request httpPostStream.Write( postBytes, 0, postBytes.Length ); httpPostStream.Close(); // Retrieve the response httpResponse = (HttpWebResponse) httpRequest.GetResponse(); // Retrieve the response stream httpResponseStream = new BinaryReader(httpResponse.GetResponseStream(), Encoding.UTF8);
byte [ ] readData;
while ( true ) { readData = httpResponseStream.ReadBytes( 4096 ); if ( readData.Length == 0 ) break; // Process the response } httpResponseStream.Close(); httpResponse.Close(); } catch ( WebException wex ) { Console.WriteLine("Exception occurred: {0}", wex.ToString()); httpResponse = (HttpWebResponse) wex.Response; httpResponse.Close(); } |
Dim httpRequest As HttpWebRequest
Dim httpResponse As HttpWebResponse
Dim httpResponseStream As BinaryReader
Try
' Create HTTP Web request
httpRequest = WebRequest.Create("http://www.microsoft.com/")
' Change method from the default "GET" to "POST"
httpRequest.Method = "POST"
' Posted forms need to be encoded so change the content type
httpRequest.ContentType = "application/x-www-form-urlencoded"
' Data to POST
Dim postData As String = "sl=foo&s2=bar"
' Retrieve a byte array representation of the data
Dim postBytes() As Byte = Encoding.UTF8.GetBytes(postData.ToString())
' Set the content length
httpRequest.ContentLength = postBytes.Length
' Retrieve the request stream so we can write the POST data
Dim httpPostStream As Stream = httpRequest.GetRequestStream()
' Write the POST request
httpPostStream.Write(postBytes, 0, postBytes.Length)
httpPostStream.Close()
' Retrieve the response
httpResponse = httpRequest.GetResponse()
' Retrieve the response stream
httpResponseStream = New BinaryReader(httpResponse.GetResponseStream(), Encoding.UTF8())
Dim readData() As Byte
While (True)
readData = httpResponseStream.ReadBytes(4096)
If readData.Length = 0 Then
GoTo afterwhile
End If
' Process the response
End While
afterwhile:
httpResponseStream.Close()
httpResponse.Close()
Catch wex As WebException
Console.WriteLine("Exception occurred: {0}", wex.ToString())
httpResponse = wex.Response
httpResponse.Close()
End Try
The following program examples illustrate posting a form to a URI and receiving the response.
Create a new CLR console application project and you might want to use HttpPostRequestCP as the project and the solution names.
Add the following codes that include HttpPostRequest class.
// HttpPostRequestCP.cpp : main project file. // // This sample illustrates how to issue an HttpWebRequest to POST data to a web site. // The steps for posting data are fairly similar to the GET request. They are: // 1. Create an HttpWebRequest object and change method to POST and content type // to encoded form // 2. Retrieve the request stream // 3. Write the post data on the request stream // 4. Retrieve the HttpWebResponse object // 5. Retrieve the response stream and receive the data // // This sample takes the URL to post to, the data string to post, and an optional // web proxy (if required to reach the Internet). The sample then performs the steps // listed above. // // usage: // Executable_file_name [-u URL] [-d data] [-s file] [-p proxy] // -u URL URL to post data to // -d data Data to post // -s file File name to save response to // -p HTTP URL Proxy to use for post operation // // sample usage: // Post data to http://www.microsoft.com and save to foo.html: // Executable_file_name -u http://www.microsoft.com -d "sl=como&s2=estas" -s foo.html // #include "stdafx.h"
using namespace System; using namespace System; using namespace System::Net; using namespace System::IO; using namespace System::Text; using namespace System::Web;
/// <summary> /// Simple class that encapsulates the HTTP post sample. /// </summary> public ref class HttpPostRequest { /// <summary> /// Displays simple usage information. /// </summary> public: static void usage() { Console::WriteLine("Executable_file_name [-u URL] [-d data] [-s file] [-p proxy]"); Console::WriteLine("Available options:"); Console::WriteLine(" -u URL URL to post data to"); Console::WriteLine(" -d data Data to post"); Console::WriteLine(" -s file File name to save response to"); Console::WriteLine(" -p HTTP URL Proxy to use for post operation"); Console::WriteLine(); }
/// <summary> /// This routine validates the data being posted to the web page. It parses /// the string for reserved characters '?', '=', and '&'. The individual /// validated parts are returned via a StringBuilder object. /// </summary> /// <param name="postData">Data to validate</param> /// <returns>StringBuilder object representing the parsed elements</returns> public: static StringBuilder^ ValidatePostData(String^ postData) { StringBuilder^ encodedPostData = gcnew StringBuilder(); // These chars should be more...e.g. custom array<Char>^ reservedChars = { '?', '=', '&' }; int pos, offset; // Validate the data to be posted Console::WriteLine("Validating the data to be posted..."); offset = 0; while (offset < postData->Length) { pos = postData->IndexOfAny(reservedChars, offset); if (pos == -1) { // UrlEncode() replaces all character codes except for letters, numbers // and the following punctuation characters: // - (minus sign) // _ (underscore) // . (period) // ! (exclamation point) // ~ (tilde) // ' (single quotation mark) // ( and ) (opening and closing parentheses) // # (number sign) // The UrlDecode() method reverses the encoding // Append the remaining part of the string Console::WriteLine("Appending the remaining part of the string..."); encodedPostData->Append(HttpUtility::UrlEncode(postData->Substring(offset, postData->Length - offset))); break; } // Found a special character so append up to the special character Console::WriteLine("Found a special character so append up to the special character..."); encodedPostData->Append(HttpUtility::UrlEncode(postData->Substring(offset, pos - offset))); encodedPostData->Append(postData->Substring(pos, 1)); offset = pos + 1; } return encodedPostData; }
/// <summary> /// This method creates an HttpWebRequest object, sets the method to "POST", /// and builds the data to post. Once the HttpWebRequest object is created, /// the request stream is obtained and the post data is sent and the /// request stream closed. The response is then retrieved. /// </summary> /// <param name="postUrl">URL to post data to</param> /// <param name="postData">Data to post</param> /// <param name="proxyServer">Proxy server to use</param> /// <param name="saveFile">Filename to save response to</param> public: static void HttpMethodPost(String^ postUrl, String^ postData, IWebProxy^ proxyServer, String^ saveFile) { HttpWebRequest^ httpRequest = nullptr; HttpWebResponse^ httpResponse = nullptr; Stream^ httpPostStream = nullptr; BinaryReader^ httpResponseStream = nullptr; FileStream^ localFile = nullptr;
try { StringBuilder^ encodedPostData; array<Byte>^ postBytes = nullptr;
// Create HTTP web request Console::WriteLine("Creating HTTP web request..."); httpRequest = (HttpWebRequest^)WebRequest::Create(postUrl); // Change method from the default "GET" to "POST" Console::WriteLine("Changing method from the default \"GET\" to \"POST\"..."); httpRequest->Method = "POST"; // Posted forms need to be encoded so change the content type Console::WriteLine("Changing the content type..."); httpRequest->ContentType = "application/x-www-form-urlencoded"; // Set the proxy Console::WriteLine("Setting the proxy..."); httpRequest->Proxy = proxyServer; // Validate and encode the data to POST Console::WriteLine("Validating and encode the data to POST..."); encodedPostData = ValidatePostData(postData); Console::WriteLine("Encoded POST string: '{0}'", encodedPostData->ToString()); // Retrieve a byte array representation of the data Console::WriteLine("Retrieving a byte array representation of the data..."); postBytes = Encoding::UTF8->GetBytes(encodedPostData->ToString()); // Set the content length (the number of bytes in the POST request) Console::WriteLine("Setting the content length - the number of bytes in the POST request..."); httpRequest->ContentLength = postBytes->Length; // Retrieve the request stream so we can write the POST data Console::WriteLine("Retrieving the request stream so we can write the POST data..."); httpPostStream = httpRequest->GetRequestStream(); // Write the POST request Console::WriteLine("Writing the POST request..."); httpPostStream->Write(postBytes, 0, postBytes->Length); httpPostStream->Close(); httpPostStream = nullptr; // Retrieve the response Console::WriteLine("Retrieving the response..."); httpResponse = (HttpWebResponse^)httpRequest->GetResponse(); // Retrieve the response stream Console::WriteLine("Retrieving the response stream..."); httpResponseStream = gcnew BinaryReader(httpResponse->GetResponseStream(), Encoding::UTF8);
array<Byte>^ readData;
// Open the file to save the response to Console::WriteLine("Opening the file to save the response to..."); localFile = File::Open(saveFile, FileMode::Create, FileAccess::Write, FileShare::None); Console::WriteLine("Saving response to: {0}", localFile->Name); Console::Write("Receiving response stream until the end...\n"); // Receive the response stream until the end int count = 0; long percent;
while (true) { readData = httpResponseStream->ReadBytes(4096); if (readData->Length == 0) break; localFile->Write(readData, 0, readData->Length); // Calculate the progress and display to the console Console::Write(" ...Calculating the progress and display to the console...\n"); count += readData->Length; percent = (count * 100) / (long)httpResponse->ContentLength; Console::Write("\b\b\b"); Console::Write("{0}%", percent.ToString()->PadLeft(2)); } Console::WriteLine(); } catch (WebException^ wex) { Console::WriteLine("HttpMethodPost() - Exception occurred: {0}", wex->Message); httpResponse = (HttpWebResponse^)wex->Response; } finally { // Close any remaining resources Console::Write("Closing any remaining resources...\n"); if (httpResponse != nullptr) { httpResponse->Close(); } if (localFile != nullptr) { localFile->Close(); } } } };
/// <summary> /// This is the main routine that parses the command line and calls routines to /// issue the POST request and receive the response. /// </summary> /// <param name="args">Command line arguments</param> int main(array<System::String ^> ^args) { // Example: http://search.live.com/results.aspx?q=tenouk&go=&form=QBLH // http://search.msdn.microsoft.com/Default.aspx?query=web&brand=msdn&locale=en-us&refinement= IWebProxy^ proxyServer; String^ uriToPost = "http://search.live.com/"; String^ proxyName = nullptr; String^ postData = "results.aspx?q=tenouk&go=&form"; String^ fileName = nullptr;
// Parse the command line if(args->Length != 0) { for (int i = 0; i < args->Length; i++) { try { if ((args[i][0] == '-') || (args[i][0] == '/')) { switch (Char::ToLower(args[i][1])) { case 'u': // URI to post to uriToPost = args[++i]; break; case 'p': // Name of proxy server to use proxyName = args[++i]; break; case 'd': // Retrieve all referenced images and text on the same host postData = args[++i]; break; case 's': // Local save path to append to retrieved resources fileName = args[++i]; break; default: HttpPostRequest::usage(); return 0; } } } catch(Exception^ err) { Console::WriteLine("Error: " + err->Message); HttpPostRequest::usage(); return 0; } } } else { HttpPostRequest::usage(); return 0; }
try { // Set the proxy if supplied or use the default IE static proxy Console::Write("Setting the proxy if supplied or use the default IE static proxy...\n"); if (proxyName == nullptr) { proxyServer = WebRequest::DefaultWebProxy; } else { proxyServer = gcnew WebProxy(proxyName); }
// Post the request and write the response to the file Console::Write("Posting the request and write the response to the file...\n"); HttpPostRequest::HttpMethodPost(uriToPost, postData, proxyServer, fileName); } catch (Exception^ ex) { Console::WriteLine("Main() - Exception occurred: {0}", ex->Message); } return 0; }
|
Build and run the project. Well, there is an error as shown below stating that 'HttpUtility' is undeclared identifier. It seems that the System.Web cannot resolve the reference. To solve this, let add a reference to the Web.dll manually.
1>.\HttpPostRequestCP.cpp(68) : error C2065: 'HttpUtility' : undeclared identifier 1>.\HttpPostRequestCP.cpp(68) : error C2227: left of '->UrlEncode' must point to class/struct/union/generic type 1> type is ''unknown-type'' 1>.\HttpPostRequestCP.cpp(73) : error C2065: 'HttpUtility' : undeclared identifier 1>.\HttpPostRequestCP.cpp(73) : error C2227: left of '->UrlEncode' must point to class/struct/union/generic type 1> type is ''unknown-type'' |
We can test this issue by adding the scope operator at the end of the System::Web namespace as shown below. There is no HttpUtility from the intellisense context menu.
So, let add the System::Web manually. Select the project folder > Right click mouse > Select References context menu.
There is no System.Web under the Name: column of the References:. Click the Add New Reference button.
Find the System.Web (Web.dll) in the .NET tab and click OK.
You can see the System.Web namespace was added in the Reference: field. Click the OK button.
Now, let re-test the System::Web using directive as shown below. This time, you should see the HttpUtility.
Build and run the project. The following is the sample output.
The following sample output is based on the following arguments:
C:\>httppostrequestcs -u http://search.msdn.microsoft.com/ -d Default.aspx?Query=web.dll -s test.htm