How to serialize an Exception object in C#?

Viewed 86817

I am trying to serialize an Exception object in C#. However, it appears that it is impossible since the Exception class is not marked as [Serializable]. Is there a way to work around that?

If something goes wrong during the execution of the application, I want to be informed with the exception that occurred.

My first reflex is to serialize it.

11 Answers

Create a custom Exception class with the [Serializable()] attribute. Here's an example taken from the MSDN:

[Serializable()]
public class InvalidDepartmentException : System.Exception
{
    public InvalidDepartmentException() { }
    public InvalidDepartmentException(string message) : base(message) { }
    public InvalidDepartmentException(string message, System.Exception inner) : base(message, inner) { }

    // Constructor needed for serialization 
    // when exception propagates from a remoting server to the client.
    protected InvalidDepartmentException(System.Runtime.Serialization.SerializationInfo info,
        System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
}

The Exception class is marked as Serializable and implements ISerializable. See MSDN: http://msdn.microsoft.com/en-us/library/system.exception.aspx

If you are attempting to serialize to XML using the XmlSerializer, you will hit an error on any members that implement IDictionary. That is a limitation of the XmlSerializer, but the class is certainly serializable.

What I've done before is create a custom Error class. This encapsulates all the relevant information about an Exception and is XML serializable.

[Serializable]
public class Error
{
    public DateTime TimeStamp { get; set; }
    public string Message { get; set; }
    public string StackTrace { get; set; }

    public Error()
    {
        this.TimeStamp = DateTime.Now;
    }

    public Error(string Message) : this()
    {
        this.Message = Message;
    }

    public Error(System.Exception ex) : this(ex.Message)
    {
        this.StackTrace = ex.StackTrace;
    }

    public override string ToString()
    {
        return this.Message + this.StackTrace;
    }
}

If you're trying to serialize the exception for a log, it might be better to do a .ToString(), and then serialize that to your log.

But here's an article about how to do it, and why. Basically, you need to implement ISerializable on your exception. If it's a system exception, I believe they have that interface implemented. If it's someone else's exception, you might be able to subclass it to implement the ISerializable interface.

Create a protected constructor like this (also you should mark your Exception class [Serializable]):

protected MyException(System.Runtime.Serialization.SerializationInfo info,
    System.Runtime.Serialization.StreamingContext context):base(info,context)
{
}

I faced a similar problem where I needed to log the details of an Exception thrown in my application, however, it contained a non-serializable member, hence it couldn't be serialized.

As a workaround the .ToString() Method gets called on the Exception which returns a string containing details of the Exception.

string bar;

if (foo is Exception exception)
{
   bar = exception.ToString();
}

Source: Exception.ToString Method

I'm not sure why you would want to serialize the exception...

If I did want to do what you specify, I'd create a custom Exception class that implements ISerializable. You can choose to make it child of Exception or you could have it be a completely custom class that only has and does what you need.

[Serializable]
public class CustomException: Exception
{
    public CustomException: ( Exception exception ) : base(exception.Message)
    {             
        Data.Add("StackTrace",exception.StackTrace);
    }      
}

To serialize your custom exception:

JsonConvert.SerializeObject(customException);
Related