Search code examples
vb.netdatagridviewhttpwebrequest

HTML response to DGV cell


In my app, I place several HTTP web requests in order to validate credentials for users on my site. Each request is broke down and sent to a DataGridView table with 3 columns = User, Pass, and response. Depending on the response the same credentials may need to be retried with a new proxy and response updated.

My question is how do I place several HTTP requests at the same time, say 20 and record each on a DGV and monitor the response in case I need to swap the proxy out and run it again.

Here is how I am posting and getting the response.

Function Post(ByVal Data As String, ByVal Proxy As String)
    Dim responseData As String = ""
    Dim Site As String = "example.com"
    Dim request As Net.HttpWebRequest = Net.WebRequest.Create(Site)
    Dim tempCookies As New CookieContainer
    Dim encoding As New ASCIIEncoding()
    Dim byteData As Byte() = encoding.GetBytes(Data)
    Try
        request.UserAgent = "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.2 Safari/537.36"
        request.Accept = "*/*"
        request.CookieContainer = tempCookies
        request.ContentLength = byteData.Length
        request.AllowAutoRedirect = True
        request.KeepAlive = True
        request.Timeout = 60000
        request.Method = "POST"
        If request.Method = "POST" Then
            request.ContentType = "application/x-www-form-urlencoded"
            Dim postByteArray() As Byte = encoding.GetBytes(Data)
            request.ContentLength = postByteArray.Length
            Dim postStream As IO.Stream = request.GetRequestStream()
            postStream.Write(postByteArray, 0, postByteArray.Length)
            postStream.Close()
        End If
        Dim response As Net.HttpWebResponse = request.GetResponse()
        If response.StatusCode = Net.HttpStatusCode.OK Then
            Dim responseStream As IO.StreamReader = _
              New IO.StreamReader(response.GetResponseStream())
            responseData = responseStream.ReadToEnd()
        End If
        response.Close()
    Catch e As Exception
        responseData = "An error occurred: " & e.Message
    End Try
    Post = responseData
End Function

 Dim comboResp As String = (Post("Username=" & User + "&Password=" & Pass & "&submitLogin=Log+In&ReturnUrl=", rndProxy))
    Dim row As String() = New String() {User, Pass, comboResp}
    DataGridView1.Rows.Add(row)

I cannot seem to get the response to show in the cell to start, then have no clue how to call a sub depending on the response of each row.

Closest example of what I am after would be Sentry MBA.


Solution

  • Let's assume you start your process from an Button.Click event handler:

    Imports System.IO
    Imports System.Net
    Imports System.Text
    
    Const COR_E_INVALIDOPERATION As Long = &H80131509
    'A class used to contain all requests data
    Private _AuthenticationObject As AuthObject
    'A List of UserIds as Passwords KeyValue pairs
    Private _CredentialsList As New Dictionary(Of String, String)
    
    Private Async Sub btnTestLogin_Click(sender As Object, e As EventArgs) Handles btnTestLogin.Click
        btnTestLogin.Enabled = False
        'Fill a list of credentials (the use of a Dictionary is just one possible method)
        _CredentialsList.Add("Username1", "Password1")
        _CredentialsList.Add("Username2", "Password2")
        _CredentialsList.Add("Username3", "Password3")
    
        _AuthenticationObject = New AuthObject
        _AuthenticationObject.URL = "http://somesite.com"
    
        _AuthenticationObject.ProxyParameters.Host = "somehostaddress"
        _AuthenticationObject.ProxyParameters.Port = 8080
        'Or simple proxy URI
        '_AuthenticationObject.ProxyParameters.Uri = New Uri("http://someproxyhost")
        _AuthenticationObject.ProxyParameters.BypassLocal = False
        _AuthenticationObject.ProxyParameters.Credentials = New String() {"proxyuserid", "proxypassword"}
    
        'If you don't want to use an Async starter, use this
        'And of course => For Each _item In _result.Result
        'Dim _result As Task(Of List(Of String())) = Task.Run(Function() CheckAuthentication(_AuthenticationObject, True))
        'Task.WaitAny(_result)
    
        Dim _result As List(Of String()) = Await CheckAuthentication(_AuthenticationObject, False)
    
        For Each _item In _result
            DataGridView1.Rows.Add(_item)
        Next
    
        btnTestLogin.Enabled = True
    End Sub
    

    This is a gateway function used to coordinate the sequential requests:

    Public Async Function CheckAuthentication(ByVal _AuthenticationObject As AuthObject, ByVal _useproxy As Boolean) As Task(Of List(Of String()))
        Dim _authresult As List(Of String()) = New List(Of String())
    
        _AuthenticationObject.UseProxy = _useproxy
    
        For Each _item In _CredentialsList
            _AuthenticationObject.LogInData = "Username=" & _item.Key & "&Password=" & _item.Value & "&submitLogin=Log+In&ReturnUrl="
    
            'This an Async version of you original function, plus some editing
            '_AuthenticationObject = Await PostAsync(_AuthenticationObject)
    
            'Test it first using a delay
            Await Task.Delay(1000)
    
            _authresult.Add(New String() {_item.Key,
                                          _item.Value,
                                          If(_AuthenticationObject.StatusCode = HttpStatusCode.OK, "OK", "Failed"),
                                          If(_AuthenticationObject.UseProxy = True, "Proxy", "No Proxy")})
        Next
        Return _authresult
    End Function
    


    This is your original function edited to support a more complex authentication object

    Private Async Function PostAsync(ByVal _PostData As AuthObject) As Task(Of AuthObject)
    
        Dim httpRequest As HttpWebRequest
        Dim _StatusCode As HttpStatusCode
        Dim _Payload As String = String.Empty
        Dim _postparameters As Byte() = Encoding.UTF8.GetBytes(_PostData.LogInData)
    
        Try
            httpRequest = WebRequest.CreateHttp(_PostData.URL)
            httpRequest.Timeout = 10000
            httpRequest.AllowAutoRedirect = False
            httpRequest.ServicePoint.Expect100Continue = False
            httpRequest.AutomaticDecompression = DecompressionMethods.GZip Or DecompressionMethods.Deflate
            httpRequest.UserAgent = "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:56.0) Gecko/20100101 Firefox/56.0"
            httpRequest.Accept = "ext/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"
            httpRequest.Headers.Add(HttpRequestHeader.AcceptEncoding, "gzip, deflate;q=0.8")
    
            httpRequest.Method = WebRequestMethods.Http.Post
            httpRequest.ContentType = "application/x-www-form-urlencoded"
            httpRequest.ContentLength = _postparameters.Length
    
            If _PostData.UseProxy Then
                If Not IsNothing(_PostData.ProxyParameters) Then
                    If (_PostData.ProxyParameters.Host.Length > 0) Then
                        httpRequest.Proxy = New WebProxy(_PostData.ProxyParameters.Host, _PostData.ProxyParameters.Port)
                    Else
                        httpRequest.Proxy = New WebProxy(_PostData.ProxyParameters.Uri, _PostData.ProxyParameters.BypassLocal)
                    End If
                    httpRequest.Proxy.Credentials = New NetworkCredential(_PostData.ProxyParameters.Credentials(0), _
                                                                                            _PostData.ProxyParameters.Credentials(1))
                Else
                    httpRequest.Proxy = WebRequest.GetSystemWebProxy()
                End If
            End If
    
            Using _stream As Stream = Await httpRequest.GetRequestStreamAsync()
                _stream.Write(_postparameters, 0, _postparameters.Length)
            End Using
    
            Using httpResponse As HttpWebResponse = CType(Await httpRequest.GetResponseAsync(), HttpWebResponse)
                Dim _encoding As System.Text.Encoding
    
                _encoding = If(httpResponse.CharacterSet.Length > 0, 
                               Encoding.GetEncoding(httpResponse.CharacterSet), 
                               Encoding.GetEncoding("utf-8"))
    
                Using _stream As Stream = httpResponse.GetResponseStream()
                    _stream.Position = 0
                    Using _reader As StreamReader = New StreamReader(_stream, _encoding)
                        _Payload = _reader.ReadToEnd().Trim()
                    End Using
                End Using
                _StatusCode = httpResponse.StatusCode
            End Using
    
        Catch exW As WebException
            If Not IsNothing(exW.Response) Then
                _StatusCode = CType(exW.Response, HttpWebResponse).StatusCode
            End If
            _Payload = String.Empty
        Catch exS As System.Exception
            _StatusCode = If(exS.HResult = COR_E_INVALIDOPERATION,
                             CType(WebExceptionStatus.ConnectFailure, HttpStatusCode),
                             CType(WebExceptionStatus.RequestCanceled, HttpStatusCode))
            _Payload = String.Empty
        End Try
    
        _PostData.StatusCode = _StatusCode
        _PostData.PayLoad = _Payload
    
        Return _PostData
    
    End Function
    

    These are the Class Objects used:

    Public Class AuthObject
    
        Private _URL As String = String.Empty
        Private _LogInData As String = String.Empty
        Private _UseProxy As Boolean = False
        Private _ProxyParameters As ProxyParameters
        Private _PayLoad As String = String.Empty
        Private _StatusCode As HttpStatusCode
    
        Public Sub New()
            Me._ProxyParameters = New ProxyParameters
        End Sub
    
        Public Property URL() As String
            Get
                Return Me._URL
            End Get
            Set(ByVal value As String)
                Me._URL = value
            End Set
        End Property
    
        Public Property LogInData() As String
            Get
                Return Me._LogInData
            End Get
            Set(ByVal value As String)
                Me._LogInData = value
            End Set
        End Property
    
        Public Property UseProxy() As Boolean
            Get
                Return Me._UseProxy
            End Get
            Set(ByVal value As Boolean)
                Me._UseProxy = value
            End Set
        End Property
    
        Public Property ProxyParameters() As ProxyParameters
            Get
                Return Me._ProxyParameters
            End Get
            Set(ByVal value As ProxyParameters)
                Me._ProxyParameters = value
            End Set
        End Property
    
        Public Property PayLoad() As String
            Get
                Return Me._PayLoad
            End Get
            Set(ByVal value As String)
                Me._PayLoad = value
            End Set
        End Property
    
        Public Property StatusCode() As HttpStatusCode
            Get
                Return Me._StatusCode
            End Get
            Set(ByVal value As HttpStatusCode)
                Me._StatusCode = value
            End Set
        End Property
    
    End Class
    
    Public Class ProxyParameters
    
        Private _Uri As Uri
        Private _Host As String
        Private _Port As Integer
        Private _Credentials As String()
        Private _BypassLocal As Boolean
    
        Public Sub New()
    
        End Sub
    
        Public Property Uri() As Uri
            Get
                Return Me._Uri
            End Get
            Set(ByVal value As Uri)
                Me._Uri = value
            End Set
        End Property
    
        Public Property Host() As String
            Get
                Return Me._Host
            End Get
            Set(ByVal value As String)
                Me._Host = value
            End Set
        End Property
    
        Public Property Port() As Integer
            Get
                Return Me._Port
            End Get
            Set(ByVal value As Integer)
                Me._Port = value
            End Set
        End Property
    
        Public Property Credentials() As String()
            Get
                Return Me._Credentials
            End Get
            Set(ByVal value As String())
                Me._Credentials = value
            End Set
        End Property
    
        Public Property BypassLocal() As Boolean
            Get
                Return Me._BypassLocal
            End Get
            Set(ByVal value As Boolean)
                Me._BypassLocal = value
            End Set
        End Property
    End Class