views:

5309

answers:

8

Hello all,

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?

UPDATE: 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...

Thanks!

A: 

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.

mson
+4  A: 

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.

mmr
+10  A: 

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) { }
    public InvalidDepartmentException(string message, System.Exception 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) { }
}
David Crow
you should forward parameters to base class
Pavel Savara
+3  A: 

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.

Rex M
+7  A: 

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;
    }
}
davogones
Refer to "Designing Custom Exceptions" http://msdn.microsoft.com/en-us/library/ms229064(v=VS.100).aspx
Shiftbit
+2  A: 

Create protected conctructor like this(also u should mark your Exception class [Serializable]):

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

A: 

Hello, i'm try this http://miscosasdepuntonet.blogspot.com/2010/02/gestion-y-serializacion-de-errores.html . It's a work in progress. It would be better y some days. I'm sorry, my english isn't good. Where i writed CarpetaLog is the name of de Folder to de log, something like "C:\Log".

SRG
+1  A: 

mson wrote: "I'm not sure why you would want to serialize the exception..."

I serialize exceptions to bubble up the exception, through a web service, to the calling object that can deserialize, then rethrow, log or otherwise handle it.

I did this. I simply created a Serializable wrapper class that replaces the IDictionary with a serializable alternative (KeyValuePair array)

/// <summary>
/// A wrapper class for serializing exceptions.
/// </summary>
[Serializable] [DesignerCategory( "code" )] [XmlType( AnonymousType = true, Namespace = "http://something" )] [XmlRootAttribute( Namespace = "http://something", IsNullable = false )] public class SerializableException
{
    #region Members
    private KeyValuePair<object, object>[] _Data; //This is the reason this class exists. Turning an IDictionary into a serializable object
    private string _HelpLink = string.Empty;
    private SerializableException _InnerException;
    private string _Message = string.Empty;
    private string _Source = string.Empty;
    private string _StackTrace = string.Empty;
    #endregion

    #region Constructors
    public SerializableException()
    {
    }

    public SerializableException( Exception exception ) : this()
    {
        setValues( exception );
    }
    #endregion

    #region Properties
    public string HelpLink { get { return _HelpLink; } set { _HelpLink = value; } }
    public string Message { get { return _Message; } set { _Message = value; } }
    public string Source { get { return _Source; } set { _Source = value; } }
    public string StackTrace { get { return _StackTrace; } set { _StackTrace = value; } }
    public SerializableException InnerException { get { return _InnerException; } set { _InnerException = value; } } // Allow null to be returned, so serialization doesn't cascade until an out of memory exception occurs
    public KeyValuePair<object, object>[] Data { get { return _Data ?? new KeyValuePair<object, object>[0]; } set { _Data = value; } }
    #endregion

    #region Private Methods
    private void setValues( Exception exception )
    {
        if ( null != exception )
        {
            _HelpLink = exception.HelpLink ?? string.Empty;
            _Message = exception.Message ?? string.Empty;
            _Source = exception.Source ?? string.Empty;
            _StackTrace = exception.StackTrace ?? string.Empty;
            setData( exception.Data );
            _InnerException = new SerializableException( exception.InnerException );
        }
    }

    private void setData( ICollection collection )
    {
        _Data = new KeyValuePair<object, object>[0];

        if ( null != collection )
            collection.CopyTo( _Data, 0 );
    }
    #endregion
}
Antony Booth