Как исправить отсутствующий дочерний объект (свойство навигации) из сериализации JSON из контроллера C# (OData)?

Стек: MVC5, WebAPI, OData, EF6

В контроллере MVC я возвращаю объект, сериализованный в объект JSON:

                .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());

Проблема в том, что когда я просматриваю возвращенные данные в Fiddler, внутри объекта JSON отсутствуют данные DefaultContentType.

У меня есть другой контроллер, который использует тот же объект (отдельно) и отлично возвращается.

К вашему сведению, вот 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; }
}

Я использую WebAPI и настроил его следующим образом для возврата содержимого JSON:

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

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

-- ОБНОВЛЕНИЕ --

Я использую WebAPI и OData, поэтому результирующий вызов должен содержать объект ProjectEditorDTO из пункта назначения ProjectEditor:

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

Данные, возвращаемые клиентом, передаются через URL-адрес OData:

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

Когда я добавляю синтаксис $expand= ($format=json&$inlinecount=allpages&$top=10&$expand=DefaultContentTypeID), я получаю следующую ошибку:

Свойство DefaultContentTypeID для типа... не является свойством навигации. Можно расширить только свойства навигации.

Хотя в db это установлено как FK.

Я предполагаю, что какой-то синтаксис расширения отсутствует и обеспечивает действительное свойство навигации?

Должно быть, я упускаю что-то действительно незначительное в этом... предложения?


person ElHaix    schedule 19.03.2014    source источник
comment
Доступен ли ваш DefaultContentType за пределами объявляющего класса/пространства имен? Может что-то с этим?   -  person dan richardson    schedule 19.03.2014
comment
Внутри ProjectEditorDTO: public ContentTypeDTO DefaultContentType { get; set; }. Это то, что имеется в виду, верно?   -  person ElHaix    schedule 19.03.2014
comment
Да. Это нормально, просто убедитесь, что к нему можно получить доступ, иначе мы могли бы быть здесь уже давно! :)   -  person dan richardson    schedule 19.03.2014
comment
Я думаю, что это больше проблема раскрытия свойства навигации. Я повторно задам вопрос, чтобы отразить это лучше.   -  person ElHaix    schedule 19.03.2014


Ответы (2)


Я не вижу, где сериализация JSON. Я думаю, в методе Ok. Насколько я вижу, я вижу, что вы передали пользовательский объект для обработки как объект JSON. Не могли бы вы попробовать использовать общий объект при проектировании коллекции? Просто избегайте использования ваших классов для определения объектов, например:

        .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
                }
        });
person frikinside    schedule 19.03.2014
comment
Я обновил вопрос, показывающий, где выполняется сериализация JSON. Поскольку я использую WebAAPI и OData, выходной объект определяется как ProjectEditorDTO и должен соответствовать этому. Когда я устанавливаю это в общий тип, я получаю сообщение об ошибке, так как оно должно быть ProjectEditorDTO. - person ElHaix; 19.03.2014
comment
Ой! Я вижу обновление сейчас. Извините за это, я думаю, что мы пишем в одно и то же время. Я не знаю, как это работает, но я думаю, что вам нужно установить свойство DefaultContentType как virtual в вашем классе ProjectEditorDTO. Вы можете это проверить? - person frikinside; 19.03.2014

Извините за опоздание, я только что прочитал вопрос. У меня была та же проблема, и я исправил ее, добавив атрибут [Key] в поле id в классе DTO. При этом дочерний объект правильно воспринимается как NavigationProperty, и $expand можно вызывать без ошибок.

person Ste    schedule 05.08.2015