tags:

views:

593

answers:

2

I'm using the [WebGet] attribute to query a REST API on a web server. Every so often (because the API is still under development) I get back an HTML document in the form of an HTTP/500 error instead of the XML I want.

Here's an example of my operation contract:

[WebGet(UriTemplate = "search/?api_key={key}&query={query}",
   BodyStyle = WebMessageBodyStyle.Bare)]
[OperationContract]
XElement Find(string key, string query);

... and here's how I call it:

var factory = new WebChannelFactory<IFooFinder>(
    new Uri("http://api.example.com"));
var channel = factory.CreateChannel();
var results = channel.Find(myApiKey, "foo");

In the event of an error, "results" ends up being an XElement that contains this XML:

<html>
    <head></head>
    <body>
        500 Internal Server Error
    </body>
</html>

Is there some way to catch the 500 error before the XML is returned, and have the channel throw an exception or something? Or am I going to have to check the results variable each time to make sure the XML I expect is in there?

+2  A: 

No, you can't really throw an exception or SOAP fault since all you have really is HTTP. So if your service fails, the only way it can communicate that back to the HTTP client is by means of a HTTP status code.

You could try making the code more meaningful, e.g. don't always return a 500 but split it up into more detail, or you could possibly include more descriptive error messages (at least for development and testing) to give you a hint what went wrong.

But the basic mechanism is : you only use HTTP for the GET, you only have HTTP to return status and error codes.

Marc

marc_s
Thanks Marc. To add insult to injury, I think the REST API I'm calling is actually returning 200/OK even when there's an error, and only giving me the error message in HTML. I'll have to contact them for more information.
Matt Hamilton
+1  A: 

If you set the status code on the server to an error code then I would expect the client to map that to an exception. I know the System.Net.HttpWebRequest throws a WebException on the client if it gets a 400 or 500 series status code.

On the server side if you don't want to add try catch blocks in every service implementation method then you are going to have to replace the standard error handler that System.ServiceModel.Web provides.

I have code that does this by creating a new derived WebHttpBehaviour and overloading AddServerErrorHandlers to prevent the default error handler from being applied. Then you need to add your error handler that will set the status code by using ApplyDispatchBehavior in a new behaviour that implements IServiceBehavior.

There is probably an easier way. There seems to be 1001 ways of skinning the same cat in WCF.

Darrel Miller
Hi Darrel. I don't have any control over the server in this case - it's a 3rd-party web site. Thanks for your answer though. +1
Matt Hamilton