17

I can't seem to prevent Web API/JSON.NET from using Newtonsoft.Json.PreserveReferencesHandling.Objects when serializing objects. In other words, $id/$ref are always used in the serialized objects despite using the following settings:

public class MvcApplication : System.Web.HttpApplication {

    protected void Application_Start () {
        WebApiConfig.Register(GlobalConfiguration.Configuration);
    }

}

public static class WebApiConfig {

    public static void Register (HttpConfiguration config) {
        JsonMediaTypeFormatter jsonFormatter = config.Formatters.OfType<JsonMediaTypeFormatter>().Single();
        jsonFormatter.UseDataContractJsonSerializer = false;
        jsonFormatter.SerializerSettings.Formatting = Newtonsoft.Json.Formatting.Indented;
        jsonFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
        jsonFormatter.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.None;
    }

}

Any ideas?

Michael
  • 434
  • 1
  • 5
  • 12
  • Setting this in the ``WebApiConfig`` class (``public static void Register (HttpConfiguration config)`` called from the ``protected void Application_Start ()`` within Global.asax.cs – Michael Jan 10 '14 at 20:18
  • 1
    As per @AndreHaverdings' answer below, having PreserveReferencesHandling set to All causes the ids and references to be added. Setting your last line to `jsonFormatter.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.None;` should do the trick. – Buzzwig Jun 09 '14 at 16:28

5 Answers5

26

Put this in the Global.asax to configure reference handling. PreserveReferencesHandling should not be 'All'

GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.None;
Community
  • 1
  • 1
Andre Haverdings
  • 847
  • 8
  • 10
  • I've tried all combinations of PreserveReferencesHandling, including "None." Every settings (currently "None") results in the same output: $id/$ref being output. Something, somewhere must be overriding my setting. – Michael Dec 06 '14 at 21:43
  • @Michael could you fix this error? Can you please help me on this topic : http://stackoverflow.com/questions/41244296/net-webapi-how-to-prevent-ref-x-output-of-json – fobus Dec 20 '16 at 14:40
7

Here is some javascript I'm using to handle the $id/$ref objects on the client side:

// function to return a JSON object form a JSON.NET serialized object with $id/$ref key-values
// obj: the obj of interest.
// parentObj: the top level object containing all child objects as serialized by JSON.NET.
function getJsonNetObject(obj, parentObj) {
    // check if obj has $id key.
    var objId = obj["$id"];
    if (typeof (objId) !== "undefined" && objId != null) {
        // $id key exists, so you have the actual object... return it
        return obj;
    }
    // $id did not exist, so check if $ref key exists.
    objId = obj["$ref"];
    if (typeof (objId) !== "undefined" && objId != null) {
        // $ref exists, we need to get the actual object by searching the parent object for $id
        return getJsonNetObjectById(parentObj, objId);
    }
    // $id and $ref did not exist... return null
    return null;
}

// function to return a JSON object by $id
// parentObj: the top level object containing all child objects as serialized by JSON.NET.
// id: the $id value of interest
function getJsonNetObjectById(parentObj, id) {
    // check if $id key exists.
    var objId = parentObj["$id"];
    if (typeof (objId) !== "undefined" && objId != null && objId == id) {
        // $id key exists, and the id matches the id of interest, so you have the object... return it
        return parentObj;
    }
    for (var i in parentObj) {
        if (typeof (parentObj[i]) == "object" && parentObj[i] != null) {
            //going one step down in the object tree
            var result = getJsonNetObjectById(parentObj[i], id);
            if (result != null) {
                // return found object
                return result;
            }
        }
    }
    return null;
}
Michael
  • 434
  • 1
  • 5
  • 12
  • Thanks for an answer that actually works. I spent the last half hour trying to turn this off in Microsoft WebApi 2.1 – ChrisG Apr 05 '14 at 21:14
7

If using serialization attributes on your objects (such as DataContract), from the JSON.Net documentation on Serialization Attributes:

As well as using the built-in Json.NET attributes, Json.NET also looks for the [SerializableAttribute][2] (if IgnoreSerializableAttribute on DefaultContractResolver is set to false) [DataContractAttribute][3], [DataMemberAttribute][4] and [NonSerializedAttribute][5] ... when determining how JSON is to be serialized and deserialized.

It also says this:

Note

Json.NET attributes take presidence over standard .NET serialization attributes, e.g. if both JsonPropertyAttribute and DataMemberAttribute are present on a property and both customize the name, the name from JsonPropertyAttribute will be used.

It seems the solution to the problem is to add [JsonObject(IsReference = false)] to your object(s) like this:

[DataContract(IsReference = true)]
[JsonObject(IsReference = false)]
public class MyObject
{
    [DataMember]
    public int MyProperty { get; set; }
}
Community
  • 1
  • 1
Michael
  • 434
  • 1
  • 5
  • 12
0

My application was causing error i debugged my asp.net application till it gave me the collection of model causing this issue. just placed the [JsonIgnore] tag and it worked fine.

[JsonIgnore]
public virtual ICollection<customer_details> customer_details { get; set; }

You can manually test by assigning [JsonIgnore] to all ICollection in Model to discover the source of issue.

-2

[JsonIgnore] worked for me. Within the model, include:

    [JsonIgnore] 
    public virtual ICollection<cell_order> cell_order { get; set; }

Unfortunately, this must be done for each case where needed.

Paul Ratazzi
  • 6,289
  • 3
  • 38
  • 50
thazard
  • 17
  • 3