I have the following code in my ServiceBase abstract class:
internal ServiceResponse ExecuteNonQuery(Action action)
{
try
{
action();
return new ServiceResponse() { IsFaulty = false };
}
catch (DbEntityValidationException e)
{
OnDbEntityValidationException(e);
return new ServiceResponse() { IsFaulty = true, Exception = e};
}
catch (Exception e)
{
_logger.Log(e);
return new ServiceResponse() {IsFaulty = true, Exception = e};
}
}
All my services derives from this class and my WCF service endpoint looks like this:
public ServiceResponse Add(Client client)
{
_logger.LogInformation($"ClientService.Add()");
return ExecuteNonQuery(() =>
{
using (var context = _contextFactory.Build())
{
context.Clients.Add(_serviceToDalMapper.Map(client));
context.SaveChanges();
}
});
}
On the client side I have similar Try/Catch method when calling my service.
What I don't understand is that when an exception is thrown on the service side, the exception is catch, but I still get an System.ServiceModel.CommunicationException on the client side. Why ? I catched my exception, shouldn't my service just return the ServiceResponse?
Add a try-catch inside your current catch, looks like the call is generating an exception, possibly generated inside the catch.
catch (DbEntityValidationException e)
{
try
{
OnDbEntityValidationException(e);
return new ServiceResponse() { IsFaulty = true, Excepetion = e};
}
catch
{
return new ServiceResponse() { IsFaulty = true, Excepetion = new Exception("Error handling the error")};
}
}
WCF can't serialize the Exception object (which makes sense in a way).
So an exception was thrown in my catch block, that's the fault here.
According to WCF best practices, I should be using FaultContract to communicate exception to the client.
Related
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?
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.";
}
}
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);
}
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);
}
When an exception is possible to be thrown in a finally block how to propagate both exceptions - from catch and from finally?
As a possible solution - using an AggregateException:
internal class MyClass
{
public void Do()
{
Exception exception = null;
try
{
//example of an error occured in main logic
throw new InvalidOperationException();
}
catch (Exception e)
{
exception = e;
throw;
}
finally
{
try
{
//example of an error occured in finally
throw new AccessViolationException();
}
catch (Exception e)
{
if (exception != null)
throw new AggregateException(exception, e);
throw;
}
}
}
}
These exceptions can be handled like in following snippet:
private static void Main(string[] args)
{
try
{
new MyClass().Do();
}
catch (AggregateException e)
{
foreach (var innerException in e.InnerExceptions)
Console.Out.WriteLine("---- Error: {0}", innerException);
}
catch (Exception e)
{
Console.Out.WriteLine("---- Error: {0}", e);
}
Console.ReadKey();
}
I regularly come into the same situation and have not found a better solution yet. But I think the solution suggested by the OP is eligible.
Here's a slight modification of the original example:
internal class MyClass
{
public void Do()
{
bool success = false;
Exception exception = null;
try
{
//calling a service that can throw an exception
service.Call();
success = true;
}
catch (Exception e)
{
exception = e;
throw;
}
finally
{
try
{
//reporting the result to another service that also can throw an exception
reportingService.Call(success);
}
catch (Exception e)
{
if (exception != null)
throw new AggregateException(exception, e);
throw;
}
}
}
}
IMHO it will be fatal to ignore one or the other exception here.
Another example: Imagin a test system that calibrates a device (DUT) and therefore has to control another device that sends signals to the DUT.
internal class MyClass
{
public void Do()
{
Exception exception = null;
try
{
//perform a measurement on the DUT
signalSource.SetOutput(on);
DUT.RunMeasurement();
}
catch (Exception e)
{
exception = e;
throw;
}
finally
{
try
{
//both devices have to be set to a valid state at end of the procedure, independent of if any exception occurred
signalSource.SetOutput(off);
DUT.Reset();
}
catch (Exception e)
{
if (exception != null)
throw new AggregateException(exception, e);
throw;
}
}
}
}
In this example, it is important that all devices are set to a valid state after the procedure. But both devices also can throw exceptions in the finally block that must not get lost or ignored.
Regarding the complexity in the caller, I do not see any problem there either. When using System.Threading.Tasks the WaitAll() method, for example, can also throw AgregateExceptions that have to be handled in the same way.
One more note regarding #damien's comment: The exception is only caught to wrap it into the AggregateException, in case that the finally block throws. Nothing else is done with the exception nor is it handled in any way.
For those who want to go this way you can use a little helper class I created recently:
public static class SafeExecute
{
public static void Invoke(Action tryBlock, Action finallyBlock, Action onSuccess = null, Action<Exception> onError = null)
{
Exception tryBlockException = null;
try
{
tryBlock?.Invoke();
}
catch (Exception ex)
{
tryBlockException = ex;
throw;
}
finally
{
try
{
finallyBlock?.Invoke();
onSuccess?.Invoke();
}
catch (Exception finallyBlockException)
{
onError?.Invoke(finallyBlockException);
// don't override the original exception! Thus throwing a new AggregateException containing both exceptions.
if (tryBlockException != null)
throw new AggregateException(tryBlockException, finallyBlockException);
// otherwise re-throw the exception from the finally block.
throw;
}
}
}
}
and use it like this:
public void ExecuteMeasurement(CancellationToken cancelToken)
{
SafeExecute.Invoke(
() => DUT.ExecuteMeasurement(cancelToken),
() =>
{
Logger.Write(TraceEventType.Verbose, "Save measurement results to database...");
_Db.SaveChanges();
},
() => TraceLog.Write(TraceEventType.Verbose, "Done"));
}
As the comments have suggested this may indicate "unfortunately" structured code. For example if you find yourself in this situation often it might indicate that you are trying to do too much within your method. You only want to throw and exception if there is nothing else you can do (your code is 'stuck' with a problem you can't program around. You only want to catch an exception if there is a reasonable expectation you can do something useful. There is an OutOfMemoryException in the framework but you will seldom see people trying to catch it, because for the most part it means you're boned :-)
If the exception in the finally block is a direct result of the exception in the try block, returning that exception just complicates or obscures the real problem, making it harder to resolve. In the rare case where there is a validate reason for returning such as exception then using the AggregateException would be the way to do it. But before taking that approach ask yourself if it's possible to separate the exceptions into separate methods where a single exception can be returned and handled (separately).
I receive an exception of type
Exception receiving EMS message: The service did not respond.
When calling the code below from more than one task.
Task.Factory.StartNew(() =>
{
var service = CreateChannel();
try
{
return service.GetStuff(string blah);
}
finally
{
var channel = ((IClientChannel)service);
try
{
channel.Close();
}
catch
{
channel.Abort();
}
}
});
private IService CreateChannel()
{
lock (_channelFactory)
{
return _channelFactory.CreateChannel();
}
}
If i remove the Channel.Close() there is no exception.
Any ideas?
Self Answer
Updating my tibco.ems.wcf assembly fixed this.
I am creating a utility class that will be used in my Facebook application for tasks that are commonly done, such as retrieving a Facebook Page ID from a URL. I am unsure if the below code is the correct way to throw and catch exceptions. Could someone please advise, thanks.
Utility Class:
public static class FacebookUtilities
{
public static string GetPageIDFromGraph(string pageUri, string accessToken)
{
try
{
FacebookClient client = new FacebookClient(accessToken);
dynamic result = client.Get(GetPageIDFromUri(pageUri), new { fields = "id" });
return result.ToString();
}
catch (FacebookOAuthException)
{
throw;
}
catch (FacebookApiException)
{
throw;
}
}
public static string GetPageIDFromUri(string pageUri)
{
if (pageUri.Contains('/'))
pageUri = pageUri.Substring(pageUri.LastIndexOf('/') + 1);
if (pageUri.Contains('?'))
return pageUri.Substring(0, pageUri.IndexOf('?'));
else
return pageUri;
}
}
Program class, just testing:
- Note "input" and "output" are just textboxes.
private void btnGetPageID_Click(object sender, EventArgs e)
{
try
{
output.Text = FacebookUtilities.GetPageIDFromGraph(input.Text, "Some Access Token Goes Here");
}
catch (FacebookOAuthException ex)
{
if (ex.ErrorCode == 803)
{
output.Text = "This page does not exist";
}
}
catch (FacebookApiException ex)
{
if (ex.ErrorCode == 100)
{
output.Text = "The request was not supported. The most likely cause for this is supplying an empty page ID.";
}
}
}
Is it correct to simply rethrow the exception from the utility class so that the calling class can catch it and do what needs to be done?
It seems that you do nothing with catched exceptions - so dont catch them. There are a lot of discussions about exception handling, but in general you should catch exceptions when you have something to do with them, or at least using finally to clean up resourses.
Since you aren't handling the exceptions in any way, your code can just be:
public static string GetPageIDFromGraph(string pageUri, string accessToken)
{
FacebookClient client = new FacebookClient(accessToken);
dynamic result = client.Get(GetPageIDFromUri(pageUri), new { fields = "id" });
return result.ToString();
}
You should only catch exceptions when you can meaningfully handle them, and it doesn't look like you can in your GetPageIDFromGraph method, so you should just propagate them.
I have a WCF service that I am consuming, and have been doing well so far.
However on our production system with a lot of traffic, I am noticing that that after gradual consistent rise and falls in memory (time in between gradually elongates and the delta gradually increases), the memory consumption is trending higher.
I'm wondering if it could be due to the way I am consuming the DAL web service:
For example:
public static int GetUserTypeFromProfileID(int profileID)
{
try
{
memberServiceClient = new MemberServiceClient(); // connect to the data service
return memberServiceClient.GetUserTypeFromProfileID(profileID); // get the profileID associated with the sessionID
}
catch (Exception ex)
{
ErrorLogging.Instance.Fatal(ex);
return 0;
}
}
If I changed this to the following, using a using statement:
public static int GetProfileIDFromSessionID(string sessionID)
{
try
{
using (memberServiceClient = new MemberServiceClient()) // connect to the data service
{
return memberServiceClient.GetProfileIDFromSessionID(sessionID); // get the profileID associated with the sessionID
}
}
catch (Exception ex)
{
ErrorLogging.Instance.Fatal(ex);
return 0;
}
}
Is it good form to perform the return inside the using section?
I believe there is nothing specific to WCF with using statement. It will dispose your MemberServiceClient before returning the value.
However Dispose() method on a WCF service client calls Close() method inside, which can throw exceptions. So it's better to call Close() method directly. You should also call Abort() method when exceptions occur. Here's the recommended implementation.
var result;
try
{
memberServiceClient = new MemberServiceClient();
result = memberServiceClient.GetUserTypeFromProfileID(profileID);
memberServiceClient.Close();
}
catch (FaultException e)
{
//handle exception
memberServiceClient.Abort();
}
catch (CommunicationException e)
{
//handle exception
memberServiceClient.Abort();
}
catch (TimeoutException e)
{
//handle exception
memberServiceClient.Abort();
}
Note: I have written a simple base class that handles these details. It's on NuGet.
Update:
Here's an example with WcfClientBase as requested:
public class MemberServiceManager : ServiceClientBase<MemberServiceClient>
{
public int GetUserTypeFromProfileID(int profileID)
{
//makes a call to GetUserTypeFromProfileID operation, closes the channel and handles the exceptions
//you may want to implement another base class for overriding exception handling methods
//return value will be default of return type if any exceptions occur
return PerformServiceOperation(item => item.GetUserTypeFromProfileID(profileID));
}
//or you can manually check if any exceptions occured with this overload
public bool TryGetUserTypeFromProfileID(int profileID, out int userType)
{
return TryPerformServiceOperation(item => item.GetUserTypeFromProfileID(profileID), out userType);
}
//these exception handling methods should be overriden in another common subclass
//they re-throw exceptions by default
protected override void HandleCommunicationException(CommunicationException exception)
{
Console.WriteLine(exception.Message);
}
protected override void HandleFaultException(FaultException exception)
{
Console.WriteLine(exception.Message);
}
protected override void HandleTimeoutException(TimeoutException exception)
{
Console.WriteLine(exception.Message);
}
}
You can also take a look at the source code on GitHub