Custom Exception Class

I wanted to create a custom class that inherits from System.Exception and adds a few properties and methods specific to the project.

The issue I’m seeing is that a standard try/catch block catches generic Exception class and the compiler thinks that converting that to my custom class is OK. However, at runtime if the actual error is something else like a a System.Net.WebException for instance, then at runtime it will not convert to my custom class. Then my own error catch throws an InvalidCastException.

Obviously the one thing I don’t want to happen is to have my error logging methods throw errors on their own…

So, how can I convert ANY exception to something that my custom class can use?

Here’s a code example:


try {
 //...code that blows up...
} catch (Exception e) {
 //Log and Report Error
 MyErrorClass er = (MyErrorClass)e;
 er.EmailOwner = true;
 er.EmailWebmaster = true;
 er.EventLogType = EventLogEntryType.Error;
 er.ErrorTitle = "Short Description of Error";
 ErrorLogging.ReportError(er);
}

Now, this code builds just fine… VS2008 and VS2010 have no issue with converting an “Exception” to “MyErrorClass”, but at runtime it certainly doesn’t like converting a “WebException” to “MyErrorClass”…

Any advice?

Thanks,
Brandon

For starters, both WebException and your own custom one, are based off the same base type. You still have to take into consideration the rules around widening and narrowing casts.

Fortunately, you aren’t limited to catching one type! You can do this for instance:

try
{
// some part of the coding whereupon it might fail at runtime
}
catch (SystemException e)
{
// block of code that does the error handling for SystemException
}
catch (ApplicationException e)
{
// block of code that does the error handling for ApplicationException
}
catch (ArgumentException e)
{
// block of code that does the error handling for the ArgumentException
}
catch (Exception e)
{
// block of code that does error handling
}
finally
{
// coding that will run no matter what happens before this point
}

The answer of course is to catch specific exceptions as well as generic ones, handling them separately.

On second look, it seems you aren’t trying to implement your own exception at all, but merely doing somethig with the one the system threw?

If so, don’t cast. Inject the exception into the constructor and process it.

MyErrorClass er = new MyErrorClass(e);
// set properties
// call your logger

Thanks, Serenarules.

So on the constructor you’re basically saying I have to map the properties like so:


public class  myErrorClass : Exception
	{
     		public  myErrorClass (Exception e)
     		{
          			// map properties
           this.StackTrace = e.StackTrace;
           this.Message = e.Message;
           //...and so on...
     		}
     		// ... more properties and methods here
	}

I don’t suppose there’s a way to do it without mapping each individual property…

Can a single contructor with the base Exception parameter allow for all other exception types to be sent in (like how the try/catch block apparently works)?

Thanks for you help!
Brandon

Perhaps this is what you want?


class CustomException : Exception
{
    public CustomException(Exception inner)
        : base("some message", inner) // inner exception is the second parameter
    {
    }
}

// and then in your calling code ...

try
{
    throw new FileNotFoundException("hi");
}
catch(Exception ex)
{
    Console.WriteLine(new CustomException(ex).ToString());
}

Designing Custom Exceptions

Hm, so you are deriving from Exception after all. I’d suggest looking at the code and link above.

I’ve followed the examples and still it won’t convert a System.Net.WebException to my custom class.

Here’s the code as it stands.

Code on the page that errors:


try {
// ...code that blows up...
} catch (Exception e) {
 
// Log and Report Error
MyError er = (MyError)e; //exception happens here (Invalid Cast)
er.EmailOwner = true;
er.EmailWebmaster = true;
er.EventLogType = EventLogEntryType.Error;
er.ErrorTitle = "My Error Message";
ErrorLogging.ReportError(er);
}
 

The custom error class:


[Serializable()] 
public class MyError: Exception, ISerializable
{
public MyError() :base()
{
//just run the base Exception constructor
setClassDefaults();
}
public MyError(string message) : base(message) {
//just run the base Exception constructor
setClassDefaults();
}
public MyError(string message, Exception inner) : base(message, inner) {
//just run the base Exception constructor
setClassDefaults();
}
// This constructor is needed for serialization.
protected MyError(SerializationInfo info, StreamingContext context) : base(info, context) {
setClassDefaults();
}
 
private void setClassDefaults(){
this.EmailOwner = false;
this.EmailWebmaster = true;
this.AddEventLog = true;
this.ErrorTitle = "Unknown Website Error";
this.ExceptionText = "Exception detail not provided...";
this.EventLogType = EventLogEntryType.Warning;
}
}

You should be instantiating your custom class using the constructor that takes an inner exception, not trying to cast the exception. Exceptions, like everything in the CLR, are classes and cannot be randomly cast.

Ahhh… of course.

Changing that line from:


MyError er = (MyError)e;

to this:


MyError er = new MyError("Website Exception", e);

Did the trick.

Thanks everyone!