In article <uD************ **@tk2msftngp13 .phx.gbl>,
jo*********@gmx .net says...
Gregory A Greenman wrote: I'm trying to write a program in vb.net to automate filling out a
series of forms on a website. There are three forms I need to
fill out in sequence. The first one is urlencoded. My program is
able to fill that one out just fine.
The second form is multipart/form-data. Unfortunately, I haven't
been able to fill that out in a way that makes the server happy.
I set up a copy of this form at my web site so that I could see
exactly what a browser sends to the server and compare that to
what my program sends. I saw a few mistakes in my program and I
fixed them, but the real web site still rejects my program's
submissions.
As best I can tell, the contents that my program submits are
identical to the contents submitted by a browser. Is there
anything else that might be causing my problem?
Well, analyzing your problem from 10000' isn't that easy... can you provide
more details (code, error messages, ...)?
Okay. I'm getting "The remote server returned an error: (500)
internal server error".
I've got a form with two text boxes in the upper left corner,
txtHalfID and txtHalfPassword . There are three text boxes in the
upper right corner, txtISBN, txtDescription and txtPrice. There's
also a drop down combo in the upper right, cmbCondition.
The bottom portion of the screen has a read only multi line text
box called txtResponse, where the raw HTML from the server is
displayed.
Below the left text boxes is a button, btnSignOn. If you click
that button, it will sign you onto Half.com using the ID and
password in the textboxes above it. This part works fine for me.
I can see the "Welcome to eBay" page in txtResponse.
Below the right boxes is a button called btnListBook. When I
click on it it should call four web pages on half.com in order.
First it calls
http://half.ebay.com/help/sell_books.cfm. It fills
in the field in the form there with txtISBN.
Next it calls
http://half.ebay.com/cat/sell/pmsearch.cgi. It
fills out the form there with txtDescription and cmbCondition.
This form allows file uploads, so it's a multipart form. Although
my program's output looks good to me, I get that server error
when I submit this form.
Here's the code:
- Start Code ---------------------------------------------------
Imports System.Net
Public Class SBM
Inherits System.Windows. Forms.Form
Dim cc As New CookieCollectio n
Const encURL As Integer = 0
Const encMulti As Integer = 1
Private Sub SBM_Load(ByVal sender As System.Object, ByVal e
As System.EventArg s) Handles MyBase.Load
txtHalfID.Text = ""
txtHalfPassword .Text = ""
txtISBN.Text = "0764560255 "
txtDescription. Text = "good good"
txtPrice.Text = "99.99"
With cmbCondition
.Items.Add(New Conditions("Bra nd New", "830"))
.Items.Add(New Conditions("Lik e New", "840"))
.Items.Add(New Conditions("Ver y Good", "849"))
.Items.Add(New Conditions("Goo d", "859"))
.Items.Add(New Conditions("Acc eptable", "864"))
.SelectedIndex = 0
End With
cmbCondition.Se lectedIndex = 0
End Sub
Private Sub btnSignOn_Click (ByVal sender As System.Object,
ByVal e As System.EventArg s) Handles btnSignOn.Click
Dim HWRequest As HttpWebRequest
Dim strURL As String
Dim HWParameters As Parameters
Dim intFound As Integer
HWRequest = GetRequest
("https://signin.ebay.com/ws/eBayISAPI.dll?S ignIn&UsingSSL= 1
&co_partnerid=2 &siteid=20")
strURL = "https://signin.half.eba y.com/ws/eBayISAPI.dll"
HWParameters = ReadResponse(HW Request, strURL)
intFound = 0
For Each p As Parameter In HWParameters
Select Case p.Name
Case "userid"
p.Value = txtHalfID.Text
intFound += 1
Case "pass"
p.Value = txtHalfPassword .Text
intFound += 1
End Select
If intFound = 2 Then
Exit For
End If
Next
HWRequest = PostRequest(str URL, HWParameters, encURL)
GetResponse(HWR equest)
End Sub
Private Sub btnListBook_Cli ck(ByVal sender As System.Object,
ByVal e As System.EventArg s) Handles btnListBook.Cli ck
Dim strPostData As String
Dim HWRequest As HttpWebRequest
Dim strURL As String
Dim HWParameters As Parameters
Dim intFound As Integer
Dim pr As Parameter
Try
HWRequest = GetRequest
("http://half.ebay.com/help/sell_books.cfm" )
strURL = "http://half.ebay.com/cat/sell/pmsearch.cgi"
HWParameters = ReadResponse(HW Request, strURL)
intFound = 0
For Each p As Parameter In HWParameters
Select Case p.Name
Case "p_code"
p.Value = txtISBN.Text
intFound += 1
End Select
If intFound = 1 Then
Exit For
End If
Next
HWRequest = PostRequest(str URL, HWParameters, encURL)
strURL = "/cat/sell/save_new_listin g.cgi"
HWParameters = ReadResponse(HW Request, strURL)
pr = New Parameter
pr.Name = "x"
pr.Value = 20
pr.Type = Parameter.Input
HWParameters.Ad d(pr)
pr = New Parameter
pr.Name = "y"
pr.Value = 20
pr.Type = Parameter.Input
HWParameters.Ad d(pr)
intFound = 0
For Each p As Parameter In HWParameters
Select Case p.Name
Case "notes"
p.Value = txtDescription. Text
intFound += 1
Case "condition"
p.Value = cmbCondition.It ems
(cmbCondition.S electedIndex).I temData
intFound += 1
End Select
If intFound = 2 Then
Exit For
End If
Next
strURL =
"http://half.ebay.com/cat/sell/save_new_listin g.cgi"
HWRequest = PostRequest(str URL, HWParameters,
encMulti)
strURL = "sell.jsp"
HWRequest.Refer er =
"http://half.ebay.com/cat/sell/pmsearch.cgi"
'the internal server error is generated in this call
'to ReadResponse
HWParameters = ReadResponse(HW Request, strURL)
intFound = 0
For Each p As Parameter In HWParameters
Select Case p.Name
Case "itemPrice"
p.Value = txtPrice.Text
intFound += 1
End Select
If intFound = 1 Then
Exit For
End If
Next
strURL = "http://half.ebay.com/cat/sell/sell.jsp"
HWRequest = PostRequest(str URL, HWParameters, encURL)
GetResponse(HWR equest)
MessageBox.Show ("Success!", MsgBoxStyle.OKO nly, "Book
Posted")
Catch ex As Exception
MessageBox.Show ("Error: " & ex.Message, "Error!!!",
MessageBoxButto ns.OK, MessageBoxIcon. Exclamation)
MsgBox("Half.co m appears to have changed its posting
procedures. As a result, this version of SBM cannot list books on
it.", MsgBoxStyle.Exc lamation, "Half.com Listing Problem")
End Try
End Sub
Private Function GetRequest(ByVa l strURL As String) As
HttpWebRequest
GetRequest = CreateRequest(s trURL)
GetRequest.Meth od = "GET"
End Function
Private Function PostRequest(ByV al strURL As String, ByVal
PostParameters As Parameters, ByVal intType As Integer) As
HttpWebRequest
Dim encoding As New System.Text.ASC IIEncoding
Dim byte1 As Byte()
Dim newStream As System.IO.Strea m
Dim strData As String
Const strBoundary As String =
"---------------------------7d4285126106b0"
PostRequest = CreateRequest(s trURL)
PostRequest.Met hod = "POST"
If intType = encURL Then
PostRequest.Con tentType = "applicatio n/x-www-form-
urlencoded"
Else
PostRequest.Con tentType = "multipart/form-data,
boundary=" & strBoundary
End If
strData = BuildRequestStr ing(PostParamet ers, intType,
strBoundary)
PostRequest.Con tentLength = strData.Length
byte1 = encoding.GetByt es(strData)
newStream = PostRequest.Get RequestStream
newStream.Write (byte1, 0, byte1.Length)
newStream.Close ()
End Function
Private Function BuildRequestStr ing(ByVal RequestParamete rs
As Parameters, ByVal intType As Integer, ByVal strBoundary As
String)
BuildRequestStr ing = ""
Select Case intType
Case encURL
For Each p As Parameter In RequestParamete rs
BuildRequestStr ing &= p.Name.Trim & "=" &
p.Value.Trim & "&"
Next
BuildRequestStr ing = Mid(BuildReques tString, 1,
Len(BuildReques tString) - 1)
Case encMulti
'the requeststring generated for the multipart form is
'shown below
For Each p As Parameter In RequestParamete rs
BuildRequestStr ing &= "--" & strBoundary &
vbCrLf & "Content-Disposition: form-data; name=""" & p.Name.Trim
& """"
Select Case p.Type
Case Parameter.File
BuildRequestStr ing &= ";
filename=""""" & vbCrLf & "Content-Type: application/octet-
stream" & vbCrLf & vbCrLf & vbCrLf
Case Parameter.Input
BuildRequestStr ing &= vbCrLf & vbCrLf
& p.Value & vbCrLf
End Select
Next
BuildRequestStr ing &= "--" & strBoundary & "--"
End Select
End Function
Private Function CreateRequest(B yVal strURL As String) As
HttpWebRequest
Dim Uri As Uri
Uri = New Uri(strURL)
CreateRequest = HttpWebRequest. Create(Uri)
CreateRequest.A llowAutoRedirec t = True
CreateRequest.C ookieContainer = New CookieContainer
If cc.Count > 0 Then
CreateRequest.C ookieContainer. Add(cc)
End If
End Function
Private Sub GetResponse(ByV al ReadRequest As HttpWebRequest)
Dim HWResponse As HttpWebResponse
Dim cookie As Cookie
HWResponse = ReadRequest.Get Response()
If HWResponse.Cook ies.Count > 0 Then
For Each cookie In HWResponse.Cook ies
cc.Add(cookie)
Next
End If
'debugging
Dim sr As System.IO.Strea mReader
Dim strResult As String
sr = New System.IO.Strea mReader
(HWResponse.Get ResponseStream( ))
txtResponse.Tex t = sr.ReadToEnd
sr.Close()
'debugging
End Sub
Private Function ReadResponse(By Val ReadRequest As
HttpWebRequest, ByVal ReadURL As String) As Parameters
Dim HWResponse As HttpWebResponse
Dim cookie As Cookie
Dim sr As System.IO.Strea mReader
Dim strResult As String
Dim intTagPos As Integer
Dim intLength As Integer
Dim intURLPos As Integer
Dim strTag As String
Dim blnFormFound As Boolean
Dim blnMoreForms As Boolean
Dim intPos As Integer
Dim strName As String
Dim strValue As String
Dim ReadParameter As Parameter
Dim intType As Integer
Dim intInputPos As Integer
Dim intTextPos As Integer
Dim intSelectPos As Integer
Dim blnTagFound As Boolean
ReadResponse = New Parameters
'the next line generates the internal server error
HWResponse = ReadRequest.Get Response()
If HWResponse.Cook ies.Count > 0 Then
For Each cookie In HWResponse.Cook ies
cc.Add(cookie)
Next
End If
sr = New System.IO.Strea mReader
(HWResponse.Get ResponseStream( ))
strResult = sr.ReadToEnd
'debugging
txtResponse.Tex t = strResult
'debugging
blnFormFound = False
blnMoreForms = True
intTagPos = 1
While Not blnFormFound And blnMoreForms
intTagPos = InStr(intTagPos , strResult.ToUpp er,
"<FORM", CompareMethod.T ext)
If intTagPos <> 0 Then
intLength = InStr(intTagPos , strResult, ">",
CompareMethod.T ext) - intTagPos
strTag = strResult.Subst ring(intTagPos,
intLength)
intURLPos = InStr(1, strTag.ToUpper,
ReadURL.ToUpper , CompareMethod.T ext)
If intURLPos <> 0 Then
intLength = InStr(intTagPos ,
strResult.ToUpp er, "</FORM>", CompareMethod.T ext) - intTagPos
strResult = strResult.Subst ring(intTagPos,
intLength)
blnFormFound = True
Else
intTagPos += 1
End If
Else
blnMoreForms = False
End If
End While
If blnFormFound Then
intTagPos = 1
While intTagPos <> 0
intInputPos = InStr(intTagPos , strResult.ToUpp er,
"<INPUT", CompareMethod.T ext)
intTextPos = InStr(intTagPos , strResult.ToUpp er,
"<TEXTAREA" , CompareMethod.T ext)
intSelectPos = InStr(intTagPos ,
strResult.ToUpp er, "<SELECT", CompareMethod.T ext)
intTagPos = IIf(intTextPos <> 0 And intTextPos <
intInputPos, intTextPos, intInputPos)
intTagPos = IIf(intSelectPo s <> 0 And
intSelectPos < intTagPos, intSelectPos, intTagPos)
intType = Parameter.Input
If intTagPos <> 0 Then
intLength = InStr(intTagPos , strResult, ">",
CompareMethod.T ext) - intTagPos
strTag = strResult.Subst ring(intTagPos,
intLength)
intPos = InStr(1, strTag.ToUpper,
"TYPE=SUBMI T", CompareMethod.T ext)
If intPos = 0 Then
intPos = InStr(1, strTag.ToUpper,
"TYPE=""SUBMIT" "", CompareMethod.T ext)
End If
If intPos = 0 Then
intPos = InStr(1, strTag.ToUpper,
"NAME=""", CompareMethod.T ext)
If intPos = 0 Then
intPos = InStr(1, strTag.ToUpper,
"NAME=", CompareMethod.T ext)
intLength = InStr(intPos + 5, strTag,
" ", CompareMethod.T ext) - intPos - 5
strName = strTag.Substrin g(intPos +
4, intLength)
Else
intLength = InStr(intPos + 6, strTag,
"""", CompareMethod.T ext) - intPos - 6
strName = strTag.Substrin g(intPos +
5, intLength)
End If
If intPos <> 0 Then
intPos = InStr(1, strTag.ToUpper,
"VALUE=""", CompareMethod.T ext)
If intPos = 0 Then
strValue = ""
Else
intLength = InStr(intPos + 7,
strTag, """", CompareMethod.T ext) - intPos - 7
strValue = strTag.Substrin g
(intPos + 6, intLength)
End If
intPos = InStr(1, strTag.ToUpper,
"TYPE=""FILE""" , CompareMethod.T ext)
If intPos = 0 Then
intPos = InStr(1, strTag.ToUpper,
"TYPE=FILE" , CompareMethod.T ext)
End If
intType = IIf(intPos = 0, intType,
Parameter.File)
ReadParameter = New Parameter
ReadParameter.N ame = strName
ReadParameter.V alue = strValue
ReadParameter.T ype = intType
ReadResponse.Ad d(ReadParameter )
End If
End If
intTagPos += 1
End If
End While
Else
Throw New System.Exceptio n("Form not found.")
End If
End Function
End Class
Public Class Parameters
Inherits System.Collecti ons.CollectionB ase
Public Sub Add(ByVal sFld As Parameter)
List.Add(sFld)
End Sub
Public ReadOnly Property Item(ByVal index As Integer) As
Parameter
Get
Return CType(List.Item (index), Parameter)
End Get
End Property
End Class
Public Class Parameter
Public Const Input As Integer = 0
Public Const File As Integer = 1
Dim strName As String
Dim strValue As String
Dim intType As Integer
Public Property Name() As String
Get
Return strName
End Get
Set(ByVal vName As String)
strName = vName
End Set
End Property
Public Property Value() As String
Get
Return strValue
End Get
Set(ByVal vName As String)
strValue = vName
End Set
End Property
Public Property Type() As Integer
Get
Return intType
End Get
Set(ByVal vType As Integer)
intType = vType
End Set
End Property
End Class
Public Class Conditions
Private strName As String
Private strID As String
Public Sub New()
strName = ""
strID = ""
End Sub
Public Sub New(ByVal Name As String, ByVal ID As String)
strName = Name
strID = ID
End Sub
Public Property Name() As String
Get
Return strName
End Get
Set(ByVal sValue As String)
strName = sValue
End Set
End Property
Public Property ItemData() As String
Get
Return strID
End Get
Set(ByVal iValue As String)
strID = iValue
End Set
End Property
Public Overrides Function ToString() As String
Return strName
End Function
End Class
- End Code -----------------------------------------------------
Here's the requeststring generated for the multipart form:
- Start requeststring ------------------------------------------
-----------------------------7d4285126106b0
Content-Disposition: form-data; name="condition "
830
-----------------------------7d4285126106b0
Content-Disposition: form-data; name="notes"
good good
-----------------------------7d4285126106b0
Content-Disposition: form-data; name="image_fil e"; filename=""
Content-Type: application/octet-stream
-----------------------------7d4285126106b0
Content-Disposition: form-data; name="image_url "
-----------------------------7d4285126106b0
Content-Disposition: form-data; name="version"
729
-----------------------------7d4285126106b0
Content-Disposition: form-data; name="domain_id "
1856
-----------------------------7d4285126106b0
Content-Disposition: form-data; name="meta_id"
1
-----------------------------7d4285126106b0
Content-Disposition: form-data; name="context_n ame"
w13.1097912464. 0000318444
-----------------------------7d4285126106b0
Content-Disposition: form-data; name="x"
20
-----------------------------7d4285126106b0
Content-Disposition: form-data; name="y"
20
-----------------------------7d4285126106b0--
- End requeststring --------------------------------------------
The requeststring looks right to me. I'm wondering if there's a
header I should set that I'm missing.
Thanks for the help.
--
Greg
----
greg -at- spencersoft -dot- com