Pregunta

Mi objetivo es reintentar un HttpWebRequest asíncrono cuando falla.

Cuando yo Anular () una HttpWebRequest, no puedo BeginGetResponse () de nuevo. Por lo tanto, la única forma de volver a solicitarlo es volver a crear el objeto HttpWebRequest. Parece que requiere mucho trabajo, ya que tendría que copiar todas las propiedades del objeto anterior. ¿Hay algún atajo?

Nota: creo que la serialización resolvería mi problema, pero esta clase no se serializará, como se explica en pregunta anterior .

Actualizar Se eliminó el código fuente del ejemplo porque no era necesario

Vista actual sobre este asunto No hay acceso directo, la única manera de rehacer la solicitud es crear otro objeto HttpWebRequest de la misma manera que creó el original.

¿Fue útil?

Solución

¡Es posible!

Solo necesita crear un nuevo HttpWebRequest y copiar todas las propiedades del objeto anterior a través de la reflexión.

Aquí hay un método de extensión que hace esto:

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

Cuando desee volver a emitir la misma solicitud, simplemente ejecute lo siguiente:

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

Otros consejos

No es posible.

Una instancia de HTTPWebRequest representa literalmente una instancia de solicitud (aunque hay casos límite en los que se reintentará internamente) y, por lo tanto, no es algo que se pueda repetir lógicamente. Es capaz de devolver exactamente una respuesta (la solicitud / respuesta es un par lógico) y, aunque puede inspeccionar esa respuesta varias veces, obtendrá exactamente el mismo objeto.

Básicamente, estás pensando que una instancia de HTTPWebRequest es una especie de fábrica, pero es realmente concreta. Tienes que crear otra instancia.

¿Dónde intenta serializar la solicitud? Puede ser una buena idea serializar la solicitud antes que intenta realizarla y luego reenviar la solicitud en caso de error (desde la instancia serializada).

Además, es posible que desee eliminar el proxy, serializar la instancia y luego restablecer el proxy, ya que parece ser que el problema radica en la serialización de la solicitud.

No hay acceso directo, la única forma de rehacer la solicitud es crear otro objeto HttpWebRequest de la misma manera que creaste el original.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top