In C #, how can I serialize a System.Exception? (.Net CF 2.0)

I want to write an exception for the MS message queue. When I try, I get an exception. So I tried to simplify it using the XmlSerializer, which still throws an exception, but it gave me a little more information:

{"An error occurred reflecting the type 'System.Exception'." }

with InnerException:

{"It is not possible to serialize a System.Exception.Data element of type System.Collections.IDictionary because it implements IDictionary." }

Code example:

Exception e = new Exception("Hello, world!"); MemoryStream stream = new MemoryStream(); XmlSerializer x = new XmlSerializer(e.GetType()); // Exception raised on this line x.Serialize(stream, e); stream.Close(); 

EDIT: I tried to make it as simple as possible, but I might have overdone it. I want the entire bit, stack trace, message, custom exception type and custom exception properties. I might even want to add an exception again.

+18
c # exception serialization compact-framework
Dec 23 '08 at 20:51
source share
7 answers

I think you basically have two options:

  • Do your own manual serialization (maybe DO NOT want to do this). XML serialization will certainly not work due to the exact message you receive in the internal exception.
  • Create your own (serializable) exception class, add data from the thrown exception to your own, and serialize.
+7
Dec 23 '08 at 20:57
source share

I watched Jason Jackson's answer, but it didn't make sense to me that I had problems with this, although System.Exception implements ISerializable. So I walked around the XmlSerializer by wrapping an exception in a class that uses BinaryFormatter instead. When the XmlSerialization of MS Message Queuing objects kicks in everything it sees, it is a class with an open byte array.

Here is what I came up with:

 public class WrappedException { public byte[] Data; public WrappedException() { } public WrappedException(Exception e) { SetException(e); } public Exception GetException() { Exception result; BinaryFormatter bf = new BinaryFormatter(); MemoryStream stream = new MemoryStream(Data); result = (Exception)bf.Deserialize(stream); stream.Close(); return result; } public void SetException(Exception e) { MemoryStream stream = new MemoryStream(); BinaryFormatter bf = new BinaryFormatter(); bf.Serialize(stream, e); Data = stream.ToArray(); stream.Close(); } } 

The first test worked fine, but user exceptions still bothered me. So I threw together my own exception. Then I just pressed a button on a blank form. Here is the code:

 [Serializable] public class MyException : Exception, ISerializable { public int ErrorCode = 10; public MyException(SerializationInfo info, StreamingContext context) : base(info, context) { ErrorCode = info.GetInt32("ErrorCode"); } public MyException(string message) : base(message) { } #region ISerializable Members void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) { base.GetObjectData(info, context); info.AddValue("ErrorCode", ErrorCode); } #endregion } private void button1_Click(object sender, EventArgs e) { MyException ex = new MyException("Hello, world!"); ex.ErrorCode = 20; WrappedException reply = new WrappedException(ex); XmlSerializer x = new XmlSerializer(reply.GetType()); MemoryStream stream = new MemoryStream(); x.Serialize(stream, reply); stream.Position = 0; WrappedException reply2 = (WrappedException)x.Deserialize(stream); MyException ex2 = (MyException)reply2.GetException(); stream.Close(); Text = ex2.ErrorCode.ToString(); // form shows 20 // throw ex2; } 

Although it seemed like all the other types of exceptions I was looking for were marked with the SerializableAttribute symbol, I should be careful about custom exceptions that were not marked with the SerializableAttribute symbol.

EDIT: In front of me. I did not understand that BinaryFormatter is not implemented on CF.

EDIT: over the code snippets were in the desktop project. In the CF version, a WrappedException will basically look the same as I just have to implement my own BinaryFormater, but I am very open to suggestions on this.

+10
Dec 23 '08 at 22:11
source share

Comment:

Serializing exceptions is a common task when deleting or interacting with systems across process boundaries. Do not listen to anyone who says otherwise; they probably never wrote a remote library.

Decision:

I tried to do this earlier by creating my own base exception class. The problem I ran into was that System.Exception is not serializing easily, so I had to inherit it. The way I dealt with this was to create my own exceptions that serialized (via ISerializable) and ended any System.Exception in a custom exception.

Throughout your server code, you should use custom exceptions anyway, and they can all be based on your basic type of serialization. This is not much work, and you will quickly create a common exception library to the end.

The layer you write to the queue (and read) must serialize / hydrate the exception. You might think something like this:

 public class WireObject<T, E> { public T Payload{get;set;} public E Exception{get;set;} } 

The server and client levels that are talking to your queue will either wrap the object that you are sending to the payload, or attach an exception (if any). When data is consumed from the queue, the client layer can check for an exception and re-throw it if it is present, otherwise transfer your data.

This is a very simple version of what I wrote before, and what I saw is written by others. Good luck with your project.

+6
Dec 23 '08 at 21:07
source share

Why? Are you creating an exception instance when retrieving from the message queue? If not, just send an exception message (as a string) ...

+2
Dec 23 '08 at 20:54
source share

Well, XML serialization is limited in its use. For example, it cannot serialize this particular scenario. For accurate serialization and deserialization of exceptions, you will need to use BinaryFormatter , which will work as long as your own exceptions are marked [Serializable] . All .Net exceptions are marked with this SerializableAttribute , i.e. they can be serialized using BinaryFormatter .

There is what you need. If your exception is not serializable, it will obviously fail. But that also will not work if your exception contains a field that is not serializable. You must ensure that this is not possible in your custom exceptions.

0
Dec 23 '08 at 23:03
source share

I followed the method suggested in this link (scroll down for the answer sent by a man named Kubilai) and it works great for me. There is no need to create wrapper classes for the exception object.

0
Jun 17 '11 at 19:59
source share

You cannot serialize a dictionary in xml. Do what the other person said and send a message, this is an important bit anyway.

-one
Dec 23 '08 at 20:55
source share



All Articles