gpt4 book ai didi

c# - HttpClient - 此实例已经启动

转载 作者:IT王子 更新时间:2023-10-29 04:52:03 25 4
gpt4 key购买 nike

我在我的 api 中使用 http 客户端时遇到了这个异常。

An unhandled exception has occurred while executing the request. System.InvalidOperationException: This instance has already started one or more requests. Properties can only be modified before sending the first request.

然后我注入(inject)了我的服务

services.AddSingleton<HttpClient>()

我认为单例是我最好的bet .我的问题是什么?

编辑:我的用法

class ApiClient
{
private readonly HttpClient _client;
public ApiClient(HttpClient client)
{
_client = client;
}

public async Task<HttpResponseMessage> GetAsync(string uri)
{
_client.BaseAddress = new Uri("http://localhost:5001/");
_client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json");
var response = await _client.GetAsync(uri);

return response;
}
}

最佳答案

这是类的设计HttpClient .Net Core Source .

这里有趣的方法是 CheckDisposedOrStarted()

private void CheckDisposedOrStarted()
{
CheckDisposed();
if (_operationStarted)
{
throw new InvalidOperationException(SR.net_http_operation_started);
}
}

现在在设置属性时会调用它

  1. 基地址
  2. 超时
  3. MaxResponseContentBufferSize

因此,如果您打算重用 HttpClient 实例,您应该设置一个预设这 3 个属性的实例,并且所有使用都必须修改这些属性。

或者,您可以创建工厂或使用简单的 AddTransient(...)。请注意,AddScoped 不是最适合此处的,因为您将在每个请求范围内收到相同的实例。

编辑基本工厂

现在工厂只不过是一个服务,负责为另一个服务提供实例。这是构建HttpClient 的基本工厂,现在意识到这只是最基本的,您可以扩展此工厂以按照您的意愿进行操作,并预设HttpClient 的每个实例。 p>

public interface IHttpClientFactory
{
HttpClient CreateClient();
}

public class HttpClientFactory : IHttpClientFactory
{
static string baseAddress = "http://example.com";

public HttpClient CreateClient()
{
var client = new HttpClient();
SetupClientDefaults(client);
return client;
}

protected virtual void SetupClientDefaults(HttpClient client)
{
client.Timeout = TimeSpan.FromSeconds(30); //set your own timeout.
client.BaseAddress = new Uri(baseAddress);
}
}

现在我为什么要使用和接口(interface)?这是通过使用依赖注入(inject)和 IoC 完成的,我们可以非常轻松地“交换”应用程序的某些部分。现在,我们不再尝试访问 HttpClientFactory,而是访问 IHttpClientFactory

services.AddScoped<IHttpClientFactory, HttpClientFactory>();

现在在您的类、服务或 Controller 中,您将请求工厂接口(interface)并生成一个实例。

public HomeController(IHttpClientFactory httpClientFactory)
{
_httpClientFactory = httpClientFactory;
}

readonly IHttpClientFactory _httpClientFactory;

public IActionResult Index()
{
var client = _httpClientFactory.CreateClient();
//....do your code
return View();
}

这里的关键是。

  1. 工厂负责生成客户端实例并管理默认值。
  2. 我们请求的是接口(interface)而不是实现。这有助于我们保持组件的独立性,并允许进行更加模块化的设计。
  3. 该服务已注册为 Scoped 实例。单例有其用途,但在这种情况下,您更可能需要一个范围内的实例。

Scoped lifetime services are created once per request.

关于c# - HttpClient - 此实例已经启动,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42235677/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com