httpclient此实例已经启动了一个或多个请求。只能在发送第一个请求之前修改属性

发布于 2025-01-27 13:19:02 字数 1531 浏览 4 评论 0原文

我是在.NET Core 2.1中创建一个应用程序,并且正在使用HTTP客户端进行Web请求。问题是我必须发送并行呼叫以节省时间,为此我正在使用task.whenall()方法,但是当我点击此方法时,我会收到错误。“此实例已经启动了一个或多个请求。只能修改属性在发送第一个请求之前,“以前我正在使用RestSharp,一切都很好,但是我想使用HTTPCLEINT。这是代码:

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)
    { ....

这是构造函数:

private readonly HttpClient _httpClient;

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

方法调用:

var user1 = AddUser("[email protected]");
var user2 = AddUser("[email protected]");

await Task.WhenAll(user1, user2);

这是启动配置:

services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();

那我做错了什么?我需要使用addransient()更改addsingleton,还是还有其他问题。在响应后,我还需要使用_client.dispose(),因为我遵循的教程没有使用dispose方法,所以我对此并不感到困惑。

I am creating an application in .Net Core 2.1 and I am using http client for web requests. The issue is I have to send parallel calls to save time and for that I am using Task.WhenAll() method but when I hit this method I get the error "This instance has already started one or more requests. Properties can only be modified before sending the first request" Previously I was using RestSharp and everything was fine but I want to use httpclient. Here is the code:

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)
    { ....

Here is the constructor:

private readonly HttpClient _httpClient;

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

Method calling:

var user1 = AddUser("[email protected]");
var user2 = AddUser("[email protected]");

await Task.WhenAll(user1, user2);

and here is the startup configuation:

services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();

So what am I doing wrong? Do I need to change AddSingleton with AddTransient() or is there any other issue. One more question do I need to use _client.Dispose() after the response because the tutorial which I followed didn't use dispose method so I am little confused in that.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

晨与橙与城 2025-02-03 13:19:02

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替换“ {...}”

HttpClient.DefaultRequestHeaders (and BaseAddress) should only be set once, before you make any requests. HttpClient is only safe to use as a singleton if you don't modify it once it's in use.

Rather than setting DefaultRequestHeaders, set the headers on each HttpRequestMessage you are sending.

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);

Replace "{...}" with your JSON.

独木成林 2025-02-03 13:19:02

也许我的两分钱会帮助某人。

调试应用程序时,我会在刷新页面时遇到此问题。

我当时正在使用单身人士,但是每个刷新都试图设置基础地址。因此,我只是将其包装在检查中,以查看是否已经设置了基本地址。

对我来说,即使已经设定了Baseaddress,它还是试图设定BaseadDress。您不能使用httpclient做到这一点。

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

Maybe my two cents will help someone.

I ran into this issue when refreshing the page when debugging the application.

I was using a singleton, but each refresh, it was trying to set the base address. So I just wrapped it in a check to see if the base address had already been set.

The issue for me was, it was trying to set the baseAddress, even though it was already set. You can't do this with a httpClient.

if (_httpClient.BaseAddress == null)
{
    _httpClient.BaseAddress = new Uri(baseAddress);
}
德意的啸 2025-02-03 13:19:02

该问题是由与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
}

The issue is caused by resetting BaseAddress and headers for the same instance of the httpclient.

I tried

if (_httpClient.BaseAddress == null) 

but I am not keen on this.

In my opinion, a better soloution is to use the httpclientFactory. This will terminate and garbage collect the instance of the httpclient after its use.

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
}

有木有妳兜一样 2025-02-03 13:19:02

当您在消息中添加请求URL和标头时,它可以很好地工作,而不是在客户端上。因此,最好不要分配给baseaddress或header defaultrequestheaders如果您将它们用于许多请求。

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

httpClient.SendAsync(msg);

It Works well when you add the request url and the headers at the message, rather than at the client. So better not to assign to BaseAddress Or the header DefaultRequestHeaders if you will use them for many requests.

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

httpClient.SendAsync(msg);
所有深爱都是秘密 2025-02-03 13:19:02

这个问题现在已经有时了,但是,我只是想到这个问题,试图在Parallel.ForeachAsync循环中调用客户端。

根据答案的解决, Mali tbt

JUSTED ihtttpclientfactory在每次迭代中创建客户端实例。

适用于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)
    { ....

This question has sometime now but, I just hit this issue trying to call a client within a Parallel.ForEachAsync loop.

Solved based on the answer by Mali Tbt

Just injected IHttpClientFactory in the constructor, and used it to create a client instances on each iteration.

Applying to OP case:

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)
    { ....
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文