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

.NET Framework 4.7.2 WinForms项目HttpClientFactory无法正常使用求助

问题:.NET 4.7.2 WinForms中使用HttpClientFactory触发空引用错误

我查遍了能找到的HttpClientFactory资料,试了几天都没解决,来求助。我想在.NET 4.7.2 WinForms项目里给REST API客户端实现HttpClientFactory,尝试了类型化客户端和命名客户端两种方式,但每次实例化都会触发空引用错误,以下是我的操作步骤:

类型化客户端实现

我创建了如下类:

Imports System.Net.Http
Imports Microsoft.Extensions.Http
Imports Microsoft.Extensions.DependencyInjection

Public Class TypedCustomHTTPClient

    Public Property _Client() As HttpClient
    Public Sub New(ByVal httpClient As HttpClient)
        'httpClient.BaseAddress = New Uri("https://api.google.com/")
        httpClient.DefaultRequestHeaders.Add("Accept", "application/json")
        httpClient.DefaultRequestHeaders.Add("User-Agent", "HttpClientFactory-Sample")
        _Client = httpClient

    End Sub


End Class

注册客户端

在项目的Main子程序中,我注册了类型化客户端和命名客户端(不确定方式是否正确):

Imports Microsoft.Extensions.DependencyInjection
Imports Microsoft.Extensions.Hosting
Imports Microsoft.Extensions.Http
Imports Polly


Module MainModule


    Public Sub Main()


        Dim seviceColl As New ServiceCollection

        '--------注册命名HttpClient
        seviceColl.AddHttpClient("s2sfHTTPClient", Sub(c)
                                                            'c.BaseAddress = New Uri("https://api.google.com/")
                                                            c.DefaultRequestHeaders.Add("Accept", "application/json")
                                                        End Sub).AddPolicyHandler(PolHolder.httpRetryWithReauthorizationPolicy())
        seviceColl.AddHttpClient("GitHub", Sub(httpClient)
                                                    httpClient.BaseAddress = New Uri("https://api.github.com/")

                                                    ' using Microsoft.Net.Http.Headers;
                                                    ' GitHub API需要两个请求头
                                                    ''httpClient.DefaultRequestHeaders.Add(HeaderNames.Accept, "application/vnd.github.v3+json")
                                                    ''httpClient.DefaultRequestHeaders.Add(HeaderNames.UserAgent, "HttpRequestsSample")
                                                End Sub)


       '注册类型化HttpClient

        seviceColl.AddHttpClient(Of TypedCustomHTTPClient)().SetHandlerLifetime(TimeSpan.FromMinutes(5)).AddPolicyHandler(PolHolder.httpRetryWithReauthorizationPolicy()) '设置生命周期为5分钟
       
        '构建服务提供器
        Dim serviceprovider = servicecoll.BuildServiceProvider
        '
        Application.Run(New Form1()) ''//这里用你的主窗体
    End Sub

End Module

使用时出错

当我尝试使用类型化客户端或者通过CreateClient方法使用命名客户端时,在CreateClient行出现空引用错误:

Private Property _httpClientFactory As IHttpClientFactory
Public Function TestQuery2(ByVal soqlQuery As String) As String
        Dim customclient = _httpClientFactory.CreateClient("s2sfHTTPClient")
        'Using customclient._Client '= New HttpClient()
        '
        Dim restRequest As String = InstanceUrl + API_ENDPOINT & "query/?q=" & soqlQuery
            Dim request = New HttpRequestMessage(HttpMethod.[Get], restRequest)
            request.Headers.Add("Authorization", "Bearer " & AuthToken)
            request.Headers.Accept.Add(New MediaTypeWithQualityHeaderValue("application/json"))
            request.Headers.Add("X-PrettyPrint", "1")
        Dim response = customclient.SendAsync(request).Result
        Return response.Content.ReadAsStringAsync().Result
        'End Using
    End Function

请问我哪里操作错了?


解决方案

核心问题

你定义的_httpClientFactory只是一个私有属性,没有从服务容器中获取实例,所以它的值是Nothing(VB.NET的空引用),调用CreateClient自然会报错。

具体修复步骤

  1. 全局保存服务容器实例
    在Main模块中,构建完服务提供器后,把它保存到全局可访问的变量中:

    Module MainModule
        Public Shared ServiceProvider As IServiceProvider
    
        Public Sub Main()
            Dim serviceColl As New ServiceCollection
            '... 你的HttpClient注册代码 ...
            ServiceProvider = serviceColl.BuildServiceProvider
            Application.Run(New Form1())
        End Sub
    End Module
    

    注意:修正了你代码中seviceColl和servicecoll的拼写不一致问题,避免潜在报错

  2. 在窗体中获取IHttpClientFactory实例
    在Form1的构造函数中,从全局服务容器获取IHttpClientFactory:

    Public Class Form1
        Private _httpClientFactory As IHttpClientFactory
    
        Public Sub New()
            InitializeComponent()
            '从全局服务容器获取实例
            _httpClientFactory = MainModule.ServiceProvider.GetService(Of IHttpClientFactory)()
        End Sub
    
        '你的TestQuery2方法放在这里
        Public Function TestQuery2(ByVal soqlQuery As String) As String
            '现在_httpClientFactory不为空
            Dim customclient = _httpClientFactory.CreateClient("s2sfHTTPClient")
            '... 剩余代码不变 ...
        End Function
    End Class
    
  3. 更规范的依赖注入方式
    如果你想严格遵循依赖注入规范,可以让Form1通过构造函数接收IHttpClientFactory,然后从服务容器解析窗体:

    '修改Main模块代码
    Public Sub Main()
        Dim serviceColl As New ServiceCollection
        '... HttpClient注册代码 ...
        '注册Form1,声明它依赖IHttpClientFactory
        serviceColl.AddTransient(Of Form1)()
        
        ServiceProvider = serviceColl.BuildServiceProvider
        '从服务容器解析Form1,而非直接New
        Dim mainForm = ServiceProvider.GetService(Of Form1)()
        Application.Run(mainForm)
    End Module
    
    '修改Form1构造函数
    Public Class Form1
        Private _httpClientFactory As IHttpClientFactory
    
        '构造函数注入IHttpClientFactory
        Public Sub New(httpClientFactory As IHttpClientFactory)
            InitializeComponent()
            _httpClientFactory = httpClientFactory
        End Sub
    
        'TestQuery2方法不变
    End Class
    

额外优化建议

  • 不要用.Result阻塞异步方法,WinForms中建议使用Async/Await避免UI线程卡顿:
    Public Async Function TestQuery2(ByVal soqlQuery As String) As Task(Of String)
         Dim customclient = _httpClientFactory.CreateClient("s2sfHTTPClient")
         Dim restRequest As String = InstanceUrl + API_ENDPOINT & "query/?q=" & soqlQuery
         Dim request = New HttpRequestMessage(HttpMethod.[Get], restRequest)
         request.Headers.Add("Authorization", "Bearer " & AuthToken)
         request.Headers.Accept.Add(New MediaTypeWithQualityHeaderValue("application/json"))
         request.Headers.Add("X-PrettyPrint", "1")
         Dim response = Await customclient.SendAsync(request)
         Return Await response.Content.ReadAsStringAsync()
     End Function
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 03:25:47