INFO: Header Required Posting HTML Form Encoded Data to ASP Page

ID: Q175474

The information in this article applies to:

SUMMARY

When writing an Internet client application that posts HTML form data to an ASP page using Wininet API or Visual Basic Internet Transfer Control, it is necessary to add the following HTTP header in the POST request:

   Content-Type: application/x-www-form-urlencoded

This header indicates that the data being posted is encoded according to the rules in the HTML specification (RFC 1866). ASP will not retrieve your HTML form variables if this header is not present in the POST request.

The following Visual Basic example demonstrates adding a custom HTTP header to a POST request using either Wininet API or the Internet Transfer Control (SP2). Please note that you need the Internet Transfer Control from at least Visual Basic 5.0 Service Pack 2 or Visual Studio Service Pack 2 to implement POST. The original control cannot post correctly due to a bug. The code fragment in the CommandButton1 Click event in the following example uses Wininet API. The code fragment in the CommandButton2 Click event uses Internet Transfer Control (SP2).

Step-by-Step Example

1. Start a new Standard EXE project. Form1 is added by default.

2. From the Project menu, choose Components, and select the Internet

   Transfer Control(SP2) into the project.

3. Place an Internet Transfer Control 5.0(SP2), Inet1, on Form1.

4. Place two CommandButtons, Command1 and Command2, on Form1.

5. Add the following code to the project code window:

      Private Declare Function InternetOpen Lib "wininet.dll" _
         Alias "InternetOpenA" _
            (ByVal lpszCallerName As String, _
             ByVal dwAccessType As Long, _
             ByVal lpszProxyName As String, _
             ByVal lpszProxyBypass As String, _
             ByVal dwFlags As Long) As Long

      Private Declare Function InternetConnect Lib "wininet.dll" _
            Alias "InternetConnectA" _
            (ByVal hInternetSession As Long, _
             ByVal lpszServerName As String, _
             ByVal nProxyPort As Integer, _
             ByVal lpszUsername As String, _
             ByVal lpszPassword As String, _
             ByVal dwService As Long, _
             ByVal dwFlags As Long, _
             ByVal dwContext As Long) As Long

   Private Declare Function InternetReadFile Lib "wininet.dll" _
            (ByVal hFile As Long, _
             ByVal sBuffer As String, _
             ByVal lNumBytesToRead As Long, _
             lNumberOfBytesRead As Long) As Integer

   Private Declare Function HttpOpenRequest Lib "wininet.dll" _
            Alias "HttpOpenRequestA" _
            (ByVal hInternetSession As Long, _
             ByVal lpszVerb As String, _
             ByVal lpszObjectName As String, _
             ByVal lpszVersion As String, _
             ByVal lpszReferer As String, _
             ByVal lpszAcceptTypes As Long, _
             ByVal dwFlags As Long, _
             ByVal dwContext As Long) As Long

   Private Declare Function HttpSendRequest Lib "wininet.dll" _
            Alias "HttpSendRequestA" _
            (ByVal hHttpRequest As Long, _
             ByVal sHeaders As String, _
             ByVal lHeadersLength As Long, _
             ByVal sOptional As String, _
             ByVal lOptionalLength As Long) As Boolean

   Private Declare Function InternetCloseHandle Lib "wininet.dll" _
            (ByVal hInternetHandle As Long) As Boolean

   Private Declare Function HttpAddRequestHeaders Lib "wininet.dll" _
             Alias "HttpAddRequestHeadersA" _
             (ByVal hHttpRequest As Long, _
             ByVal sHeaders As String, _
             ByVal lHeadersLength As Long, _
             ByVal lModifiers As Long) As Integer

   Private Sub Command1_Click()
            Dim hInternetOpen As Long
            Dim hInternetConnect As Long
            Dim hHttpOpenRequest As Long
            Dim bRet As Boolean

            hInternetOpen = 0
            hInternetConnect = 0
            hHttpOpenRequest = 0

            'Use registry access settings.
            Const INTERNET_OPEN_TYPE_PRECONFIG = 0
            hInternetOpen = InternetOpen("http generic", _
                            INTERNET_OPEN_TYPE_PRECONFIG, _
                            vbNullString, _
                            vbNullString, _
                            0)

            If hInternetOpen <> 0 Then
               'Type of service to access.
               Const INTERNET_SERVICE_HTTP = 3
               Const INTERNET_DEFAULT_HTTP_PORT = 80
               'Change the server to your server name
               hInternetConnect = InternetConnect(hInternetOpen, _
                                  "yourserver", _
                                  INTERNET_DEFAULT_HTTP_PORT, _
                                  vbNullString, _
                                  "HTTP/1.0", _
                                  INTERNET_SERVICE_HTTP, _
                                  0, _
                                  0)

               If hInternetConnect <> 0 Then
                'Brings the data across the wire even if it locally cached.
                 Const INTERNET_FLAG_RELOAD = &H80000000
                 hHttpOpenRequest = HttpOpenRequest(hInternetConnect, _
                                     "POST", _
                                     "/scripts/testpost.asp", _
                                     "HTTP/1.0", _
                                     vbNullString, _
                                     0, _
                                     INTERNET_FLAG_RELOAD, _
                                     0)

                  If hHttpOpenRequest <> 0 Then
                     Dim sHeader As String
                     Const HTTP_ADDREQ_FLAG_ADD = &H20000000
                     Const HTTP_ADDREQ_FLAG_REPLACE = &H80000000
           sHeader = "Content-Type: application/x-www-form-urlencoded" _
                       & vbCrLf
                     bRet = HttpAddRequestHeaders(hHttpOpenRequest, _
                       sHeader, Len(sHeader), HTTP_ADDREQ_FLAG_REPLACE _
                       Or HTTP_ADDREQ_FLAG_ADD)

                     Dim lpszPostData As String
                     Dim lPostDataLen As Long

                     lpszPostData = "lname=Doe&fname=John"
                     lPostDataLen = Len(lpszPostData)
                     bRet = HttpSendRequest(hHttpOpenRequest, _
                            vbNullString, _
                            0, _
                            lpszPostData, _
                            lPostDataLen)

                     Dim bDoLoop             As Boolean
                     Dim sReadBuffer         As String * 2048
                     Dim lNumberOfBytesRead  As Long
                     Dim sBuffer             As String
                     bDoLoop = True
                     While bDoLoop
                      sReadBuffer = vbNullString
                      bDoLoop = InternetReadFile(hHttpOpenRequest, _
                         sReadBuffer, Len(sReadBuffer), lNumberOfBytesRead)
                      sBuffer = sBuffer & _
                           Left(sReadBuffer, lNumberOfBytesRead)
                      If Not CBool(lNumberOfBytesRead) Then bDoLoop = False
                     Wend
                     MsgBox sBuffer
                     bRet = InternetCloseHandle(hHttpOpenRequest)
                  End If
                  bRet = InternetCloseHandle(hInternetConnect)
               End If
               bRet = InternetCloseHandle(hInternetOpen)
            End If

   End Sub

   Private Sub Command2_Click()
         Dim strURL As String, strFormData As String
         'Change the server to your server name
         strURL = "http://yourserver/scripts/testpost.asp"
         strFormData = "lname=Doe&fname=John"
         Inet1.Execute strURL, "Post", strFormData, _
            "Content-Type: application/x-www-form-urlencoded"
   End Sub

   Private Sub Inet1_StateChanged(ByVal State As Integer)
       Dim vtData As Variant ' Data variable.

       Select Case State
       ' ... Other cases not shown.
       Case icError ' 11
           ' In case of error, return ResponseCode and
   ' ResponseInfo.
           vtData = Inet1.ResponseCode & ":" & _
           Inet1.ResponseInfo

       Case icResponseCompleted  ' 12
           Dim strData As String: strData = ""
           Dim bDone As Boolean: bDone = False

           ' Get first chunk.
           vtData = Inet1.GetChunk(1024, icString)
           DoEvents

           Do While Not bDone

               strData = strData & vtData
               ' Get next chunk.
               vtData = Inet1.GetChunk(1024, icString)
               DoEvents

               If Len(vtData) = 0 Then
                   bDone = True
               End If
           Loop

          MsgBox strData
       End Select
   End Sub

   Private Sub Form_Load()
       Inet1.Cancel
   End Sub

6. From the File menu, choose Make Project1.exe to compile the project.

   Note that tracing the Inet1_StateChanged event callback function in the
   VB debugger may not work properly because this callback function needs
   to be repeated called and can't be stopped in debugger before a complete
   HTTP response is received. If you need to trace the Inet1_StateChanged
   event callback function in the debugger, use Debug.Print.

7. Create a testpost.asp file and place it in your Web server scripts
   directory:

      <HTML>
      <HEAD>
      <TITLE>test asp</TITLE>
      </HEAD>
      <BODY BGCOLOR=#FFFFFF>
      <H3>test asp</H3>
      fname is
      <% =Request("fname") %>
      <BR>
      lname is
      <% =Request("lname") %>
      </BODY>
      </HTML>

REFERENCES

RFC 1866 - Hypertext Markup Language - 2.0 at: http://nic.merit.edu/internet/documents/rfc/rfc1866.txt

Section 8.2, "Form Submission"

Keywords          : kbcode kbIE400 kbIE401 AXSDKMisc 
Version           : WINDOWS:1.0,4.0,4.01,5.0
Platform          : WINDOWS
Issue type        : kbinfo

Last Reviewed: January 9, 1999