0

I have a web api that returns a complex object that looks like this:

public class CanDeleteRumsaAttributeResponse
{
    public CanDeleteRumsaAttributeResponse()
    {

    }
    public CanDeleteRumsaAttributeResponse(int attributeId)
    {
        RumsaAttributeId = attributeId;
    }

    public int RumsaAttributeId { get; set; }

    public bool AttributeFound { get; set; }
    public List<RumsaRoom> AffectedRumsaRooms { get; set; } = new List<RumsaRoom>();
    public List<RumsaAttribute> AffectedLinkedRumsaAttributes { get; set; } = new List<RumsaAttribute>();
    [JsonIgnore]
    public bool CanDelete
    {
        get
        {
            return AffectedRumsaRooms.Count == 0&&AttributeFound&&AffectedLinkedRumsaAttributes.Count==0;
        }
    }

}

When I debug it I can see that the controller return that object and that the list AffectedLinkedRumsaAttributes has several objects in the list

When the client receives the list all but the first object are null. I've tried returning the object as Ok(CanDeleteRumsaAttributeResponse) and I've tried serializing it like this:

        RoomAttributesUtils utils = new RoomAttributesUtils(db);
        string json = JsonConvert.SerializeObject(utils.GetCanDeleteColor(id));
        var response = this.Request.CreateResponse(HttpStatusCode.OK);
        response.Content = new StringContent(json, Encoding.UTF8, "application/json");
        return response;

In the second case I can search the json string and find the missing data. So its being serialized in the second case.

I've checked fiddler to see what is being sent and I can see that something is not right in the json-data.

The missing objects gets values like $ref: "4" and so on, but nothing else.

Here is the json-string I'm afraid I dont know how to format it properly for Stackoverflow, but I think that the information is there as well, but when I look at it using a viewer, its not and it sure doesnt deserialize to the correct objects.

The other list in the object can have any number of objects and they all return fine. Also, other endpoints are returning lists of the same type perfectly fine. The three objects have unique values on the Code property and they are V30, V31 and V12 (if you want to identify them in the json string).

Any ideas?

Here is the json string

{"RumsaAttributeId":4797,"AttributeFound":true,"AffectedRumsaRooms":[{"$id":"1","RoomName":"STÄD","RoomNumber":"U12102-1150","Building":"U1","PartOfBuilding":"21","Plan":"02","Number":"1150","RoomDescriptions":[],"IsDeleted":false,"PMs":[],"IDNR":"175D_40","Exclude":false,"Department":"VN40 Lokalvård","Comments":"","Area":"23.19","HygeneClass":null,"CeilingHeight":"","UniqueRoomId":"d00e5325-7918-4d01-b273-813a770b46ca-010591d3","SolviegHasOpenedThis":true,"LastSynchedFromRevit":"1900-01-01T00:00:00","LastUpdatedFromRevit":"1900-01-01T00:00:00","Id":25772}],"AffectedLinkedRumsaAttributes":[{"$id":"2","AMACode":"KBC.3211","Malning":"56-03510","AvaliableColors":[{"$id":"3","AvaliableMaterials":[{"$ref":"2"},{"$id":"4","AMACode":"MBE.221","Malning":"-","AvaliableColors":[{"$ref":"3"}],"RoomDescriptions":[],"Code":"V30","ShortDescription":"Kakel, vattenavvisande beklädnad","LongDescription":"-","Comment":"-","PartOfRoom":null,"PartOfRoomId":960,"Id":1438},{"$id":"5","AMACode":"MBE.222","Malning":"-","AvaliableColors":[{"$ref":"3"}],"RoomDescriptions":[],"Code":"V31","ShortDescription":"Kakel, vattentät beklädnad","LongDescription":"-","Comment":"-","PartOfRoom":null,"PartOfRoomId":960,"Id":1439}],"RoomDescriptions":[],"Code":"V31_01","ShortDescription":"Kakel, vattentät beklädnad","LongDescription":"Marazzi SistemC Arch ME83, kulör Bianco(vit)200x200x5 mm. Fog Mapei Ultracolor Plus kulör 111 Silver Grey","Comment":"På 1 fondvägg","PartOfRoom":null,"PartOfRoomId":960,"Id":4797}],"RoomDescriptions":[],"Code":"V12","ShortDescription":"Gipsskivor, hygienklass 2","LongDescription":"Hög standard, hygienklass 2\n","Comment":"-","PartOfRoom":null,"PartOfRoomId":960,"Id":1425},{"$ref":"4"},{"$ref":"5"}]}
Erik83
  • 539
  • 3
  • 5
  • 19
  • `$ref` is an actual value you're sending? Or is that the bug? – Yuval Itzchakov Aug 31 '16 at 06:51
  • The $ref is what I can read in a viewer, but now that Im looking at it again I think Im misstaken there: the $ref is something else, they exist separetly in the json string. Its like the deserializer skips 2 objects... – Erik83 Aug 31 '16 at 06:59
  • When serializing, you must have enabled [`PreserveReferencesHandling`](http://www.newtonsoft.com/json/help/html/preserveobjectreferences.htm). This functionality tracks all object references in the object graph and when an object is encountered more than once, it is tagged with a reference to the first object - the `$ref` you are seeing. You need to deserialize with the same setting, or disable it on the server. – dbc Aug 31 '16 at 07:29
  • Also, just in case you are using entity framework, see [Json.Net adding $id to EF objects despite setting PreserveReferencesHandling to “None”](https://stackoverflow.com/questions/18128689/json-net-adding-id-to-ef-objects-despite-setting-preservereferenceshandling-to). Otherwise see [how to remove $id during JSON serialization](https://stackoverflow.com/questions/11542144/how-to-remove-id-during-json-serialization). For background see [What is the difference between PreserveReferencesHandling and ReferenceLoopHandling in Json.Net?](https://stackoverflow.com/questions/23453977) – dbc Aug 31 '16 at 07:36
  • Im using entity framework. Ok, I've tried setting preservereferenceshandling to All and None, with the same result. I checked your first link and Im not having a custom contractresolver. Do I still need to do that? – Erik83 Aug 31 '16 at 09:04
  • Also its funny how the ids in the json does not exist except in the $ref. Shouldnt there be an object that its pointing to? – Erik83 Aug 31 '16 at 09:05
  • The value in the `"$ref" : X` property referrs to the value in the `"$id" : X` property added previously. For instance, for `"$ref":"4"` you will see `"$id":"4"` earlier in the JSON. You might also have global serializer settings as shown [here](https://stackoverflow.com/questions/13274625) or [here](https://stackoverflow.com/questions/21815759) that enables this functionality. Beyond that I can't guess how the setting is getting enabled without a [mcve]. – dbc Aug 31 '16 at 19:18
  • Yes, but the "$id":"4" does only exists in the raw json string. When you look at it with a viewer its not there. I couldnt find a solution so I split the complex type into several types. That worked fine for a while, but I keep getting this problem. I tried to look at the serializer settings at runtime and I cant see anything that does not look like what I've set on purpose. – Erik83 Sep 01 '16 at 12:15

1 Answers1

1

I had a similar situation in which I found that due to circular references, the serialization was not completed.

public class Blog
{
    public int BlogId { get; set; }
    public string Url { get; set; }

    public List<Post> Posts { get; set; }
}

public class Post
{
    public int PostId { get; set; }
    public string Title { get; set; }
    public string Content { get; set; }

    public int BlogForeignKey { get; set; }

    [ForeignKey("BlogForeignKey")]
    public Blog Blog {get;set;}

}

I just deleted the child to parent relationship and included the foreingkey anotation to the entity set.

public class Blog
{
    public int BlogId { get; set; }
    public string Url { get; set; }

    [ForeignKey("BlogForeignKey")]
    public List<Post> Posts { get; set; }
}

public class Post
{
    public int PostId { get; set; }
    public string Title { get; set; }
    public string Content { get; set; }

    public int BlogForeignKey { get; set; }
}

Also consider LoopReferenceHandling