You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用HttpClient从内部WebApi获取数据失败,求排查解决

问题:调用内部WebAPI获取数据失败,后续出现空引用异常

我尝试从内部开发的WebApi获取数据,但一直未成功。该API通过Post请求返回数据,请求体包含复杂筛选条件。此前我曾成功通过Post请求向该API写入数据,但获取数据时遇到瓶颈。

初始请求代码

Public Async Function Request(ByVal client As HttpClient, ByVal content As String) As Task

      Dim buffer = System.Text.Encoding.UTF8.GetBytes(content)
      Dim byteContent = New ByteArrayContent(buffer)
      byteContent.Headers.ContentType = New MediaTypeHeaderValue("application/json")

      Dim response = Await client.PostAsync(client.BaseAddress, byteContent)
      Dim result As String = response.Content.ReadAsStringAsync().Result
      _result = result

 End Function

为便于使用MSTest测试,结果存储在类变量中。该函数应返回JSON数组,但未返回任何内容,也无错误提示。

对应的MSTest测试方法

<TestMethod()> Public Sub ShouldSuccessfullyInterrodateTheSpenHapi()

      Dim da = New SPEN.ODSDataPackagerService
      Dim crit As New HttpCriterion
      Dim stopped As Boolean
      Dim jsonString As String = Nothing

      crit.StartTime = "2022-11-03T00:00:00"
      crit.EndTime = "2022-11-03T00:30:00"
      crit.Interval = "30m"
      crit.TagAttribute = "InstrumentTag"
      crit.TagFilter = "confidential"
      crit.Delimiter = "~"
      crit.ServerName = "SPRODA"

      '序列化对象为JSON
      jsonString = da.GetCriteriaJson(crit)

      Try
           da.InitialiseSettings()
           da.Request(da.Clients(0), jsonString)
           Debug.Print(da.Result)
           Assert.IsTrue(True)
      Catch ex As Exception
           Assert.IsTrue(False)
      End Try

 End Sub

请问我忽略了什么?


编辑:出现空引用异常

经过进一步尝试,现在至少能获取到错误信息,代码如下:

Public Async Function GetVoltagesFromPI(ByVal client As HttpClient, ByVal content As String) As Task(Of PIItemList)
      Dim piItems As PIItemList = New PIItemList
      Dim buffer = System.Text.Encoding.UTF8.GetBytes(content)
      Dim byteContent = New ByteArrayContent(buffer)
      byteContent.Headers.ContentType = New MediaTypeHeaderValue("application/json")

      Try
           Dim response As New HttpResponseMessage
           response = Await client.PostAsync(client.BaseAddress, byteContent)

           If response.IsSuccessStatusCode Then
                _result = New PIItemList
                _result = JsonConvert.DeserializeObject(response.Content.ReadAsStringAsync().Result)
           End If
      Catch ex As Exception
           Throw
      Finally

      End Try

 End Function

函数在以下代码处报错:

response = Await client.PostAsync(client.BaseAddress, byteContent)

错误信息:

System.NullReferenceException: 'Object variable or With block 

我认为代码逻辑应该没问题,但显然存在实现缺陷,仍未找到解决方案。


问题分析与解决建议

  • 异步调用未等待:初始测试方法中调用da.Request(da.Clients(0), jsonString)时,未用Await等待异步方法完成,导致测试方法可能在请求结束前就读取da.Result,自然拿不到数据。MSTest支持异步测试,需将测试方法改为Async Sub,并使用Await等待请求完成。
  • 空引用异常根源:报错行的空引用大概率是client或client.BaseAddress为Nothing。检查da.InitialiseSettings()是否正确初始化了da.Clients(0),确保HttpClient实例已创建且BaseAddress已设置有效值。
  • 同步阻塞异步方法:代码中使用response.Content.ReadAsStringAsync().Result会阻塞线程,易引发死锁,应改为Await response.Content.ReadAsStringAsync()。
  • 缺失错误状态校验:初始代码未检查响应状态码,即使API返回400、500等错误也不会触发异常,无法知晓失败原因。需添加response.EnsureSuccessStatusCode()抛出HTTP错误异常。
  • 反序列化类型缺失:编辑后的代码中JsonConvert.DeserializeObject未指定目标类型,应写成JsonConvert.DeserializeObject(Of PIItemList)(Await response.Content.ReadAsStringAsync()),才能正确反序列化为PIItemList对象。

修改后的测试方法示例

<TestMethod()> Public Async Sub ShouldSuccessfullyInterrodateTheSpenHapi()

      Dim da = New SPEN.ODSDataPackagerService
      Dim crit As New HttpCriterion
      Dim jsonString As String = Nothing

      crit.StartTime = "2022-11-03T00:00:00"
      crit.EndTime = "2022-11-03T00:30:00"
      crit.Interval = "30m"
      crit.TagAttribute = "InstrumentTag"
      crit.TagFilter = "confidential"
      crit.Delimiter = "~"
      crit.ServerName = "SPRODA"

      jsonString = da.GetCriteriaJson(crit)

      Try
           da.InitialiseSettings()
           ' 等待异步请求完成
           Await da.Request(da.Clients(0), jsonString)
           Debug.Print(da.Result)
           Assert.IsNotNull(da.Result)
      Catch ex As Exception
           Assert.Fail($"请求失败: {ex.Message}")
      End Try

 End Sub

修改后的请求方法示例

Public Async Function Request(ByVal client As HttpClient, ByVal content As String) As Task

      If client Is Nothing OrElse client.BaseAddress Is Nothing Then
          Throw New ArgumentNullException("HttpClient实例或BaseAddress未初始化")
      End If

      ' 直接使用StringContent简化代码
      Dim byteContent = New StringContent(content, Encoding.UTF8, "application/json")

      Dim response = Await client.PostAsync(client.BaseAddress, byteContent)
      ' 校验HTTP请求状态,失败则抛出异常
      response.EnsureSuccessStatusCode()
      Dim result As String = Await response.Content.ReadAsStringAsync()
      _result = result

 End Function

内容的提问来源于stack exchange,提问作者Paul Johnson

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 14:10:28