How to Resolve TargetInvocationException Error: Catching Exception in Asynchronous Calls

So here's the situation. You're wrapping a webservice in library used for some clients. You want to call the web service methods  asynchronously using MethodNameAsync.

When you plug out the network cable to test for offline scenarios, ta-da, you get this cryptic error called "TargetInvocationException".

This code gives me TargetInvocationException error:

void _ws_loginCompleted(object sender, ws.loginCompletedEventArgs e)
{
    if (IsWsResponseOk(e.Result))
    {
        // Save session key used for upcoming Web Service Requests
        _sessionKey = e.Result.message;
    }
    IResponse response = ConvertWsResponse(e.Result);
    LoginCompleted(this, response);
}

Since I'm a productive programmer, at first I asked uncled Google about this error. He showed me this post in MSDN forum that leads to this blog about using BackgroundWorker to do synchronous web calls instead.

Dude, that's not an elegant solution,  I say.

So, I read up on MSDN about this creepy TargetInvocationException, and found out that if there's an error in the asynchronous call, e.Result is basically not valid.

So here's my (elegant) solution to the above TargetInvocationException error, I've put in BOLD the methods that you need to place to handle the error:

void _ws_loginCompleted(object sender, ws.loginCompletedEventArgs e)
{
    ws.ws_response wsResponse = IsAsyncCallOk(e) ? e.Result : BuildWsErrorMsg(e);
    if (IsWsResponseOk(wsResponse))
    {
        // Save session key used for upcoming Web Service Requests
        _sessionKey = wsResponse.message;
    }
    IResponse response = ConvertWsResponse(wsResponse);
    LoginCompleted(this, response);
}

private bool IsAsyncCallOk(System.ComponentModel.AsyncCompletedEventArgs args)
{ 
    return (args.Error != null) ? false : true;
}

private ws.ws_response BuildWsErrorMsg(System.ComponentModel.AsyncCompletedEventArgs e)
{
    ws.ws_response wsResponse = new ws.ws_response();
    wsResponse.status_code = -1;
    wsResponse.message = GetInnerExceptionError(e);
    return wsResponse;
}

private static string GetInnerExceptionError(System.ComponentModel.AsyncCompletedEventArgs e)
{
    if (e.Error.Message != null)
    {
        return e.Error.Message;
    }

    // Find the InnerException that threw this error
    Exception ex = e.Error.InnerException;
    while (ex == null)
    {
        ex = ex.InnerException;
    }
    return ex.Message;
}

Now, my client code doesn't need any changes or catching some fancy Asynchronous Exceptions...

static void TestDmsLoginLogout()
{
    IServer server = Config.IServerFactory("http://127.0.0.1");
    ICredential credential = Config.ICredentialFactory("admin", "admin");

    IDms dms = Config.IDmsFactory(server);
    dms.LoginCompleted += new LoginCompletedEventHandler(dms_LoginCompleted);
    dms.LoginAsync(credential);

    System.Threading.Thread.Sleep(10000);

    dms.LogoutCompleted += new LogoutCompletedEventHandler(dms_LogoutCompleted);
    dms.LogoutAsync();
}

static void dms_LogoutCompleted(object sender, IResponse result)
{
    Console.WriteLine("\nDMS Logout completed. Result={0}, ErrorMessage={1}",
        result.Success.ToString(), result.ErrorMessage);
}

static void dms_LoginCompleted(object sender, IResponse result)
{
    Console.WriteLine("\nDMS Login completed. Result={0}, ErrorMessage={1}",
            result.Success.ToString(), result.ErrorMessage);
}

And the Console Output for the above test code is:

DMS Login completed. Result=False, ErrorMessage=No connection could be made beca
use the target machine actively refused it 127.0.0.1:80

DMS Logout completed. Result=False, ErrorMessage=No connection could be made bec
ause the target machine actively refused it 127.0.0.1:80

Hope that helps for those in familiar situations.

Share this post: | | | |
Published Thursday, August 21, 2008 1:33 PM by zeddy
Filed under: ,

Comments

# How to Resolve "Unable to read data from the transport connection" Error

Thursday, October 09, 2008 5:03 PM by Z & his Startup

Previously when dealing with Web Service calls, I've discussed on how to resolve the TargetInvocation

# Recent Faves Tagged With "asynchronous" : MyNetFaves

Pingback from  Recent Faves Tagged With "asynchronous" : MyNetFaves

Powered by Community Server (Commercial Edition), by Telligent Systems