2012-08-24 21 views
6

Estoy usando HttpClient para llamar a mi apéndice web MVC 4. En mi llamada a la API web, devuelve un objeto de dominio. Si algo sale mal, se lanzará un HttpResponseException en el servidor, con un mensaje personalizado.HttpClient no informa la excepción devuelta por la API web

[System.Web.Http.HttpGet] 
    public Person Person(string loginName) 
    { 
     Person person = _profileRepository.GetPersonByEmail(loginName); 
     if (person == null) 
      throw new HttpResponseException(
     Request.CreateResponse(HttpStatusCode.NotFound, 
       "Person not found by this id: " + id.ToString())); 

     return person; 
    } 

Puedo ver el mensaje de error personalizado en el cuerpo de la respuesta con IE F12. Sin embargo, cuando lo llamo usando HttpClient, no obtengo el mensaje de error personalizado, solo el código http. El "ReasonPhrase" siempre es "No encontrado" para 404, o "Internal Server Error" para 500 códigos.

¿Alguna idea? ¿Cómo devuelvo el mensaje de error personalizado de la API web, mientras mantengo el tipo de devolución normal como mi objeto de dominio?

+0

¿Qué servidor web está utilizando, IIS o ASP.NET Web Server? –

+0

Estoy usando IIS en un Win 2008 R2. De nuevo, está bien cuando lo llamo usando un navegador. – Calvin

Respuesta

14

(Poniendo mi respuesta aquí para una mejor formato)

Sí lo vi, pero HttpResponseMessage no tiene una propiedad cuerpo. Me di cuenta yo mismo: response.Content.ReadAsStringAsync().Result;. El código de muestra:

public T GetService<T>(string requestUri) 
{ 
    HttpResponseMessage response = _client.GetAsync(requestUri).Result; 
    if(response.IsSuccessStatusCode) 
    { 
     return response.Content.ReadAsAsync<T>().Result; 
    } 
    else 
    { 
     string msg = response.Content.ReadAsStringAsync().Result; 
      throw new Exception(msg); 
    } 
} 
+4

Debe tener cuidado de invocar 'Result' directamente desde' ReadAsAsync ', ya que esto puede causar problemas de subprocesamiento intermitente. En su lugar, intente: 'var contentTask = response.Content.ReadAsAsync ();' seguido de 'contentTask.Wait();' y luego 'return contentTask.Result;' –

+0

¡Gracias por la sugerencia! – Calvin

+2

@Sixto: ¿Puedes describir los problemas de enhebrado? El [resultado] (http://msdn.microsoft.com/en-us/library/vstudio/dd321468 (v = vs.110) .aspx) dice "El acceso de obtención para esta propiedad asegura que la operación asincrónica esté completa. antes de volver." Parece que está incorporada una llamada a 'Esperar'. –

0

El mensaje de error personalizado estaría en el 'cuerpo' de la respuesta.

+0

Sí, lo vi, pero HttpResponseMessage no tiene una propiedad del cuerpo. Me di cuenta yo mismo: 'response.Content.ReadAsStringAsync(). Result;'. El código de ejemplo: public T GetService (string requestUri) { HttpResponseMessage response = _client.GetAsync (requestUri) .Result; if (response.IsSuccessStatusCode) { return response.Content.ReadAsAsync () .Result; } else { cadena msg = response.Content.ReadAsStringAsync(). Resultado; lanzar nueva excepción (msg); } } – Calvin

+0

En realidad, por cuerpo, quise decir el contenido de la respuesta. –

1

Expliqué un poco de la lógica al tomar la excepción de una respuesta.

Esto hace que sea muy fácil de extraer la excepción, la excepción interna, excepción interna :), etc

public static class HttpResponseMessageExtension 
{ 
    public static async Task<ExceptionResponse> ExceptionResponse(this HttpResponseMessage httpResponseMessage) 
    { 
     string responseContent = await httpResponseMessage.Content.ReadAsStringAsync(); 
     ExceptionResponse exceptionResponse = JsonConvert.DeserializeObject<ExceptionResponse>(responseContent); 
     return exceptionResponse; 
    } 
} 

public class ExceptionResponse 
{ 
    public string Message { get; set; } 
    public string ExceptionMessage { get; set; } 
    public string ExceptionType { get; set; } 
    public string StackTrace { get; set; } 
    public ExceptionResponse InnerException { get; set; } 
} 

Para una discusión completa ver this blog post.

Cuestiones relacionadas