Obtendo detalhes de erro do WCF Rest
-
22-09-2019 - |
Pergunta
Eu tenho um serviço de descanso consumido por um cliente .NET WCF.
Quando um erro é encontrado, o serviço restante retorna uma solicitação ruim HTTP 400 com o corpo de resposta que contém detalhes serializados JSON.
Se eu executar a solicitação usando Fiddler, JavaScript ou diretamente de C#, posso acessar facilmente o corpo de resposta quando ocorrer um erro.
No entanto, estou usando um WCF ChannelFactory
com 6 interfaces bastante complexas. A exceção lançada por este proxy é sempre um ProtocolException
, sem detalhes úteis.
Existe alguma maneira de obter o corpo de resposta quando recebo esse erro?
Atualizar
Sei que existem várias maneiras diferentes de fazer isso usando .NET e que existem outras maneiras de obter a resposta de erro. Eles são úteis para saber, mas não respondem a essa pergunta.
Os serviços restantes que estamos usando mudam e quando eles fazem as interfaces complexas são atualizadas. Usando o ChannelFactory
Com as novas interfaces significa que obteremos exceções de tempo de compilação (em vez de executar tempo) e facilitaremos a manutenção e a atualização do código.
Existe alguma maneira de obter o corpo de resposta para um status HTTP de erro ao usar canais WCF?
Solução
Não use o ChannelFactory :-) Sério. Por que você criaria uma interface de repouso e, em seguida, usaria o proxy do cliente WCF. Qual é o benefício de usar o serviço restante? Por que não usar apenas WshttpBinding? Com a classe HTTPClient no kit de partida REST, você pode fazer solicitações HTTP padrão e, em seguida, desfilizar a resposta usando o DataContractSerializer.
Por exemplo
var httpClient = new HttpClient();
var content = httpClient.Get("http://example.org/customer/45").Content;
var customer = content.ReadAsDataContract<Customer>()
Outras dicas
Você pode recuperar os detalhes da exceção como abaixo:
Exception innerException = exception.InnerException;
WebException webException = innerException as WebException;
HttpWebResponse response = webException.Response as HttpWebResponse;
string statusDescription = response.StatusDescription;
HttpStatusCode statusCode = response.StatusCode;
o InnerException
do ProtocolException
será uma WebException
. Você pode obter o HttpWebResponse
a partir disso e ligue GetResponseStream
para ler o corpo de resposta real. (Lembre -se de procurar o início do fluxo antes de ler).
var webException = (WebException) protocolException.InnerException;
var response = (HttpWebResponse) webException.Response;
var responseStream = response.GetResponseStream()
responseStream.Seek(0, SeekOrigin.Begin);
var reader = new StreamReader(responseStream);
var responseContent = reader.ReadToEnd();
Você poderia tentar jogar um WebProtocolexception do serviço. Dessa forma, os detalhes do erro devem ser incluídos no corpo da resposta HTTP. Dê uma olhada neste artigo:
Meus dois centavos é que o WCF é bom em expor a mesma classe usando muitas ligações diferentes. Ao se comunicar com C#, use uma ligação de sabão boa em informações de exceção. Se você precisar usar a encadernação do estilo REST, poderá usar um WebRequest simples para ligar para o Serviço e usar o Serializer JSON para desserializar os resultados. Isso também fornecerá acesso direto ao código de resposta.
A abordagem descrita pelo usuário653761 funciona para mim; Depois de ter acesso ao HttpWebResponse
objeto eu posso usar o DataContractSerializer
aula como esta:
var serializer = new DataContractSerializer(typeof(MyDataContractType));
var deserialized =
(serializer.ReadObject(httpWebResponse.GetResponseStream()) as MyDataContractType);
// ...
Eu acho que isso funcionaria para qualquer coisa que o WCF possa serializar se você usar o serializador certo, ainda não testou o desempenho (ainda).