This is an old thread, but worthy of another answer.
@mson wondered why anyone would want to serialize an Exception. Here's our reason for doing it:
We have a Prism/MVVM application with views in both Silverlight and WPF, with the Data Model in WCF services. We want to be sure that data access and updates occur without error. If there is an error, we want to know about it immediately, and let the user know that something may have failed. Our applications will pop a window informing the user of a possible error. The actual exception is then e-mailed to us, and stored in SpiceWorks for tracking. If the error occurs on a WCF service, we want to get the full exception back to the client so this process can happen.
Here is the solution I came up with that can be handled by both WPF and Silverlight clients. The methods below a in a "Common" class library of methods used by multiple applications in every layer.
A byte array is easily serialized from a WCF service. Pretty much any object can be converted into a byte array.
I started with two simple methods, Object2Bytes and Bytes2Object. These convert any object to a Byte array and back. NetDataContractSerializer is from the Windows version of the System.Runtime.Serialization Namespace.
Public Function Object2Bytes(ByVal value As Object) As Byte()
Dim bytes As Byte()
Using ms As New MemoryStream
Dim ndcs As New NetDataContractSerializer()
ndcs.Serialize(ms, value)
bytes = ms.ToArray
End Using
Return bytes
End Function
Public Function Bytes2Object(ByVal bytes As Byte()) As Object
Using ms As New MemoryStream(bytes)
Dim ndcs As New NetDataContractSerializer
Return ndcs.Deserialize(ms)
End Using
End Function
Originally, we would return all results as an Object. If the object coming back from the service was a byte array, then we knew it was an exception. Then we would call "Bytes2Object" and throw the exception for handling.
Trouble with this code is, it's incompatible with Silverlight. So for our new applications I kept the old methods for hard-to-serialize objects, and created a pair of new methods just for exceptions. DataContractSerializer is also from the System.Runtime.Serialization Namespace, but it is present in both the Windows and Silverlight versions.
Public Function ExceptionToByteArray(obj As Object) As Byte()
If obj Is Nothing Then Return Nothing
Using ms As New MemoryStream
Dim dcs As New DataContractSerializer(GetType(Exception))
dcs.WriteObject(ms, obj)
Return ms.ToArray
End Using
End Function
Public Function ByteArrayToException(bytes As Byte()) As Exception
If bytes Is Nothing OrElse bytes.Length = 0 Then
Return Nothing
End If
Using ms As New MemoryStream
Dim dcs As New DataContractSerializer(GetType(Exception))
ms.Write(bytes, 0, bytes.Length)
Return CType(dcs.ReadObject(ms), Exception)
End Using
End Function
When no errors occur, the WCF service returns 1. If an error occurs, it passes the Exception to a method that calls "ExceptionToByteArray," then generates a unique integer from the present time. It uses that integer as a key to cache the byte array for 60 seconds. The WCF service then returns the key value to the client.
When the client sees that it got back an integer other than 1, it makes a call to the Service's "GetException" method using that key value. The service fetches the byte array from cache and sends it back to the client. The client calls "ByteArrayToException" and processes the exception as I described above. 60 seconds is plenty of time for the client to request the exception from the service. In less than a minute, the server's MemoryCache is cleared.
I think this is easier than creating a custom Exception class. I hope this is a help to somebody later on.