Saltar al contenido

Uso de GuaranteeSuccessStatusCode y manejo de HttpRequestException que arroja

Luego de consultar con expertos en el tema, programadores de deferentes áreas y maestros dimos con la respuesta al dilema y la dejamos plasmada en esta publicación.

Solución:

El uso idiomático de EnsureSuccessStatusCode es verificar de manera concisa el éxito de una solicitud, cuando no desea manejar los casos de falla de ninguna manera específica. Esto es especialmente útil cuando desea crear rápidamente un prototipo de un cliente.

Cuando decida que desea manejar los casos de falla de una manera específica, no Haz lo siguiente.

var response = await client.GetAsync(...);
try

    response.EnsureSuccessStatusCode();
    // Handle success

catch (HttpRequestException)

    // Handle failure

Esto arroja una excepción solo para detectarlo de inmediato, lo que no tiene ningún sentido. Él IsSuccessStatusCode propiedad de HttpResponseMessage está ahí para este propósito. Haz lo siguiente en su lugar.

var response = await client.GetAsync(...);
if (response.IsSuccessStatusCode)

    // Handle success

else

    // Handle failure

No me gusta AsegurarSuccessStatusCode ya que no devuelve nada significativo. Es por eso que he creado mi propia extensión:

public static class HttpResponseMessageExtensions

    public static async Task EnsureSuccessStatusCodeAsync(this HttpResponseMessage response)
    
        if (response.IsSuccessStatusCode)
        
            return;
        

        var content = await response.Content.ReadAsStringAsync();

        if (response.Content != null)
            response.Content.Dispose();

        throw new SimpleHttpResponseException(response.StatusCode, content);
    


public class SimpleHttpResponseException : Exception

    public HttpStatusCode StatusCode  get; private set; 

    public SimpleHttpResponseException(HttpStatusCode statusCode, string content) : base(content)
    
        StatusCode = statusCode;
    

El código fuente de GuaranteeSuccessStatusCode de Microsoft se puede encontrar aquí

Versión síncrona basada en enlace SO:

public static void EnsureSuccessStatusCode(this HttpResponseMessage response)

    if (response.IsSuccessStatusCode)
    
        return;
    

    var content = response.Content.ReadAsStringAsync().GetAwaiter().GetResult();

    if (response.Content != null)
        response.Content.Dispose();

    throw new SimpleHttpResponseException(response.StatusCode, content);

Lo que no me gusta de IsSuccessStatusCode es que no es “bien” reutilizable. Por ejemplo, puede usar una biblioteca como polly para repetir una solicitud en caso de un problema de red. En ese caso, necesita su código para generar una excepción para que polly o alguna otra biblioteca pueda manejarlo …

A continuación se muestra mi solución propuesta. El único defecto es que, dado que el administrador de recursos del marco ASP.NET Core es interno del marco, no puedo reutilizar directamente las cadenas de mensajes internacionalizados de Microsoft, por lo que solo estoy usando el mensaje literal en inglés aquí.

ventajas

  • Registra el contenido de un error del servidor 5xx
    • A veces, un error del servidor es en realidad un error del cliente disfrazado, como un cliente que usa un punto final obsoleto que finalmente se apagó.
  • Hace que sea más fácil descubrir errores al escribir pruebas de integración usando ConfigureTestContainer

Contras

  • Ineficiente.
    • Si lee el contenido de la respuesta y el contenido es muy largo, ralentizará al cliente. Para algunos clientes, con requisitos suaves de respuesta en tiempo real, esta fluctuación puede ser inaceptable.
  • Responsabilidad incorrecta por registro y monitoreo de errores.
    • Si se trata de un error del servidor 5xx, ¿por qué le importa al cliente, ya que el cliente no hizo nada malo? Solo llama response.EnsureSuccessStatusCode(); y deja que el servidor se ocupe de ello.
    • ¿Por qué no simplemente revisar los registros de errores del servidor cuando hay un error interno del servidor?
  • Requiere leer el Content propiedad antes de comprobar el estado. Puede haber situaciones en las que esto no sea deseable, una de las cuales es la ineficiencia.

Uso

using (var requestMessage = new HttpRequestMessage(HttpMethod.Post, "controller/action"))

  using (var response = await HttpClient.SendAsync(requestMessage))
  
    var content = await response.Content.ReadAsStringAsync();
    response.EnsureSuccessStatusCode2(content);
    var result = JsonConvert.DeserializeObject(content);
  

API

    public static class HttpResponseMessageExtensions
    
        public static void EnsureSuccessStatusCode2(this HttpResponseMessage message, string content = null)
        
            if (message.IsSuccessStatusCode)
                return;
            var contentMessage = string.IsNullOrWhiteSpace(content) ? string.Empty : $"Content: content";
            throw new HttpRequestException(string.Format(
                System.Globalization.CultureInfo.InvariantCulture,
                "Response status code does not indicate success: 0 (1).2",
                (int)message.StatusCode,
                message.ReasonPhrase,
                contentMessage)
                );
        
    

Si te apasiona este mundo, tienes la libertad de dejar una crónica acerca de qué le añadirías a este artículo.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *