5

Consider the following very basic WCF service implementation:

public enum TransactionStatus 
{
    Success = 0,
    Error = 1
}

public class TransactionResponse
{
    public TransactionStatus Status { get; set; }
    public string Message { get; set; }
}


[ServiceContract]
[XmlSerializerFormat]
public interface ITestService
{
    [OperationContract]
    TransactionResponse DoSomething(string data);
}   

public class TestService : ITestService
{
    public TransactionResponse DoSomething(string data)
    {
        var result = ProcessData(data); // may throw InvalidOperationException
        return new TransactionResponse() 
        {
            Status = TransactionStatus.Success,
            Message = result                
        };            
    }

    private string ProcessData(string data) 
    {
        if (data = "foobar")
            throw new InvalidOperationException();

        return data;        
    }        
}

In the instance that the DoSomething method does throw an InvalidOperationException, I would like to intercept the fault and return a TransactionResponse object, rather than have WCF raise a FaultException with the client. How can I do this without surrounding each method body in a huge try catch statement? Is there some where I can hook into? Can I do this with some sort of attribute or something? An example of how I would like to handle it can be demonstrated using ASP.NET MVC:

public class ApiController : BaseController
{
    protected override void OnException(ExceptionContext filterContext)
    {
        var ex = filterContext.Exception;
        var message = HttpContext.IsDebuggingEnabled ? ex.ToString() : ex.Message;

        _logger.Error("Error processing request for controller {0}, action {1}",
            filterContext.RequestContext.RouteData.Values["controller"],
            filterContext.RequestContext.RouteData.Values["action"]);

        _logger.Error(ex.ToString());
        filterContext.ExceptionHandled = true;
        filterContext.Result = ToXml(new ApiResult(false)
        {
            Message = message
        });
    }

    // ...
}

Using the above method in MVC, I can ensure that no matter which controller action throws an exception, I can handle it and return an appropriately formatted ActionResult containing the necessary info. Is there a way to do this kind of thing with WCF?

Chris
  • 27,596
  • 25
  • 124
  • 225

1 Answers1

7

Check out the WCF IErrorHandler interface - it allows you to centrally define one way in your service implementation to catch all exceptions and either swallow them, or convert them to WCF-friendly SOAP exceptions. This will make sure the channel between the client and the server isn't faulted, e.g. it can still be used after this call failed.

I don't understand why you'd want to "catch" the SOAP faults and convert those to something else, though.... nor do I know of any support that WCF would give you. The basic assumption is: catch .NET exceptions and convert them into interoperable SOAP faults

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
  • 1
    Here is an scenario: Sometimes you must provide a service for an enterprise which took weird decisions on their service specifications (e.g. returning the whole important data as an XML string) and they usually expect you to never ever throw any SoapFault but to return something with an error code. Such situation brough me here in first place :p – user1778770 Jun 25 '14 at 17:09
  • 1
    Exactly my case :'( – George Oct 30 '20 at 19:38