1

I am trying to propagate to my UI the GatewayConnectionFailedException as you can see. I want this code to catch everything except that exception which I want the presentation layer to catch to notify the user that the database was the problem so he can go and fix it. My problem is that when I throw it the first time then I get GatewayConnectionFailedException not handled by user code on the GatewayException catch clause.

Its also important to note the the GatewayConnectionFailedException extends GatewayException which extends Exception. Is there something I am missing or will I have to move all the catch to the presentation layer ?

        try
        {
             something();
        }
        catch (GatewayConnectionFailedException gcfe)
        {
            throw;
        }
        catch (GatewayException ge)
        {
            if (ge.GetType() == typeof(GatewayConnectionFailedException))
                throw;
            string errMsg = "Records could not be retrieved due to a data gateway error. " + GetTypeInfo();
            _logger.Error(errMsg + "\r\n{0}", ge);
        }
        catch (Exception e)
        {
            if (e.GetType() == typeof(GatewayConnectionFailedException))
                throw;
            string errMsg = "Records could not be retrieved due to an unexpected error. " + GetTypeInfo();
            _logger.Error(errMsg + "\r\n{0}", e);
        }
Stainedart
  • 1,929
  • 4
  • 32
  • 53
  • 4
    Quick note: `throw;` is preferred over `throw e;` when [rethrowing an exception](http://stackoverflow.com/questions/730250/is-there-a-difference-between-throw-and-throw-ex). – Anthony Pegram Jan 13 '12 at 15:30
  • @Carl T: what exception do you throw ? – Tigran Jan 13 '12 at 15:32
  • @Tigran the method something(); throws a GatewayConnectionFailedException which gets caught in the first catch. – Stainedart Jan 13 '12 at 15:33
  • every catch block will catch throw'ed type exception. so you do not use if(ge.GetType() etc etc.... and of course exception base classes must be catched bottom. because catch block work top to bottom. – Nuri YILMAZ Jan 13 '12 at 15:34
  • catches follow a top->down methodology. Is an exception `GatewayConnectionFailedException gcfe` was caught then if won't go to `GatewayException ge`, and that's why you make the most general catch (Exception) to the end. – Lee Scott Jan 13 '12 at 15:34
  • @CarlT.: so if you do it more then one time the catch works ? – Tigran Jan 13 '12 at 15:40
  • you throw an exception, so what you expect to happen here ??? – Tigran Jan 13 '12 at 15:42

6 Answers6

2

Stupid question... is your UI code try-catching in it's call to this layer? Something has to handle that second throw...

In a nutshell, it sounds like you're trying to do this:

using System;

namespace ConsoleApplication1
{
    class ExceptionA : Exception
    {
        public override string Message
        {
            get
            {
                return "Exception A";
            }
        }
    }

    class ExceptionB : ExceptionA
    {
        public override string Message
        {
            get
            {
                return "Exception B";
            }
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                DoThing();
            }
            catch (Exception ex)
            {
                Console.WriteLine("Caught in 'UI' code: " + ex.Message);
            }
        }

        static void DoThing()
        {
            try
            {
                throw new ExceptionB();
            }
            catch (ExceptionB ex)
            {
                Console.WriteLine("Caught B");
                throw;
            }
            catch (ExceptionA ex)
            {
                Console.WriteLine("Caught A");
            }
            catch (Exception ex)
            {
                Console.WriteLine("Caught Generic");
            }
        }
    }
}

Which yields this output:

Caught B
Caught in 'UI' code: Exception B
Press any key to continue...

It just seems like you don't have anything catching the 2nd thrown exception, which is why it's "unhandled." If we comment out the try-catch in main, we end up with an unhandled exception:

static void Main(string[] args)
        {
            //try
            //{
            DoThing();
            //}
            //catch (Exception ex)
            //{
            //Console.WriteLine("Caught in 'UI' code: " + ex.Message);
            //}
        }

Yielding the following output:

Caught B

Unhandled Exception: ConsoleApplication1.ExceptionB: Exception B at ConsoleApplication1.Program.DoThing() in C:\Users\Giovanni\AppData\Local\T emporary Projects\ConsoleApplication1\Program.cs:line 50 at ConsoleApplication1.Program.Main(String[] args) in C:\Users\Giovanni\AppDa ta\Local\Temporary Projects\ConsoleApplication1\Program.cs:line 33 Press any key to continue . . .

Giovanni Galbo
  • 12,963
  • 13
  • 59
  • 78
  • I want my aspx page to catch this database exception so that user can go and fix it. All the other exception I want them caught here. (why the catch Exception e) at the bottom – Stainedart Jan 13 '12 at 15:43
  • Exactly. Try copy and pasting my example and play with it. In DoThing() if you change the throw to ExceptionA, any a plain old Exception() it's caught withing DoThing(); as opposed to ExceptionB it bubbles up to Main(). In this example, Main() is the equivalent of asp.net calling the next layer. – Giovanni Galbo Jan 13 '12 at 15:55
  • Actually this exactly how it is setup where the GatewayConnectionFailedException is a GatewayException. After verification I had a typo in the presentation layer catch it was catching the wrong exception type (gateway connection time out exception) thanks for your help. – Stainedart Jan 13 '12 at 15:59
  • No problem, figured it was something like that. – Giovanni Galbo Jan 13 '12 at 16:00
1

Instead of using throw exceptionName try only throw.

Edit 1:
Try catching all exceptions in the same block, then throw back the exception only if it's the GatewayConnectionFailedException

try
{
     something();
}
catch (Exception e)
{
    if (e.GetType() == typeof(GatewayConnectionFailedException))
        throw;
    string errMsg = "Records could not be retrieved due to an unexpected error. " + GetTypeInfo();
    _logger.Error(errMsg + "\r\n{0}", e);
}
Gabriel GM
  • 6,391
  • 2
  • 31
  • 34
1

One item to not although this might not fix the exception, if you are catching and rethrowing the exception use this code instead:

catch (GatewayConnectionFailedException)
{
    throw;
}

this way the stacktrace reflects the programs journey more accurately. It may not solve the issue though.

Andy Stannard
  • 1,673
  • 2
  • 18
  • 32
  • not it does not. I have changed the syntax now but when the exception is thrown again it gets to the second catch and gives me a GatewayConnectionFailedException not handled by user code – Stainedart Jan 13 '12 at 15:35
  • Is it when debugging? I think it is the debugger breaking out when an exception is thrown. I would just just hit play to carry on debugging and you should get to the error message screen. If it continues to annoy you, you can uncheck a checkbox under debug > Exceptions for various exception types – Andy Stannard Jan 13 '12 at 15:47
1

Hard to tell what is missing without full picture, but one important thing that you should throw exceptions in different way. The syntax should be

throw;

you will have full stacktrace. More info.

Community
  • 1
  • 1
Lukasz Madon
  • 14,664
  • 14
  • 64
  • 108
1

Catching of GatewayConnectionFailedException should solve your problem and in catch block just do throw, don't throw the exception object. Answer by Andy is correct.

Secondly I'm assuming GatewayConnectionFailedException inherits from GatewayException.

Select catch sequence in ascending of order of inheritance, child class should come first and then base class.

catch(Child){}
catch(Base){}
catch(Exception) {} //Base class for all exceptions
Amar Palsapure
  • 9,590
  • 1
  • 27
  • 46
1

to start your try catch is redundant. the first catch will handle GatewayConnectionFailedException the remaining catches will never be of type GatewayConnectionFailedException because they were handled by the first catch. so the code can be simplified to

try
{
    something();
}
catch (GatewayConnectionFailedException)
{
    throw;
}
catch (GatewayException e)
{
    _logger.Error(e.Message, e);
}

Now how the UI will handle this depends on how you handle the exception. if you just throw the exception, then you need a try catch in the presentation layer as well. However if the return type of this layer returned an object like

class Result<T>
{
     T Value {get;set;}
     Exception Error {get;set;}
}

Then you could simply process the type without need try/catch in the presentation layer.

Also worth noting is what you are catching and why you are trying to catch it. typically you don't want to catch Exception except at the application layer where you log the error and fail. Exceptions should be exceptional, and therefore only catch exceptions you expect can happen and why they may happen. otherwise let them bubble up.

Jason Meckley
  • 7,589
  • 1
  • 24
  • 45