7
catch(Exception ex)
{
    //do what you want here

    //When type of exception is System.Web.Services.Protocols.SoapException
    //if (ex.Code.Name.Equals("Client"))
    //{
    //      msg = "service's function not exist";
    //}
    //else if (ex.Code.Name.Equals("Server"))
    //{
    //     msg = "function error"
    //}
    //else
    //{
    //     msg = "unknown";
    //}
    //MessageBox.Show(msg, "error", MessageBoxButtons.OK);

**But ex is not System.Web.Services.Protocols.SoapException so I cannot call ex.Code.Name.Equals("Client")**


//When System.Net.WebException
//switch (ex.Status)
//{
//   case System.Net.WebExceptionStatus.ConnectFailure:
//              do some thing
                break;
//   case System.Net.WebExceptionStatus.Timeout:
                //do some thing
                break;
//    case System.Net.WebExceptionStatus.ProtocolError:
            switch (((System.Net.HttpWebResponse)ex.Response).StatusCode)
            {
                  case System.Net.HttpStatusCode.NotFound:
                        //do some thing
                        break;
                    case System.Net.HttpStatusCode.ServiceUnavailable:
                        //do some thing
                        break;
                    case System.Net.HttpStatusCode.Unauthorized:
                        //do some thing
                        break;
                    default:
                        //do some thing
                        break;
                }
                break;
            default:
                //do some thing
                break;
        }
}

But Exception is not System.Net.WebException. So cannot call ex.Status

My problem:

I have a Smartclient software include WindowsForm as client and a webservice as server. Client and Server both are n-tiers application I have tested and found that has any problem when call service from Client

  1. in app.config: service's path wrrong . I catch System.NotSupportedException
  2. Or when the server cannot connect: System.Net.WebExceptionStatus
  3. Server's webconfig is wrong : System.InvalidOperationException
  4. Service throws an exception: System.Web.Services.Protocols.SoapException ...

My Idea

I call the Exception that as representative of all other exception types is representativeAlException I have namespace : Common and two classese representativeAlException.cs and BusinessExceptionHandler.cs

Make a common function with a param as (representativeAlException ex)

            try
            {
                Err_LogCheck.Service1.Service1 service = new Err_LogCheck.Service1.Service1();
                return service.getDeviceByZero(ZERO);
            }
            catch (Common.representativeAlException ex)
            {
                Common.BusinessExceptionHandler.ProcessException(ex);
            }

What I want to do

Where the service is called. Only one catch block can handler for all type of Exception

in ProcessException(representativeAlException ex) function

switch (ex)
{
case System.InvalidOperationException:
 //Do some thing
 break;
case System.NotSupportedException:
 //Do some thing
 break;
case System.Web.Services.Protocols.SoapException:
 //do some thing
 break;
...
...
3
  • Try my answer, I cast ex to specific exception so you can use the methods and properties of that specific exception.
    – kazinix
    Commented Oct 4, 2012 at 3:11
  • Seriously, don't do a catch-all exception block. It's a bad programming practice. Only catch specific exceptions. Commented Oct 4, 2012 at 3:36
  • i do catch-all in any where. But the exception is separated to any type in a common function Commented Oct 4, 2012 at 3:53

4 Answers 4

16

To handle all exception, use Exception class.

try
{

}
catch(Exception ex)
{
     switch (ex.GetType().ToString())
     {
         case "System.InvalidOperationException":
              //cast ex to specific type of exception to use it's properties
              ((InvalidOperationException)ex).SomeMethod();
         break;
         case "System.NotSupportedException":
             ((System.NotSupportedException)ex).AnotherMethod();
         break;
         case "System.Web.Services.Protocols.SoapException":
             ((System.Web.Services.Protocols.SoapException)ex).OtherMethod();
         break;
     }

}

Why can't you just use multiple catch block anyway?

18
  • ex is not Exception. "I call the Exception that as representative of all other exception types is representativeAlException". My catch block is : catch (Common.representativeAlException ex) Commented Oct 4, 2012 at 1:13
  • 2
    Your question is not clear so I assumed you want to handle all types of exception. I'm trying to help but all I get is downvote.
    – kazinix
    Commented Oct 4, 2012 at 1:16
  • i am sorry because of my bad english. I want to do that: where the webservice is called, using only one catch block instead of many catch block for many exception types. And in my common function, i will check type of exception and send each message to end-user Commented Oct 4, 2012 at 1:20
  • 1
    Have you tried my codes, it's meant to catch all types of exception.
    – kazinix
    Commented Oct 4, 2012 at 1:25
  • This is the answer, best as I can tell, based on the question. I'm not sure why it got downvoted.
    – siride
    Commented Oct 4, 2012 at 1:27
10

This is now a language feature. Just use a switch/case statement

The asker's first attempt, shown commented out in the code snippet in the question, is now the easiest and in my opinion best way to do this.

I actually came across this question while trying to figure out what Resharper had done with one of its suggested improvements. I'm still not 100% sure on the terminology involved as the only documentation I could find was explaining Discards and only mentions in passing the "pattern matching with the is and switch keywords" that is also being performed.

I had started, as Onkel-j reccomends, with a chain of 'if ex is Type':

try
{
    doWork();
}
catch (Exception ex)
{
    if (ex is SpecificExceptionType)
    {
        //todo
    }
    else 
    {
        //etc
    }
}

but resharper suggested I let it change this to a switch/case:

try
{
    doWork();
}
catch (Exception ex)
{
    switch (ex)
    {
        case SpecificExceptionType _:
            //todo
            break;            
        default:
            //etc
            break;
    }
}

Resharper has used Discards to do a sort of automatic is and toss out the unused variable. If you need to actually use the exception as the specific type, give it a name in place of the underscore:

try
{
    doWork();
}
catch (Exception ex)
{
    switch (ex)
    {
        case SpecificExceptionType specific:
            HandleSpecificException(specific);
            break;            
        default:
            //etc
            break;
    }
}

Or to answer the original question:

catch(Exception ex)
{
    //do what you want here
    
    switch(ex)
    {
        case System.Web.Services.Protocols.SoapException soapEx:        
            if (soapEx.Code.Name.Equals("Client"))
            {
                  msg = "service's function not exist";
            }
            else if (soapEx.Code.Name.Equals("Server"))
            {
                 msg = "function error"
            }
            else
            {
                 msg = "unknown";
            }
            MessageBox.Show(msg, "error", MessageBoxButtons.OK);    
            break;
        case System.Net.WebException webEx:
            switch (webEx.Status)
            {
               case System.Net.WebExceptionStatus.ConnectFailure:
                    //do some thing
                    break;
               case System.Net.WebExceptionStatus.Timeout:
                    //do some thing
                    break;
                case System.Net.WebExceptionStatus.ProtocolError:
                    switch (((System.Net.HttpWebResponse)webEx.Response).StatusCode)
                    {
                        case System.Net.HttpStatusCode.NotFound:
                            //do some thing
                            break;
                        case System.Net.HttpStatusCode.ServiceUnavailable:
                            //do some thing
                            break;
                        case System.Net.HttpStatusCode.Unauthorized:
                            //do some thing
                            break;
                        default:
                            //do some thing
                            break;
                    }
                    break;
                default:
                    //do some thing
                    break;
            }
            break;
        default:
            //etc
            break;
    }
}
7

User2808350 is correct that try catch blocks can have many different catches for a reason, however sometimes you find you are repeating yourself (DRY) when using this pattern.

An alternative that can result in concise, readable code is to use the is operator which evaluates to true if your exception is an instance of a particular type or one that derives from that type. Unfortunately it's not possible to use the is operator in a switch block, so you have to use if-then-else.

Here is an example where I test the exception type and set the exit code accordingly.

try
{
    // try something
}
catch (Exception e)
{
    if (e is FileNotFoundException)
        Environment.ExitCode = 2;
    else if (e is InvalidOperationException)
        Environment.ExitCode = 1;
    else
        Environment.ExitCode = 42;
    throw;
}
2
  • Upvoting, because mentioning the DRY principle. Which is why I ended up doing it this way. Commented Dec 2, 2015 at 11:40
  • Reading this exact code is noticeably harder compared to switch statements, which can be inlined due to short lines. While this is not wrong, I doubt using "is" is worth the added reading complexity.
    – Felini
    Commented Apr 15, 2018 at 8:11
1

Should use

try {

    ....

}
catch (System.Net.HttpStatusCode.NotFound)
{
 //do some thing
}    
catch (System.Net.HttpStatusCode.ServiceUnavailable)
{
 //do some thing
}

catch (System.Net.HttpStatusCode.Unauthorized)
{
 //do some thing
}

catch (System.Net.HttpStatusCode.NotFound)
{
 //do some thing
}    
catch (Exception)
{
 //do some thing
}

It's better that using swicth

1
  • 4
    This doesn't answer original question, neither any proof for "this way is better" was provided.
    – Felini
    Commented Apr 15, 2018 at 8:05

Not the answer you're looking for? Browse other questions tagged or ask your own question.