我的目标是在失败时重试异步HttpWebRequest。
当我Abort()一个HttpWebRequest时,我再也无法使用BeginGetResponse()。因此,再次请求的唯一方法可能是重新创建HttpWebRequest对象。它似乎需要大量工作,因为我必须从旧对象复制所有属性。有没有捷径?
注意:我认为序列化可以解决我的问题,但是这个类不会序列化,如previous question中所述。
更新删除了示例源代码,因为它是不必要的
关于此事的当前观点没有捷径,重做请求的唯一方法是创建另一个HttpWebRequest对象,就像创建原始对象一样。
答案 0 :(得分:14)
这是不可能的。
HTTPWebRequest实例实际上表示一个请求实例(尽管存在将在内部重试的边缘情况),因此不能在逻辑上重复。它能够准确地返回一个响应(请求/响应是一个逻辑对),虽然你可以多次检查该响应,但你将获得完全相同的对象。
基本上,您认为HTTPWebRequest实例是一种工厂,但它确实具体。你必须创建另一个实例。
答案 1 :(得分:2)
您在哪里尝试序列化请求?在尝试创建之前序列化请求,然后在失败时重新发送请求(来自序列化实例)可能是个好主意。
此外,您可能希望删除代理,序列化实例,然后重新设置代理,因为这似乎是序列化请求时的问题所在。
答案 2 :(得分:2)
没有快捷方式,重做请求的唯一方法是创建另一个HttpWebRequest对象,就像创建原始对象一样。
答案 3 :(得分:2)
您只需要创建一个新的HttpWebRequest
并通过反射从旧对象复制所有属性。
这是扩展方法,可以执行此操作:
/// <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;
}
如果要重新发出相同的请求,只需执行以下操作:
// 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();