Search code examples
c#.nethttpwebrequest

How to request an aborted HttpWebRequest again?


My objective is to retry an asynchronous HttpWebRequest when it fails.

When I Abort() an HttpWebRequest, I cannot BeginGetResponse() again. So the only way to request again probably is recreate the HttpWebRequest object. It seems to require a lot of work since I would have to copy all properties from the old object. Is there any shortcut?

Note: I think that serialization it would solve my problem, but this class won't serialize, as discussed in a previous question.

Update Removed example source code because it was unnecessary

Current view on this matter There is no shortcut, the only way to redo the request is creating another HttpWebRequest object the same way you created the original one.


Solution

  • It's possible!

    You just need to create a new HttpWebRequest and copy all of the properties over to it from the old object via reflection.

    Here's an extension method that does this:

    /// <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;
    }
    

    When you want to re-issue the same request, simply execute the following:

    // 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();