Getting error detail from WCF REST
Asked Answered
N

6

9

I have a REST service consumed by a .Net WCF client.

When an error is encountered the REST service returns an HTTP 400 Bad Request with the response body containing JSON serialised details.

If I execute the request using Fiddler, Javascript or directly from C# I can easily access the response body when an error occurs.

However, I'm using a WCF ChannelFactory with 6 quite complex interfaces. The exception thrown by this proxy is always a ProtocolException, with no useful details.

Is there any way to get the response body when I get this error?


Update

I realise that there are a load of different ways to do this using .Net and that there are other ways to get the error response. They're useful to know but don't answer this question.

The REST services we're using will change and when they do the complex interfaces get updated. Using the ChannelFactory with the new interfaces means that we'll get compile time (rather than run time) exceptions and make these a lot easier to maintain and update the code.

Is there any way to get the response body for an error HTTP status when using WCF Channels?

Nanci answered 25/3, 2010 at 15:35 Comment(2)
Reading your explanation, it sounds like you don't have control over the REST service itself, is that correct?Cigar
Actually in this case we do, but it's difficult to change. Our problem is complexity - the WCF ChannelFactory gives a really nice way to manage that with interfaces. The annoying thing is that it throws away the response body when the HTTP header status is anything other than 200. When we get an error from the REST service it returns an HTTP 400 or 500 status with details in the body.Nanci
F
1

Don't use ChannelFactory :-) Seriously though. Why would you create a REST interface and then use the WCF client proxy. What is the benefit of using the REST service? Why not just use wsHttpBinding? With the HttpClient class from the REST starter kit you can make standard HTTP requests and then deserialize the response using the DataContractSerializer.

E.g.

var httpClient = new HttpClient();
var content = httpClient.Get("http://example.org/customer/45").Content;
var customer = content.ReadAsDataContract<Customer>()
Frangible answered 25/3, 2010 at 23:5 Comment(1)
I like your simple-is-better approach, but we have a large number of interfaces, and almost all the methods take complex POST content. The code simplicity of the ChannelFactory's proxy implementation saves us an awful lot of code complexity. I know that it can be done your way, but what I really want to know is: can we get the error detail if we do it the ChannelFactory way?Nanci
V
5

you can retrieve the exception detail as below:

                Exception innerException = exception.InnerException;
                WebException webException = innerException as WebException;
                HttpWebResponse response = webException.Response as HttpWebResponse;
                string statusDescription = response.StatusDescription;
                HttpStatusCode statusCode = response.StatusCode;
Vesical answered 10/3, 2011 at 15:5 Comment(0)
S
5

The InnerException of the ProtocolException will be a WebException. You can get the HttpWebResponse from that and call GetResponseStream to read the actual response body. (Remember to seek to the beginning of the stream before reading).

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();
Skillless answered 7/1, 2014 at 9:50 Comment(0)
S
3

You could try throwing a WebProtocolException from the service. This way the error details should be included in the body of the HTTP response. Have a look at this article:

Effective Error Handling with WCF & REST

Signorino answered 5/4, 2010 at 14:0 Comment(1)
That's exactly what the service does - the details as JSON serialised in the body of the HTTP response. The problem is that the ChannelFactory throws an exception without those details for any HTTP header status other than 200. The service works, it's WCF's client implementation that's the problem.Nanci
F
1

Don't use ChannelFactory :-) Seriously though. Why would you create a REST interface and then use the WCF client proxy. What is the benefit of using the REST service? Why not just use wsHttpBinding? With the HttpClient class from the REST starter kit you can make standard HTTP requests and then deserialize the response using the DataContractSerializer.

E.g.

var httpClient = new HttpClient();
var content = httpClient.Get("http://example.org/customer/45").Content;
var customer = content.ReadAsDataContract<Customer>()
Frangible answered 25/3, 2010 at 23:5 Comment(1)
I like your simple-is-better approach, but we have a large number of interfaces, and almost all the methods take complex POST content. The code simplicity of the ChannelFactory's proxy implementation saves us an awful lot of code complexity. I know that it can be done your way, but what I really want to know is: can we get the error detail if we do it the ChannelFactory way?Nanci
P
1

My two cents is that WCF is good at exposing the same class using many different bindings. When communicating with C#, use a SOAP binding that is good at exception information. If you must use the REST style binding, you could use a simple WebRequest to call the service and use the JSON serializer to deserialize the results. This will also give you direct access to the response code.

Phototube answered 29/4, 2010 at 16:3 Comment(0)
U
1

The approach described by user653761 works for me; after having access to the HttpWebResponse object I can use the DataContractSerializer class like this:

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

// ...

I guess this would work for anything that WCF can serialize if you use the right serializer, didn't test for performance (yet).

Undershrub answered 30/9, 2011 at 9:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.