Reusing try catch for wcf call

I have a series of methods that call wcf services and all of them have the same try catch code

Response Method1(Request request)
{
    Response response = null;
    using(ChannelFactory<IService1> factory = new ChannelFactory<IService1>(myEndpoint))
    {
        IService1 channel = factory.CreateChannel();
        try
        {
            response = channel.Operation(request);
        }
        catch(CommunicationException ex)
        {
            // Handle Exception
        }
        catch(TimeoutException ex)
        {
            // Handle Exception
        }
        catch(Exception ex)
        {
            // Handle Exception
        }
    }
    return response;
}

And so on (I have 6 methods like this for different services).. how can i encapsulate all the service calls and handle the exceptions in a single method

EDIT

Following Nathan A's advice I created a simple generic method:

protected TResult ExecuteAndCatch<TResult>(Func<T, TResult> serviceCall, T request)
    where T : Request
    where TResult : Response
{
    try
    {
        return serviceCall(request);
    }
    catch (CommunicationException ex)
    {
    }
    catch (TimeoutException ex)
    {
    }
    catch (Exception ex)
    {
    }
    return null;
}

The new methods would like this

Response NewMethod1(Request request)
{
    Response response = null;
    using(ChannelFactory<IService1> factory = new ChannelFactory<IService1>(myEndpoint))
    {
        IService1 channel = factory.CreateChannel();
        response = channel.Operation(request);
    }
    return response;
}

and i'm trying to call it like

Response response = ExecuteAndCatch<Response>(NewMethod1, new Request())

What am I doing wrong?

Upvotes: 2

Views: 922

Answers (3)

MattC
MattC

Reputation: 4004

If your client derives from ClientBase<T> e.g MyClient : ClientBase<IWCFService>

You could then create your own base class that provides methods that will wrap the common functionality.

The below sample code could be expanded to allow the final derived class to specify what to do when a particular method call fails. Here I just call HandleError

In specific client class

//method that returns a value
public int Ping()
{
    return Protect(c => c.Ping());
}    

//void method usage
public void Nothing(int stuff)
{
    Protect(c => c.Nothing(stuff));
}      

In client base class

protected void Protect(Action<IWCFService> action)
{
    Protect(c => { action(c); return true; });
}

//add other exception handling
protected Protect<T>(Func<IWCFService, T> func)
{
    try
    {
        return func(Channel);
    }
    catch (FaultException e)
    {
        HandleError(e);//up to you to implement this and any others
    }

    return default(T);
}

Upvotes: 1

tezromania
tezromania

Reputation: 817

inject the various clients through an interface and then run the operation in a single place?

HttpResponse performOperation(IServiceClient injectedServiceClient)
{
    IServiceClient client = injectedServiceClient;

    try
    {
        client.Operation();
    }
    catch(CommunicationException ex)
    {
        // Handle Exception
    }
    catch(TimeoutException ex)
    {
        // Handle Exception
    }
    catch(Exception ex)
    {
        // Handle Exception
    }
    return httpResponse(httpStatusCode.OK);
}

Upvotes: 0

Nathan A
Nathan A

Reputation: 11319

Use a wrapper function.

Take a look at this article: http://mytenpennies.wikidot.com/blog:writing-wcf-wrapper-and-catching-common-exceptions

Here's an example from the article:

private void ExecuteAndCatch<T> (Action<T> action, T t) {
    try {
        action (t);
        Success = true;
    }
    catch (TimeoutException) {
        Success = false;
        Message = "Timeout exception raised.";
    }
    catch (CommunicationException) {
        Success = false;
        Message = "Communication exception raised.";
    }
}

Upvotes: 3

Related Questions