0
votes

Im trying to implement the global error handling in WCF using the IErrorHandler interfcae but i want to return (in case of unhandled exception) a simple string (this is the return type of my service) how can i acheive that? the ProvideFault method inside the IErrorHandler set the 'fault' argument to Message type and the Message type ToString() generate XML like response so this is not working for me (because my client want to get simple string in a specific format).

thanks

1
If I understand correctly - your service method already returns a string. You have a specific string that you want to return from the service if an exception occurs?Scott Hannen
@ScottHannen yes, exactly. and i want to do this from the global error handler.eitanby
I can provide a way to do it that's not from the global error handler, but doesn't require you to write the same code in every service method.Scott Hannen

1 Answers

0
votes

According to the documentation,

IErrorHandler enables you to explicitly control the SOAP fault generated

It's not for changing the actual return value of the service.

If I understand correctly, your service already returns a string. If an error occurs, you want your service to return a particular string.

In its simplest form, this would look like this:

public string YourServiceMethod(int someInput)
{
    try
    {
        // Do whatever the method does
    }
    catch(Exception ex)
    {
        // Log the exception, probably?
        return "This is the specific error message I want to return."
    }
}

If you want to avoid writing that same code in every method, one way to accomplish that is using an interceptor, such as with Castle Windsor's dependency injection container.

That means modifying the whole WCF service to use Windsor (or some similar DI framework) but it's worth it for lots of other reasons. I use it for every WCF service I write. Here's a tutorial on how to add Windsor to your WCF service in five minutes.

Then you would write a class called an interceptor. It might look something like this:

public class ErrorMessageInterceptor : IInterceptor
{
    public void Intercept(IInvocation invocation)
    {
        try
        {
            invocation.Proceed();
        }
        catch (Exception ex)
        {
            // log your exception
            invocation.ReturnValue = "Your specific error message.";
        }
    }
}

Then, when you register your service with the container you would do this:

container.Register(
    Component.For<IInterceptor>().ImplementedBy<ServerLogInterceptor>()
       .Named("ErrorMessageInterceptor"));

container.Register(Component.For<IYourService,YourService>()
   .Interceptors("ErrorMessageInterceptor"));

where IYourService is your service interface and YourService is the actual service class.

This means that every time an instance of YourService is activated, an instance of ErrorMessageInterceptor is created. All calls to the service's method are "intercepted" by the interceptor's Intercept method. It's essentially putting a try/catch around the method call without directly adding it into the original method.

If you needed to you could be more specific. For example, your interceptor could check invocation.Method.ReturnType to see if the method returns a string, and only add your error message then.

You can do some great stuff with interceptors. A scenario like this where you're trying to something small is a great opportunity to try working with them. If you haven't used DI with WCF before it looks weird, but likewise once you try it you might find that it's a very useful pattern.