HttpRequestMessage
对象只能使用一次;将来尝试使用同一个对象会抛出异常。我正在使用Polly重试一些请求,我正在解决这个问题。我知道如何克隆请求,SO上有很多例子,但我无法弄清楚如何克隆请求并在Polly重试时发送新请求。我怎么能做到这一点?
这些是我的政策,仅供参考。这是一个Xamarin应用程序。我想在网络出现故障时重试几次,如果响应未经授权,我想用保存的凭据重新验证并再次尝试原始请求。
public static PolicyWrap<HttpResponseMessage> RetryPolicy
{
get => WaitAndRetryPolicy.WrapAsync(ReAuthPolicy);
}
private static IAsyncPolicy WaitAndRetryPolicy
{
get => Policy.Handle<WebException>().WaitAndRetryAsync(4, _ => TimeSpan.FromSeconds(2));
}
private static IAsyncPolicy<HttpResponseMessage> ReAuthPolicy
{
get => Policy.HandleResult<HttpResponseMessage>(x => x.StatusCode == HttpStatusCode.Unauthorized)
.RetryAsync((_, __) => CoreService.LogInWithSavedCredsAsync(true));
}
由于HttpRequestMessage
重用,这不起作用,但这正是我想要实现的目标:
var request = new HttpRequestMessage(HttpMethod.Post, "some_endpoint")
{
Content = new StringContent("some content")
};
request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
var policyResponse = await ConnectivityHelper.RetryPolicy
.ExecuteAndCaptureAsync(() => _client.SendAsync(request)).ConfigureAwait(false);
// handle outcome
答案 0 :(得分:0)
如果重复使用 InvalidOperationException
,则抛出 HttpRequestMessage
的代码是 HttpClient
本身内的验证步骤。
private static void CheckRequestMessage(HttpRequestMessage request)
{
if (!request.MarkAsSent())
{
throw new InvalidOperationException(SR.net_http_client_request_already_sent);
}
}
internal bool MarkAsSent()
{
return Interlocked.Exchange(ref sendStatus, messageAlreadySent) == messageNotYetSent;
}
您可以将 polly 重试策略放在 DelegatingHandler
中,这样就可以了。它还提供了一个很好的 SoC(关注点分离)。如果以后您不想不重试或更改重试行为,只需删除 DelegatingHandler
或更改它。注意处理 HttpRequestMessage
和中间 HttpResponseMessage
对象。