MS Access中的异步HTTP POST请求

时间:2016-09-08 17:35:10

标签: rest ms-access asynchronous access-vba

我在访问项目中使用Asynchronous HTTP Request Class。 作者只添加了GET。因此,我试图在课程中添加POST功能。

我将以下代码添加到Class

Public Sub PostRequest(serviceURL As Variant, Optional apiBody As String)
On Error GoTo Sub_Err

    Set m_oXmlHttp = New MSXML2.XMLHTTP60

    m_oXmlHttp.Open "POST", serviceURL, True

    'this sets the onreadystatechange call back to an instance of this object
    'which causes the default method HandleResponse to be called when the ready
    'state changes
    m_oXmlHttp.onreadystatechange = Me
    m_oXmlHttp.send apiBody


'Error Catching
Sub_Exit:
    Exit Sub
Sub_Err:
    MsgBox Error$
    Resume Sub_Exit
End Sub

在调用上述子时,我在我的表格中起诉以下代码。

Private WithEvents oAHlogin As clsAsyncHTTP  


Private Sub PostLoginData()
    Dim apiURL, apiBody As String
    apiURL = "myurl"
    apiBody = "mybody"

    Set oAHlogin = New clsAsyncHTTP                                     
    oAHlogin.PostRequest apiURL, apiBody       '*This is where the execution stops*.

End Sub


Private Sub oAHlogin_ResponseReady(ByVal ready As Boolean)  
    If ready Then
        Debug.Print oAHlogin.GetReponseText
    End If
End Sub

见上面一行,我提到过这是执行停止的地方。任何帮助表示赞赏。我对编程比较陌生。我错误地称这个子?括号丢失了吗?

我能够正确执行GET,如班级作者所示。我添加的POST不起作用

编辑1 :回复Gord Thompson,使这个Q重复:Question # 1463635用于ASP,我要求VBA中的Access是完全不同的东西。

编辑2 :我在Access项目中添加了以下引用。

References

3 个答案:

答案 0 :(得分:2)

如果你是"发布或" GET" ing并不重要。在实现这一目标之前,您需要了解的一些事情。

  1. MS Access vba是单线程的,因此除了使用外部DLL或几乎没有可用的黑客外,不能执行并行执行或线程执行。
  2. 为了实现"异步HTTP请求"或者换句话说,要告诉VBA不要等待HTTP回复,你需要对回调类进行一些修改。
  3. 流程如下:

    1. 创建您的HTTP请求
    2. 添加所有参数及其他所有参数
    3. 分配回调函数
    4. 使用[varAsyn] = True
    5. 发送/打开MSXML2.XMLHTTP
    6. 让vba继续处理其他代码,一旦收到http回复,回调类将触发一个事件。
    7. 重要:回调函数将是一个类,该类需要hack。

      [第1步:准备回调课程]

      在您的VBA中创建新的Class模块,使用以下代码将其命名为HTTP_HANDLER_CLASS:

      Option Compare Database
      Option Explicit
      Dim m_xmlHttp As MSXML2.XMLHTTP
      
      Public Sub Initialize(ByRef xmlHttpRequest As MSXML2.XMLHTTP)
         Set m_xmlHttp = xmlHttpRequest
      End Sub
      
      Sub OnReadyStateChange()
         If m_xmlHttp.ReadyState = 4 Then
            If m_xmlHttp.status = 200 Then
               Debug.Print m_xmlHttp.responseText
            Else
               'Error happened
           End If
         End If
      End Sub
      

      [第2步:修改/黑客回拨课程]

      1. 现在导出该类并将其作为HTTP_HANDLER_CLASS.cls
      2. 保存在桌面上
      3. 在任何文本编辑工具中打开导出的类
      4. 添加:"属性OnReadyStateChange.VB_UserMemId = 0"就在sub" Sub OnReadyStateChange()" http://www.bootstraptoggle.com/
      5. 之下
      6. 返回VBA并导入课程(覆盖或删除现有的)
      7. 这将使OnReadyStateChange()成为默认函数,这是我们想要的,到目前为止,您已经完成了最重要的部分:

        [步骤3:发送请求此示例使用SOAP操作] 假设一个Web服务" CallingServiceName"您可以使用iEmail,iPassword两个参数,如果登录成功与否则返回一个字符串。

        Module level variable:
        Public xmlHttpRequest As MSXML2.XMLHTTP
        
        Public Function HTTP_TEST()
        
        On Error GoTo FailedState
        If Not xmlHttpRequest Is Nothing Then Set xmlHttpRequest = Nothing
        
        Dim MyXmlHttpHandler As HTTP_HANDLER_CLASS 'our hacked call back class
        Set xmlHttpRequest = New MSXML2.XMLHTTP
        
        Dim sURL As String
        Dim sEnv As String
        
        
        sURL = "http://mydomain.co.uk/mywebsite/myservices.asmx?op=CallingServiceName"
        
        sEnv = "<?xml version=""1.0"" encoding=""utf-8""?>"
        sEnv = sEnv & "<soap:Envelope xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema"" xmlns:soap=""http://schemas.xmlsoap.org/soap/envelope/"">"
        sEnv = sEnv & "  <soap:Body>"
        sEnv = sEnv & "    <CallingServiceName xmlns=""http://mydomain.co.uk/"">"
        sEnv = sEnv & "      <iEmail>username</iEmail>"
        sEnv = sEnv & "      <iPassword>mypassword</iPassword>"
        sEnv = sEnv & "    </CallingServiceName>"
        sEnv = sEnv & "  </soap:Body>"
        sEnv = sEnv & "</soap:Envelope>"
        
        ' Now create an instance of our call-back class
        Set MyXmlHttpHandler = New HTTP_HANDLER_CLASS 
        MyXmlHttpHandler.Initialize xmlHttpRequest
        
           ' Now attach the call-back class to our request, so whenever the request's state changes, callback classs default function will fire.
            xmlHttpRequest.OnReadyStateChange = MyXmlHttpHandler
        
           ' seal the envelop and send it
            xmlHttpRequest.Open "Post", sURL, True ' here set varAsyn=true 
            xmlHttpRequest.setRequestHeader "Host", "mydomain.co.uk"
            xmlHttpRequest.setRequestHeader "Content-Type", "text/xml; charset=utf-8"
            xmlHttpRequest.setRequestHeader "soapAction", "http://mydomain.co.uk/CallingServiceName"
            xmlHttpRequest.Send sEnv
        
            Debug.Print "Controller finished job" ' this is for you to realize vba will continue to work, the http result will be fired whenever the onstateChanges.
        
           Exit Function
        
        FailedState:
            'MsgBox err.Number & ": " & err.description
        End Function
        

        <强> [结果] enter image description here

        哦,顺便说一下,Microsoft XML v3就足够了。 Result

        上面的示例使用SOAP版本,但您可以使用任何方法。如果这有帮助,请告诉我。

答案 1 :(得分:1)

您需要设置标题 - 在致电.Send

之前,您至少需要将此行添加到您的课程中
m_oXmlHttp.setRequestHeader "Content-Type", "application/x-www-form-urlencoded"

答案 2 :(得分:1)

在更多地讨论代码之后,我发现在进行异步POST时,在我之前标记为重复的问题的答案中,代码需要进行一些微妙的更改。这是最终为我工作的代码:

' VBA project reference required:
'     Microsoft XML, v6.0

Dim postData As String
postData = "word1=hello&word2=world"

Dim objXmlHttp As New MSXML2.XMLHTTP
objXmlHttp.Open "POST", "http://localhost:8080/postTest.php", True
objXmlHttp.setRequestHeader "Content-Type", "application/x-www-form-urlencoded"
objXmlHttp.setRequestHeader "Content-Length", Len(postData)
objXmlHttp.send postData
Set objXmlHttp = Nothing