9

我的目标是在异步 HttpWebRequest 失败时重试它。

当我Abort()一个 HttpWebRequest 时,我不能再次 BeginGetResponse()。所以再次请求的唯一方法可能是重新创建 HttpWebRequest 对象。这似乎需要做很多工作,因为我必须从旧对象中复制所有属性。有什么捷径吗?

注意:我认为序列化可以解决我的问题,但是这个类不会序列化,如上一个问题中所述。

更新删除了示例源代码,因为它是不必要的

目前对此事的看法没有捷径,重做请求的唯一方法是创建另一个 HttpWebRequest 对象,就像您创建原始对象一样。

4

4 回答 4

14

这是不可能的。

HTTPWebRequest 实例实际上代表一个请求实例(尽管存在内部重试的极端情况),因此在逻辑上不是可以重复的东西。它能够只返回一个响应(请求/响应是一对逻辑对),尽管您可以多次检查该响应,但您将获得完全相同的对象。

基本上,您认为 HTTPWebRequest 实例是一种工厂,但它确实是具体的。您必须创建另一个实例。

于 2009-01-28T15:48:33.527 回答
4

这是可能的!

您只需要创建一个新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();
于 2016-01-18T17:45:29.820 回答
2

您在哪里尝试序列化请求?在尝试发出请求之前序列化请求可能是个好主意,然后在失败时重新发送请求(从序列化实例)。

此外,您可能希望删除代理、序列化实例,然后重新设置代理,因为这似乎是序列化请求的问题所在。

于 2009-01-05T02:27:22.530 回答
2

没有捷径,重做请求的唯一方法是创建另一个 HttpWebRequest 对象,就像创建原始对象一样。

于 2009-01-12T14:44:41.533 回答