Получение подробной информации об ошибке из WCF REST - PullRequest
9 голосов
/ 25 марта 2010

У меня есть служба REST, используемая клиентом .Net WCF.

При обнаружении ошибки служба REST возвращает неверный запрос HTTP 400 с телом ответа, содержащим сериализованные детали JSON.

Если я выполню запрос, используя Fiddler, Javascript или непосредственно из C #, я легко получу доступ к телу ответа при возникновении ошибки.

Однако я использую WCF ChannelFactory с 6 довольно сложными интерфейсами. Исключением, выданным этим прокси-сервером, всегда является ProtocolException, без каких-либо полезных подробностей.

Есть ли способ получить тело ответа, когда я получаю эту ошибку?


Обновление

Я понимаю, что существует множество разных способов сделать это с помощью .Net и что есть другие способы получить ответ об ошибке. Их полезно знать, но не отвечайте на этот вопрос.

Службы REST, которые мы используем, изменятся, и когда они сделают, сложные интерфейсы будут обновлены. Использование ChannelFactory с новыми интерфейсами означает, что мы получим исключения во время компиляции (а не во время выполнения) и сделаем их намного проще для поддержки и обновления кода.

Можно ли получить тело ответа об ошибке HTTP-статуса при использовании каналов WCF?

Ответы [ 6 ]

5 голосов
/ 10 марта 2011

вы можете получить подробную информацию об исключении, как показано ниже:

                Exception innerException = exception.InnerException;
                WebException webException = innerException as WebException;
                HttpWebResponse response = webException.Response as HttpWebResponse;
                string statusDescription = response.StatusDescription;
                HttpStatusCode statusCode = response.StatusCode;
4 голосов
/ 07 января 2014

InnerException из ProtocolException будет WebException. Вы можете получить HttpWebResponse от этого и вызвать GetResponseStream, чтобы прочитать фактическое тело ответа. (Не забудьте поискать начало потока перед чтением).

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();
3 голосов
/ 05 апреля 2010

Вы можете попробовать выбросить WebProtocolException из службы. Таким образом, сведения об ошибке должны быть включены в текст ответа HTTP. Посмотрите на эту статью:

Эффективная обработка ошибок с WCF & REST

1 голос
/ 30 сентября 2011

Подход, описанный пользователем 653761, работает для меня; после доступа к объекту HttpWebResponse я могу использовать класс DataContractSerializer следующим образом:

var serializer = new DataContractSerializer(typeof(MyDataContractType));
var deserialized = 
    (serializer.ReadObject(httpWebResponse.GetResponseStream()) as MyDataContractType);

// ...

Полагаю, это сработает для всего, что WCF может сериализовать, если вы используете правильный сериализатор, но еще не проверили его на производительность.

1 голос
/ 29 апреля 2010

Мои два цента в том, что WCF хорошо показывает один и тот же класс, используя много разных привязок. При взаимодействии с C # используйте привязку SOAP, которая хороша для информации об исключениях. Если вам необходимо использовать привязку стиля REST, вы можете использовать простой WebRequest для вызова службы и использовать сериализатор JSON для десериализации результатов. Это также даст вам прямой доступ к коду ответа.

1 голос
/ 26 марта 2010

Не используйте ChannelFactory :-) Серьезно, хотя. Зачем вам создавать REST-интерфейс, а затем использовать клиентский прокси WCF. В чем преимущество использования сервиса REST? Почему бы просто не использовать wsHttpBinding? С помощью класса HttpClient из начального набора REST вы можете выполнять стандартные HTTP-запросы, а затем десериализовать ответ с помощью DataContractSerializer.

* 1003 Е.Г. *

var httpClient = new HttpClient();
var content = httpClient.Get("http://example.org/customer/45").Content;
var customer = content.ReadAsDataContract<Customer>()
...