victor
victor

Reputation: 1552

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?

Upvotes: 2

Views: 6466

Answers (3)

Vijay
Vijay

Reputation: 11

The default serializer settings needs to be changed as follows. In Global.aspx,

protected void Application_Start()
{
    var jsonMediaTypeFormatter = GlobalConfiguration.Configuration.Formatters.JsonFormatter;
    jsonMediaTypeFormatter.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.All;
    jsonMediaTypeFormatter.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
}

Upvotes: 1

Brian Rogers
Brian Rogers

Reputation: 129667

GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings only affects Web API calls. Since you are calling JsonConvert.SerializeObject directly, you either need to pass the settings directly to it as shown below or else set up the global default settings as shown in @vendettamit's answer.

var arr = @Html.Raw(@JsonConvert.SerializeObject(Model.Services, new JsonSerializerSettings
                    { PreserveReferencesHandling = PreserveReferencesHandling.All }));

Upvotes: 0

vendettamit
vendettamit

Reputation: 14677

You need to change the DefaultSettings to new ones.

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

Source

Upvotes: 2

Related Questions