Consuming FaultContract with Restful WCF services
Solution ·I’ve learned something new this morning while doing a proof-of-concept around WCF REST services.
I did a little WPF demo app both hosting and consuming web services. I was trying to handle faults properly, using fault contracts. I had experience with SOAP-based WCF web services, so I went the motions, starting by creating a fault contract:
[DataContract]
public class WrongInteger
{
[DataMember]
public int Value { get; set; }
}
A fault contract is just a data contract that you throw with an exception.
Then I declared that my service operation can raise that fault:
[WebInvoke(Method = "PUT")]
[OperationContract]
[FaultContract(typeof(WrongInteger))]
void PushInteger(int a);
Then I implemented the operation, throwing the usual fault exception:
void IPushService.PushInteger(int a)
{
if (a == 2)
{
throw new FaultException<WrongInteger>(new WrongInteger { Value = 2 });
}
}
This code works fine if you’re using SOAP WCF services. But with REST WCF services, your HTTP response will just be gibberish with an status of bad request.
Digging on the web I found there’s actually a new class, WebFaultException, derived from FaultException that you must use with REST web services:
void IPushService.PushInteger(int a)
{
if (a == 2)
{
throw new WebFaultException<WrongInteger>(new WrongInteger { Value = 2 }, HttpStatusCode.InternalServerError);
}
}
This will spit out the serialized fault contract into the http-response. Now for the client side code
using (WebChannelFactory<IPushService> factory = new WebChannelFactory<IPushService>("myService"))
{
IPushService service = factory.CreateChannel();
try
{
service.PushInteger(2);
}
catch (WebFaultException<WrongInteger> ex)
{
Dispatcher.Invoke((Action)delegate
{
MessageBox.Show(string.Format("Expected exception: {0}, {1}", ex.Message, ex.Detail.Value));
});
}
catch (Exception ex)
{
Dispatcher.Invoke((Action)delegate
{
MessageBox.Show(ex.Message);
});
}
}
Well, another surprise, that doesn’t work either. The thrown exception isn’t a fault exception, it’s a protocol exception.
I haven’t found a way to make this work. Actually, I’ve read that you should craft HTTP request by hand and look at the http-response in order to get your fault.
Well, that’s a bit of a disappointment! It seems that the fault scenario wasn’t taught through from the get-go. For instance, the WebFaultException class is new in .NET 4.0. So in .NET 3.5, you couldn’t fault: your exceptions would just be generic exceptions. Now we can transmit a fault but we can’t consume it. Maybe in .NET 5.0…
It’s especially frustrating since it would be easy to write a WCF inspector to do that job…
If you find a more elegant way, please let me know!
3 responses