asp.net Httpclient此示例已启动一个或多个请求,只能在发送第一个请求之前修改属性

cidc1ykv  于 2023-06-07  发布在  .NET
关注(0)|答案(5)|浏览(272)

我正在.Net Core 2.1中创建一个应用程序,并使用HTTP客户端进行Web请求。问题是我必须发送并行调用以保存时间,为此我使用Task.WhenAll()方法,但当我点击此方法时,我得到错误“此示例已启动一个或多个请求。属性只能在发送第一个请求之前修改“以前我使用RestSharp,一切都很好,但我想使用httpclient。下面是代码:

public async Task<User> AddUser(string email)
{
    var url = "user/";
    _client.BaseAddress = new Uri("https://myWeb.com/");
    _client.DefaultRequestHeaders.Accept.Clear();
    _client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(Constants."application/json"));
    _client.DefaultRequestHeaders.Add("Authorization", "Bearer " + token);
    var json = new {email = email }
    var response = await _client.PostAsJsonAsync(url,json);
    if (response .IsSuccessStatusCode)
    { ....

下面是constructor:

private readonly HttpClient _httpClient;

public UserRepository(HttpClient httpClient)
{         
    _httpClient = httpClient;
}

方法调用:

var user1 = AddUser("user@user.com");
var user2 = AddUser("test@test.com");

await Task.WhenAll(user1, user2);

下面是启动配置:

services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();

我做错了什么?我是否需要使用AddTransient()更改AddSingleton,或者是否存在其他问题。还有一个问题,我是否需要在响应后使用_client.Dispose(),因为我遵循的教程没有使用dispose方法,所以我有点困惑。

u4dcyp6a

u4dcyp6a1#

HttpClient.DefaultRequestHeaders(和BaseAddress)只应在发出任何请求之前设置一次。HttpClient只有在使用后不修改它的情况下才能安全地用作单例。
与其设置DefaultRequestHeaders,不如在您发送的每个HttpRequestMessage上设置头。

var request = new HttpRequestMessage(HttpMethod.Post, url);
request.Headers.Accept.Clear();
request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token);
request.Content = new StringContent("{...}", Encoding.UTF8, "application/json");
var response = await _client.SendAsync(request, CancellationToken.None);

"{...}"替换为JSON。

b4lqfgs4

b4lqfgs42#

也许我的两分钱能帮到别人。
我在调试应用程序时刷新页面时遇到了这个问题。
我使用的是单例,但每次刷新,它都试图设置基址。所以我只是把它 Package 在一个检查中,看看是否已经设置了基址。
对我来说,问题是,它试图设置baseAddress,尽管它已经设置好了。你不能用httpClient来做这件事。

if (_httpClient.BaseAddress == null)
{
    _httpClient.BaseAddress = new Uri(baseAddress);
}
nue99wik

nue99wik3#

此问题是由于重置同一httpclient示例的BaseAddress和标头而导致的。
我尽力了

if (_httpClient.BaseAddress == null)

但我不喜欢这个
在我看来,一个更好的解决方案是使用httpclientFactory。这将在httpclient示例使用后终止并对其进行垃圾收集。

private readonly IHttpClientFactory _httpClientFactory;
public Foo (IHttpClientFactory httpClientFactory) 
{
_httpClientFactory = httpClientFactory;
}
public  httpresponse Bar ()
{
_httpClient = _httpClientFactory.CreateClient(command.ClientId);

using var response = await _httpclient.PostAsync(uri,content);
return response;
// here as there is no more reference to the _httpclient, the garbage collector will clean 
// up the _httpclient and release that instance. Next time the method is called a new 
// instance of the _httpclient is created
}
ufj5ltwl

ufj5ltwl4#

当您在消息中而不是在客户端添加请求URL和头时,它工作得很好。所以最好不要分配给BaseAddress或头DefaultRequestHeaders,如果你将使用它们的许多请求。

HttpRequestMessage msg = new HttpRequestMessage {
    Method = HttpMethod.Put,
    RequestUri = new Uri(url),
    Headers = httpRequestHeaders;
};

httpClient.SendAsync(msg);
mpgws1up

mpgws1up5#

这个问题已经有一段时间了,但是,我只是在尝试在Parallel.ForEachAsync循环中调用客户端时遇到了这个问题。
根据Mali Tbt的答案求解
在构造函数中注入IHttpClientFactory,并在每次迭代中使用它创建客户端示例。
适用于OP病例:

private readonly IHttpClientFactory _clientFactory;

// Constructor
public UserRepository(IHttpClientFactory httpClientFactory)
  {         
      _clientFactory = httpClientFactory;
  }

// calling method
public async Task<User> AddUser(string email)
{
    var url = "user/";
    var client = _clientFactory.CreateClient("UserRepository");

    client.BaseAddress = new Uri("https://myWeb.com/");
    client.DefaultRequestHeaders.Accept.Clear();
    client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(Constants."application/json"));
    client.DefaultRequestHeaders.Add("Authorization", "Bearer " + token);
    var json = new {email = email }
    var response = await client.PostAsJsonAsync(url,json);
    if (response .IsSuccessStatusCode)
    { ....

相关问题