A circular reference was detected while serializing an object of type ‘System.Reflection.RuntimeModule’

When building web services that return JSON you’ll probably come up against a variant of this error when trying to serialize exceptions. (It also occurs with many other types but my solution only deals with exceptions so we’ll stick with that for now)

The reason for the problem, as the error suggests, is a circular reference in the object graph that prevents the serialization from completing. Thankfully this can be easily resolved by implementing a converter to return only the relevant parts of the exception (or any other object):

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Web.Script.Serialization;

namespace MyCompany.MyWidget
{
    internal class ExceptionConverter : JavaScriptConverter
    {
        public override IEnumerable<Type> SupportedTypes
        {
            //Add a list of the type you want to convert here
            get { return new ReadOnlyCollection<Type>(new List<Type>(new[] { typeof(Exception) })); }
        }

        public override object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer)
        {
            if (dictionary == null) throw new ArgumentNullException("dictionary");

            //check that the passed object is of the correct type
            if (type == typeof(Exception))
            {
                //Since we've lost most of the data of the original exception
                //we'll deserialize to a plain Exception object
                var message = dictionary[@"Message"].ToString();
                return new Exception(message);
            }

            return null;
        }

        public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer)
        {
            var exception = obj as Exception;
            if (exception != null)
            {
                var result = new Dictionary<string, object>
                    {
                        //Make sure anything added here is serializable!
                        {@"Type", exception.GetType().ToString()},
                        {@"Message", exception.Message},
                        {@"Source", exception.Source}
                        //add whatever other properties you're interested in seeing on the client
                    };

                return result;
            }
            return new Dictionary<string, object>();
        }
    }
}

This code converts an exception into a dictionary of serializable objects and outputs the dictionary as JSON. You’d use this in your code like this:

public Stream MyWebServiceCall(Stream value)
{
    try
    {
        //Web service foo goes here
    }
    catch (Exception ex)
    {
        //It's all gone wrong. Send an exception to the caller

        var serializer = new JavaScriptSerializer();
        serializer.RegisterConverters(new JavaScriptConverter[] { new ExceptionConverter()});
        string json = serializer.Serialize(ex);
        return new MemoryStream(Encoding.UTF8.GetBytes(json));
    }
}

For all your effort, you’ll now see this in your JSON output: image

Fabulous eh?

This entry was posted in Development, JavaScript, JQuery, WCF. Bookmark the permalink.
  • johnnliu

    I was going to ask why not just specify which members of your class are to be serializable.  Then I realized you are serializing an framework object you can’t control.

    • chaholl

      Nothing’s ever as simple as it should be! All these years of SharePointing and I’ve come to accept that as a fact of life ;)