tags:

views:

264

answers:

3

I'm writing a web service which is wrapper for a vendor's web service, and have a fairly detailed series of catch statements for a call to a vendors web service methods. I have two or three types of exceptions that I'm handling (System.Web.Services.Protocols.SoapException, System.ApplicationException, System.Exception...)

I just realized that most of the errors are the same between their two Create method and their Update method.

Is there any clever way to share the exact same error handlers across multiple methods? I started to write just a common method, but then realized I would have to write at least one common method for each type of exception that I'm handling. It would be great if I could handle all of them the exact same way.

This is a web service with an established interface. Just thinking out loud as I write this, I guess I could put as little code as possible in the web methods, then they could call a shared method? Just want to make sure I'm not missing an obvious trick.

Thanks, Neal

+5  A: 

You could a function that takes a Delegate and then call it with a lambda expression (C# 3) or anonymous method. The function can invoke the passed in Delegate in a try block and handle the exceptions.

private T CallWebService<T>(Func<T> function)
{
    try
    {
        return function();
    }
    catch (SoapException e)
    {
        // handle SoapException
    }
    catch (ApplicationException e)
    {
        // handle ApplicationException
    }
    // catch and handle other exceptions    
}

public ReturnType CallCreate(ParamType param)
{
    return CallWebService(() => WebService.InvokeCreate(param));
}

public ReturnType CallUpdate(ParamType param)
{
    return CallWebService(() => WebService.InvokeUpdate(param));
}

If the individual methods need their own specific exceptions handled, then this could be added to the CallCreate and CallUpdate methods.

The above example uses lambda expressions. The equivalent of CallCreate using anonymous methods is:

public ReturnType CallCreate(ParamType param)
{
    return CallWebService<ReturnType>(delegate()
    { 
        return WebService.InvokeCreate(param) 
    });
}
Phil Ross
+1 - This is the way to go.
ChaosPandion
+1  A: 

You could use Phil Ross's delegate approach, or alternatively, you can create an IWebMethodInvoker that implements an Invoke() method:

interface IWebMethodInvoker
{
    void Invoke();
}

Then you implement this interface in a class for each web method call:

class CreateInvoker : IWebMethodInvoker
{
   public SomeDataType Data {get; set;}
   public SomeOtherType Results {get; set;}

   public void Invoke()
   {
       Results = YourWebServiceMethod(Data);
   }
}

Then, you create a method that takes an instance of this interface, invokes it and does the error handling:

public void ExecuteWebServiceCall(IWebMethodInvoker invoker)
{
    try
    {
        invoker.Invoke();
    }
    catch (ExceptionType1 e)
    {
        // Handle Exception Type 1
    }
    catch (ExceptionType2 e)
    {
        // Handle Exception Type 2
    } // etc
}

Then, all you need to invoke the web service is this:

var createInvoker = new CreateInvoker() { Data = someStuff };
ExecuteWebServiceCall(createInvoker);
var results = createInvoker.Results;

This might be a bit more typing than the delegate approach but possibly less confusing for less experienced developers.

DrJokepu
I disagree, this makes it more complicated.
ChaosPandion
+1  A: 

Is there any real value in handling the different types of exceptions explicitly. i.e. is there any valid use case that you have to handle SoapException from a ApplicationException. Mist of the time there isn't.

If you still think that there is value I would suggest to use the ExceptionHandling application block from the Enterprise Library. Using EnterpriseLibrary in this kind of scenario is more cleaner and better design in my view than peppering your code with many catch blocks.

Pratik
Good point, with Sql Exception you get more info, but with SoapException - I haven't seen anything useful there I guess.
NealWalters