Unable to catch Webservice call method within try catch block - c#

I am developing a WP8 application. I created a web service on out-systems and then I am calling those web service methods in my app:
ServiceReference1.WebServiceClient ws = new WebServiceClient();
try
{
ws.FetchInboxAsync(EmailId);
}
catch(Exception e)
{
MessageBox.Show(e.Message);
}
Now if the server is down, I expect the control to go into the catch block but it does not and I get the following exception:
An exception of type 'System.ServiceModel.CommunicationException'
occurred in System.ServiceModel.ni.dll but was not handled in user
code.
I do realize that the web service call method is asynchronous, so its exception would not be caught in try catch. On forums, people suggest using await keyword. But when I write
await ws.FetchInboxAsync(EmailId);
I get an error : Cannot await void.
I tried something mentioned in answers here, but still I get the same exception

You can subscribe to FetchInboxCompleted event:
ServiceReference1.WebServiceClient ws = new WebServiceClient();
ws.FetchInboxCompleted += new EventHandler<ServiceReference1.FetchInboxCompletedEventArgs>(c_FetchInboxCompleted);
ws.FetchInboxAsync(EmailId);
And in event handler, check the result:
static void c_FetchInboxCompleted(object sender, serviceReference1.FetchInboxCompletedEventArgs e)
{
// check e.Error which contains the exception, if any
}

If the auto-generated WCF client proxy supports it, you should be able to await a method ending with TaskAsync:
await ws.FetchInboxTaskAsync(EmailId);
If the auto-generated WCF client proxy doesn't define this method, then you can define it yourself as described on MSDN:
public static Task FetchInboxTaskAsync(this ServiceReference1.WebServiceClient client, string emailId)
{
return Task.Factory.FromAsync(client.BeginFetchInbox, client.EndFetchInbox, emailId, null);
}

Related

Error handling using delegates

I have a common method that I'm using to handle a specific error that may come back from a number of functions:
protected async Task<T> RunMyMethod<T>(Func<T> method)
{
try
{
var returnValue = await Task.Run<T>(method);
return returnValue;
}
catch (MyCustomException)
{
// Force a clean shutdown of the software
ShutdownApplication();
return default(T);
}
}
Here's an example of how that is then used in a derived class:
private async Task<IEnumerable<MyData>> GetMyData()
{
var returnValue = await base.RunMyMethod<IEnumerable<MyData>>(() =>
{
var returnval = GetMyDataFromServer();
return returnval;
});
return returnValue;
}
When an exception of type MyCustomException occurs in GetMyDataFromServer() the software doesn't drop into the catch block. I get the following error in the function GetMyData():
An exception of type 'System.ServiceModel.FaultException`1' occurred in mscorlib.dll but was not handled in user code
Additional information: Exception of type 'MyCustomException' was thrown.
This is with only User-unhandled exceptions turned on.
GetMyDataFromServer() communicates with a WCF service. This service is what throws the error.
ChannelFactory<TChannel> cf = new ChannelFactory<TChannel>(endPointName);
Binding binding = new BasicHttpBinding(BasicHttpSecurityMode.TransportCredentialOnly);
var clientCredentials = new ClientCredentials();
. . .
channel = cf.CreateChannel();
var data = channel.CallWCFService();
Having looked around on-line, it appeared that the correct way to handle this was to change the base method as follows:
protected async Task<T> RunMyMethod<T>(Func<T> method)
{
var returnValue = await Task.Run<T>(method).ContinueWith(e =>
{
ShutdownApplication();
return default(T);
}, TaskContinuationOptions.OnlyOnFaulted);
return returnValue;
}
When I run this, I'm obviously not trapping for the correct error message, but I'm just getting a TaskCancellationException.
So, I have two questions: is my conclusion about how to handle this exception correct and, if so, how do I trap a specific error; and why am I getting a TaskCancellationException?
You get TaskCancellationException because the continuation is cancelled as it's conditional (i.e. TaskContinuationOptions.OnlyOnFaulted) and the condition isn't met since the antecedent task wasn't faulted.
There's no reason to use that method of adding a continuation. Using async-await like you did at the start is good enough (and even simpler).
The issue is that you are trying to catch MyCustomException but that isn't the exception being thrown. Since you're using WCF the exception is FaultException. You can check the "real" exception stored in FaultException.InnerException.

exception generated inside an await block is not catched in try catch block

I have a sync function such as the following function that generate an IO error (I delete the detail to make it simple):
public override void SyncFunction()
{
throw new IOException("test");
}
and I used it in this way:
try
{
await Task.Run(() => this.SyncFunction());
}
catch (Exception ex)
{
MessageBox.Show("Error:"+Environment.NewLine + ex.Message);
}
But when I run the application, the catch block doesn't get called, but I am getting a message that application crashed. What is the problem and how can I fix it?
The code as you described it should handle the exception just fine.
However, the thing that would crash your application is an exception thrown inside an async void method as the exception has no Task to be stored inside.
So, my guess is that SyncFunction actually looks more like this:
public override async void SyncFunction()
{
throw new IOException("test");
}
And when you invoke it the exception is posted to a ThreadPool thread and that crashes the application.
If that's the case, don't use async void unless in a UI event handler and make sure you handle such exceptions by registering to the AppDomain.CurrentDomain.UnhandledException event.

Xamarin Android Questions and Issues when working with WebServices (SOAP .NET 2.0)

I've been working with Xamarin and Webservices (Stated as .NET 2.0 Webservice in Xamarin) in the past few weeks. And I've runned into a few problems that I couldn't figure a workaround yet.
1st) How do I set a timeout for the webservice? The Timeout property is ignored regardless of its value. I believe the default being used is something around 30 seconds. But I'd like 5 seconds~~.
2nd) When the WebService call any method async, using the Begin. Is there anyway to check whether the async method was completed correctly or was timed out? The only way I got to "check" is by perfoming a try/catch in the End method. If it was fired because of a timeout, it will raise an exception. But I wonder if there is some property or method somewhere that would tell me if the webservice call did timeout or was processed correctly. The webservice method being used here is "IsAlive".
WebService.MainService.BeginIsAlive ((ar) =>
{
try
{
bool result = WebService.MainService.EndIsAlive (ar); //If timedout will raise an exception.
RunOnUiThread (() =>
{
Toast.MakeText (this, "Running as expected...", ToastLength.Long).Show();
});
StartActivity (typeof(OtherScreen));
}
catch (Exception ex)
{
//Probably timeout.
}
}, null);
3rd) Is there a way to Cancel a webservice async operation? Such as "CancelIsAlive". The only method I found was Webservice.Abort. But I do not believe it is a best practice and since it is not specific, it may screw everything up.
Thanks in advance, Luís Henrique.
That's what usually I do for calling WebServices and having control on them (assume your ws function needs an string and returns an string):
public static void CallSomeFunction(string SomeParameter, Action<string> Ok, Action Error, Activity Context)
{
ThreadPool.QueueUserWorkItem ((object e) => {
var proxy = new YourProxyClass();
proxy.Timeout = 10000;
try{
var res = proxy.YourFunction(SomeParameter);
Context.RunOnUiThread(() => Ok(res));
}
catch(Exception Ex){
if(Error != null)
Context.RunOnUiThread(Error);
}
});
}
This is how I do asynchronous tasks, use the ThreadPool to make synchronous calls, and pass some Actions to execute if all is ok or wrong. Also I'm passing a Context so my Ok and Error actions be executed in the UI thread.

Catching an exception thrown in an asynchronous callback

I have a method that takes a callback argument to execute asynchronously, but the catch block doesn't seem to be catching any exceptions thrown by the synchronous call (this.Submit refers to a synchronous method).
public void Submit(FileInfo file, AnswerHandler callback)
{
SubmitFileDelegate submitDelegate = new SubmitFileDelegate(this.Submit);
submitDelegate.BeginInvoke(file, (IAsyncResult ar) =>
{
string result = submitDelegate.EndInvoke(ar);
callback(result);
}, null);
}
Is there a way to catch the exception thrown by the new thread and send it to the original thread? Also, is this the "proper" way to handle async exceptions? I wrote my code so it could be called like this (assuming the exception issue is fixed):
try
{
target.Submit(file, (response) =>
{
// do stuff
});
}
catch (Exception ex)
{
// catch stuff
}
but is there a more proper or elegant way to do this?
If you're targeting .NET 4.0, you can utilize the new Task Parallel Library, and observe the Task object's Exception property.
public Task Submit(FileInfo file)
{
return Task.Factory.StartNew(() => DoSomething(file));
}
private void DoSomething(FileInfo file)
{
throw new Exception();
}
Then use it like this:
Submit(myFileInfo).ContinueWith(task =>
{
// Check task.Exception for any exceptions.
// Do stuff with task.Result
});
where DoSomething is the method you'd like call asynchronously, and the delegate you pass to ContinueWith is your callback.
More information about exception handling in TPL can be found here: http://msdn.microsoft.com/en-us/library/dd997415.aspx
This is not a 'best practice' solution, but I think it's a simple one that should work.
Instead of having the delegate defined as
private delegate string SubmitFileDelegate(FileInfo file);
define it as
private delegate SubmitFileResult SubmitFileDelegate(FileInfo file);
and define the SubmitFileResult as follows:
public class SubmitFileResult
{
public string Result;
public Exception Exception;
}
Then, the method that actually does the file submission (not shown in the question) should be defined like this:
private static SubmitFileResult Submit(FileInfo file)
{
try
{
var submissionResult = ComplexSubmitFileMethod();
return new SubmitFileResult { Result = submissionResult };
}
catch (Exception ex)
{
return new SubmitFileResult {Exception = ex, Result = "ERROR"};
}
}
This way, you'll examine the result object, see if it has the Result or the Exception field set, and act accordingly.
In short, no.
When you call submitDelegate.BeginInvoke, it spawns the new thread, returns, and promptly exits your try/catch block (while the new thread runs in the background).
You could, however, catch all unhandled exceptions like this:
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(YourException);
This will catch everything in the application domain, however (not just your async method).

To handle exception with every form or just at main

I have a question about handling exception. I have a Winform that uses a webservice proxy on each form for data retrieval and processing. Here is where I really got confused and having a long time deciding which is better.
A. For each call in the web service do a try catch to display the error message and allow the user to re try the process by clicking the button again.
B. Since the error occurred on the web-service and the error was probably because the web service was inaccessible, just make a generic try catch in the WinMain function in the Program.cs and show an error message that web service is inaccessible before the application closes.
The main argument in this is A is more user friendly but needs a lot of try catch code. B is easier to code but just lets the application ends. I am leaning on A but am trying to search the net with options how to lessen the code needed to be written to do this. Any ideas there?
When you add a web reference, the code generator automatically adds "Async" methods to access the web service.
I would recommend that you use the Async methods rather than the synchronous methods. The nice thing about that is that the EventArgs for the Async methods provide an Error property that you can use to see if the request was successful or not.
private void CheckWebservice(string data)
{
WebService.Server server = new WebService.server();
server.methodCompleted += server_methodCompleted;
server.methodAsync(data);
}
private void server_methodCompleted(object sender, methodCompletedEventArgs e)
{
if (e.Error != null)
if (MessageBox.Show("Error", "Error", MessageBoxButtons.AbortRetryIgore) == DialogResult.Retry)
{
// call method to retry
}
else
{
if (e.Result == "OK") { // Great! }
}
}
If you must use the synchronous methods for some reason, then you could, of course, write a class to encapsulate the methods to call your web service so that you can call it from various places without duplicating the code. Your encapsulation class could do all the error handling and return a result.
class CallWebService
{
public enum Result
{ Unknown, Success, NotAvailable, InvalidData } // etc
public Call(string data)
{
Webservice.Server server = new Webservice.Server();
string result = string.Empty;
try
{
result = server.getResult(data);
}
catch (Exception ex) // replace with appropriate exception class
{
return Result.NotAvailable;
}
if (result == "OK") return Result.Success
else return Result.InvalidData;
}
}
Encapsulate the webservice call and the try/catch block inside a class =)

Categories

Resources