错误“请求消息已发送。无法多次发送相同的请求消息'

Sho*_*ore 0 c#

这就是我正在尝试的:

public static async Task<HttpResponseMessage> post(string specificUrl, string token, StringContent inputData) // specificUrl like "user/" at the end "/"
{
    var policy = Policy
        .Handle<Exception>()
        .OrResult<HttpResponseMessage>(res => !res.IsSuccessStatusCode)
        .RetryAsync(3);

    string fullUrl = baseUrl + specificUrl;
    using (var requestMessage = new HttpRequestMessage(HttpMethod.Post, fullUrl))
    {
        requestMessage.Content = inputData;
        requestMessage.Headers.Add("access_token", token);
        //HttpResponseMessage res = await client.SendAsync(requestMessage).ConfigureAwait(false);
        HttpResponseMessage res = await policy.ExecuteAsync(() => client.SendAsync(requestMessage)).ConfigureAwait(false);
        return res;
    }
}
Run Code Online (Sandbox Code Playgroud)

一旦代码到达 waitAndRetryPolicy 并等待所需的时间,我就会收到以下错误:

System.InvalidOperationException:'请求消息已发送。无法多次发送相同的请求消息。

AAA*_*ddd 6

简而言之,您不能重用HttpRequestMessage. 它解决了一大堆无法在级别上缓解的问题(例如流媒体内容等)SendAsync

您需要HttpRequestMessageExecuteAsynclambda 中创建或重新创建,或者更好的是,使用IHttpClientFactory然后在该级别使用Polly 。HttpClientBuilder

重新创建的示例HttpRequestMessage

return await policy.ExecuteAsync(() =>
{
   // Note the 'using' here is a superfluous, but good practice
   using var requestMessage = new HttpRequestMessage(HttpMethod.Post, fullUrl)
   {
       Content = new StringContent(aString)
   };

   requestMessage.Headers.Add("access_token", token);
   return client.SendAsync(requestMessage);

}).ConfigureAwait(false);
Run Code Online (Sandbox Code Playgroud)

但是,理想情况下,您应该HttpClientFactory与类型化或命名的客户端一起使用。

给定一个类型化的客户端

public class MyTypedClient
{
   private readonly HttpClient _client;

   public MyTypedClient(HttpClient client) => _client = client;
   public async Task<HttpResponseMessage> MyCall(string inputData)
   {
      using var requestMessage = new HttpRequestMessage(HttpMethod.Post, "/someRoute") { Content = new StringContent(inputData) };
      var result = await _client.SendAsync(requestMessage);
      result.EnsureSuccessStatusCode();
      return result;
   }
}
Run Code Online (Sandbox Code Playgroud)

依赖注入(DI) 用法示例

private static readonly AsyncRetryPolicy<HttpResponseMessage> retryPolicy
   = HttpPolicyExtensions
      .HandleTransientHttpError() // Whatever??
      .RetryAsync(3);

public static void Main()
{
   var serviceCollection = new ServiceCollection();

   serviceCollection
      .AddHttpClient<MyTypedClient>(ClientConfiguration)
      .AddPolicyHandler(retryPolicy);

   var provider = serviceCollection.BuildServiceProvider();
   // Whatever
}

private static void ClientConfiguration(HttpClient client)
{
   client.BaseAddress = new Uri("http://bob.com");
   /// blah blah blah
}
Run Code Online (Sandbox Code Playgroud)

注意:这并不是关于依赖注入(DI)、Polly 或其他任何内容(例如世界最佳实践、如何在该级别使用身份验证AddHttpClient等)的教程。这只是一个示例用例,说明它如何适合共同利用政策

掘金队

  • Microsoft.Extensions.DependencyInjection
  • Microsoft.Extensions.Http
  • Microsoft.Extensions.Http.Polly
  • 波莉

其他资源