How to fix a missing child object (navigation property) from JSON serialization from C# controller (OData)?

StackOverflow https://stackoverflow.com/questions/22510239

Question

Stack: MVC5, WebAPI, OData, EF6

In a MVC controller, I am returning an object that is serialized to a JSON object:

                .Select(s => new ProjectEditorDTO()
                {
                    // projection
                    WebsiteId = s.WebsiteId,
                    WebsiteGUID = s.WebsiteGUID,
                    WebsiteName = s.WebsiteName,
                    WebsiteNotes = s.WebsiteNotes,
                    Test = "some test string",
                    DefaultContentType = new ContentTypeDTO 
                        { 
                            ContentTypeId = s.DefaultContentTypeID,
                            Description = s.ContentType.Description
                        }
                });

            var r = results.ToList();  // contains DefaultContentType object

            return Ok(results, results.GetType());

The problem is that when I view the returned data in Fiddler, it's missing the DefaultContentType data inside the JSON object.

I have another controller that uses the same object (alone), and returns just fine.

FYI, here is the ContentTypeDTO:

public class ContentTypeDTO
{
    public int ContentTypeId { get; set; }

    [Required]
    [StringLength(100, MinimumLength=3)]
    [Display(Name="Content Type")]
    public string Description { get; set; }

    //public int NumberOfContentTypes { get; set; }

    //public UserDTO UserDTO { get; set; }
}

I am using WebAPI, and have it configured as the following to return JSON content:

        var json = config.Formatters.JsonFormatter;
        json.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.Objects;

        config.Formatters.Remove(config.Formatters.XmlFormatter);

-- UPDATE --

I am using WebAPI and OData, so the resulting call has to contain ProjectEditorDTO object form the ProjectEditor destination:

        modelBuilder.EntitySet<Core.UI.Models.ProjectEditorDTO>("ProjectEditor");              

The data returned from the client is done via an OData URL:

?$format=json&$inlinecount=allpages&$top=10

When I add the $expand= syntax ($format=json&$inlinecount=allpages&$top=10&$expand=DefaultContentTypeID), I get the following error:

Property 'DefaultContentTypeID' on type ... is not a navigation property. Only navigation properties can be expanded.

Even though in the db this is set as a FK.

I'm guessing some expand syntax is missing and ensuring a valid navigation property?

I must be missing something really minor on this... suggestions?

Was it helpful?

Solution

I don't see where the JSON Serialization are. I guess is in the Ok Method. For what I can see, I see that you passed a custom object for treating like a JSON Object. Could yo please try to use a generic object when you project the collection? Just avoiding using your classes to define the objects, something like this:

        .Select(s => new 
        {
            // projection
            WebsiteId = s.WebsiteId,
            WebsiteGUID = s.WebsiteGUID,
            WebsiteName = s.WebsiteName,
            WebsiteNotes = s.WebsiteNotes,
            Test = "some test string",
            DefaultContentType = new 
                { 
                    ContentTypeId = s.DefaultContentTypeID,
                    Description = s.ContentType.Description
                }
        });

OTHER TIPS

Sorry for arriving late, I just read the question. I had the same problem and I fixed it adding the [Key] attribute to the id field in the DTO class. With that in place, the child object is correctly seen as a NavigationProperty and $expand can be called without errors.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top