Como pedir um abortado HttpWebRequest de novo?
-
03-07-2019 - |
Pergunta
Meu objetivo é repetir uma assíncrona HttpWebRequest quando ele falhar.
Quando eu Abort () um HttpWebRequest, não posso BeginGetResponse () novamente. Assim, a única forma de solicitar novamente provavelmente é recriar o objeto HttpWebRequest. Ele parece exigir muito trabalho desde que eu teria que copiar todas as propriedades do objeto de idade. Existe algum atalho?
Nota: Eu acho que a serialização que iria resolver o meu problema, mas essa classe não vai serialize, como discutido em uma pergunta anterior .
Atualizar exemplo Removido o código fonte porque era desnecessário
Vista actual sobre este assunto Não há nenhum atalho, a única maneira de refazer a solicitação é criar outra HttpWebRequest objeto da mesma forma que criou o original.
Solução
É possível!
Você só precisa criar uma nova HttpWebRequest
e copiar todas as propriedades até lá a partir do objeto de idade através da reflexão.
Aqui está um método de extensão que faz isso:
/// <summary>
/// Clones a HttpWebRequest for retrying a failed HTTP request.
/// </summary>
/// <param name="original"></param>
/// <returns></returns>
public static HttpWebRequest Clone(this HttpWebRequest original)
{
// Create a new web request object
HttpWebRequest clone = (HttpWebRequest)WebRequest.Create(original.RequestUri.AbsoluteUri);
// Get original fields
PropertyInfo[] properties = original.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);
// There are some properties that we can't set manually for the new object, for various reasons
List<string> excludedProperties = new List<String>(){ "ContentLength", "Headers" };
// Traverse properties in HttpWebRequest class
foreach (PropertyInfo property in properties)
{
// Make sure it's not an excluded property
if (!excludedProperties.Contains(property.Name))
{
// Get original field value
object value = property.GetValue(original);
// Copy the value to the new cloned object
if (property.CanWrite)
{
property.SetValue(clone, value);
}
}
}
return clone;
}
Quando você quiser re-emitir o mesmo pedido, simplesmente executar a seguinte:
// Create a request
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create("https://www.google.com/");
// Change some properties...
// Execute it
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
// Clone the request to reissue it using our extension method
request = request.Clone();
// Execute it again
response = (HttpWebResponse)request.GetResponse();
Outras dicas
Não é possível.
instância Uma httpwebrequest representa literalmente uma instância pedido (embora existam casos extremos, onde ele tentará novamente internamente), e, portanto, não é algo que pode, logicamente, ser repetido. Ele é capaz de retornar exatamente uma resposta (request / response sendo um par lógico), e embora você pode inspecionar que vários resposta vezes você vai ter exatamente o mesmo objeto.
Basicamente, você está pensando uma instância httpwebrequest é uma espécie de fábrica, mas é realmente concreto. Você tem que criar outra instância.
Onde você está tentando serializar o pedido? Pode ser uma boa idéia para serializar o pedido antes você tentar fazê-lo, e depois reenviar o pedido em caso de falha (a partir da instância serializada).
Além disso, você pode querer remover o proxy, serializar o exemplo, e em seguida, defina a parte de trás proxy, uma vez que parece ser o lugar onde as mentiras de problema na serialização o pedido.
Não há nenhum atalho, a única maneira de refazer a solicitação é criar outra HttpWebRequest objeto da mesma forma que criou o original.