victor victor - 3 months ago 33
C# Question

Circular reference while serializing EF model to Json

I know that are tons of questions related to this topic all over SO but none of them solved my problem.

I'm using MVC 5 with Entity Framework 6 and Newtonsoft.Json.

I have the usual scenario for this exception:

Service => Staff => Service


When I try to serialize a
service
object in my view, like this:

var arr = @Html.Raw(@JsonConvert.SerializeObject(Model.Services));


I get the "
circular reference was detected while serializing an object of type...
" exception.

All the answers I found here say it is wasy to solve, I should just add

GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings
.PreserveReferencesHandling = PreserveReferencesHandling.All;

GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings
.ReferenceLoopHandling = ReferenceLoopHandling.Serialize;


in my
Global.asax
file.

Well, I did, and it just doesn't work. I read a bunch of articles on MSDN an they all say the same thing. I don't know why, but it just doesn't work for me.

The only way I could make it work, was to create the whole serialization context in my controller:

var settings = new JsonSerializerSettings
{
PreserveReferencesHandling = PreserveReferencesHandling.All,
ReferenceLoopHandling = ReferenceLoopHandling.Serialize
};


var serializer = JsonSerializer.Create(settings);
var msmStream = new MemoryStream();
var txtWriter = new StreamWriter(msmStream);
var writer = new JsonTextWriter(txtWriter) { Formatting = Formatting.Indented };
serializer.Serialize(writer, services);

var json = Encoding.ASCII.GetString(msmStream.GetBuffer());


However, this is a terrible terrible solution, specially if I'm serializing a property from my view model on the fly in the view. It also defeats the whole purpose of a "global configuration".

Has anybody faced this problem?

Answer

You need to change the DefaultSettings to new ones.

JsonConvert.DefaultSettings = () => new JsonSerializerSettings
{
    PreserveReferencesHandling = PreserveReferencesHandling.All,
    ReferenceLoopHandling = ReferenceLoopHandling.Serialize
};

Source