HttpClient重试后无法发送第二个请求

本文关键字:第二个 请求 重试 HttpClient | 更新日期: 2023-09-27 18:13:26

最初我想发送没有客户端证书的第一个请求,如果错误是"身份验证错误",那么我想重新发送带有附加证书的请求。第一个代码是

HttpStringContent ehttpContent = new HttpStringContent(content);
HttpRequestMessage req2 = new HttpRequestMessage(method, resourceUri);
req2.Headers.Add("SOAPAction", soapAction);
req2.Content = ehttpContent;
req2.Content.Headers.ContentType = HttpMediaTypeHeaderValue.Parse("text/xml; charset=utf-8");
bool retry= await FirstLoginAttempt(...);
if( retry) {
 newHttpClient = new HttpClient(baseFilter2);
 try
 {
     cts.CancelAfter(Constants.HttpTimeOut);
     System.Diagnostics.Debug.WriteLine(ehttpContent);
     eresponse = await newHttpClient.SendRequestAsync(req2).AsTask(cts.Token);
     if (cts != null)
     {
        cts.Dispose();
        cts = null;
 } catch { ... }

}

前面的代码调用FirstLoginAttempt,它可能会因证书错误而失败。它返回true或false,然后前面的代码尝试发送一个带有证书的新httpClient。

public static async Task<bool> FirstLoginAttempt() {
httpClient = new HttpClient();
try
{
    cts.CancelAfter(Constants.HttpTimeOut);
    var operation = httpClient.SendRequestAsync(ereq).AsTask(cts.Token);
    eresponse = await operation;
    if (cts != null) { cts.Dispose(); cts = null; }
}
catch (TaskCanceledException e)
{
  if (cts != null) { cts.Dispose(); cts = null; }
   throw e;
}
catch (Exception exx)
{ ... }
}

当第一次登录尝试返回true以便再次尝试时,第二个httpclient(具有相同的内容)失败,并且异常表示我不能发送相同的请求两次。这可能意味着之前的操作还没有完成?我该如何解决我的问题?我能否以某种方式确保第一个请求生命周期结束以便重试?

我的环境是Windows Phone 8.1

Update # 1。在使用lambda

之后

StackTrace = " at System.Runtime.CompilerServices.TaskAwaiter. "ThrowForNonSuccess(Task Task)'r'n atSystem.Runtime.CompilerServices.TaskAwaiter。HandleNonSuccessAndDebuggerNotification(Task Task)'r'n at System.Runtime.CompilerServices.TaskAwaiter ' 1.GetResult()'r'n…Message = "Exception from HRESULT: 0x80072EFD" (Throw for non - success)

在堆栈跟踪上方……

 Func<HttpRequestMessage> httpRequestCreator = () =>
                {
     HttpStringContent ehttpContent = new HttpStringContent(content);
     var req = new HttpRequestMessage(method, resourceUri)
     {
         Content = ehttpContent
     };
     req.Headers.Add("SOAPAction", soapAction);
     req.Content.Headers.ContentType = HttpMediaTypeHeaderValue.Parse("text/xml; charset=utf-8");
     return req;
};
if (cts != null) { cts.Dispose(); cts = null; }
cts = new System.Threading.CancellationTokenSource();
newHttpClient = new HttpClient();
try
{
    cts.CancelAfter(Constants.HttpTimeOut);
    eresponse = await newHttpClient.SendRequestAsync(httpRequestCreator()).AsTask(cts.Token);
    if (cts != null) { cts.Dispose(); cts = null; }
}
catch (TaskCanceledException e
{
    if (cts != null) { cts.Dispose(); cts = null; }
    throw e;
}
catch (Exception exx)
{
    exception2 = exx;
    ...
    ...
}

HttpClient重试后无法发送第二个请求

问题在于您正在为两个请求重新使用您的HttpRequestMessage,这是您无法做到的。相反,您可以为想要发送的每条消息创建一个新请求。处理这个问题的一种方法是创建一个每次返回一个新实例的Func<HttpRequestMessage>:

Func<HttpRequestMessage> httpRequestCreator = () => 
{
     var request = new HttpRequestMessage(method, resourceUri)
     {
          Content = content
     };
     request.Headers.Add("SOAPAction", soapAction);
     request.Content.Headers.ContentType =
                            HttpMediaTypeHeaderValue.Parse("text/xml; charset=utf-8"); 
     return request;
};
bool retry = await FirstLoginAttempt(httpRequestCreator());
// If re-try is needed:
var operation = await httpClient.SendRequestAsync(httpRequestCreator()).AsTask(cts.Token);

作为旁注-不要依赖正常代码执行路径的异常处理。相反,考虑发送身份验证信息,即使它可能不需要,或者更确切地说,请求您正在查询的服务在运行时提供有关是否需要传递该信息的信息。