ASP.NET Веб-API показывает объекты в формате JSON, о которых я не просил

#c# #json #entity-framework #asp.net-web-api #serialization

#c# #json #entity-framework #asp.net-web-api #сериализация

Вопрос:

У меня есть веб-API с ASP.NET и я пытаюсь вернуть некоторые данные, но это вызывает проблемы, поскольку они ссылаются на объекты, на которые я не хочу ссылаться.

Структура класса в этом случае следующая:

Entitats (сущности), Equips (команды) и Esports (спорт)

У объекта много команд, а у одной команды есть только один вид спорта.

Я использую Entity Framework, и объекты имеют отношения в обоих направлениях; в спорте много команд, а у команды есть сущность.

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

  entitats _entitat = (
                   from e in db.entitats
                       .Include("equips.esports")
                   where e.id == id
                   select e
               ).FirstOrDefault();
  

Это должно дать мне именно то, что я хочу, проблема в том, что в первой команде, когда она показывает мне спорт, спорт содержит все другие команды (из этого объекта), которые имеют тот же вид спорта, а затем, когда пришло время показать их в массиве Team, он использует $ ref и $ id.

 "$id": "1",
"equips": [
    {
        "$id": "2",
        "activitats_concedides": [],
        "activitats_demanades": [],
        "categories": null,
        "categories_competicio": null,
        "competicions": null,
        "entitats": {
            "$ref": "1"
        },
        "esports": {
            "$id": "3",
            // These shouldn't even be here
            "equips": [
                {
                    "$ref": "2"
                },
                {
                    "$id": "4",
                    "activitats_concedides": [],
                    "activitats_demanades": [],
                    "categories": null,
                    "categories_competicio": null,
                    "competicions": null,
                    "entitats": {
                        "$ref": "1"
                    },
                    "esports": {
                        "$ref": "3"
                    },
                    "sexes": null,
                    "id": 8,
                    "nom": "Test 2",
                    "id_entitat": 1,
                    "id_categoria": 3,
                    "id_esport": 1,
                    "id_competicio": 2,
                    "id_categoria_competicio": null,
                    "id_sexe": 3,
                    "borrat": false
                },
                {
                    "$id": "5",
                    "activitats_concedides": [],
                    "activitats_demanades": [],
                    "categories": null,
                    "categories_competicio": null,
                    "competicions": null,
                    "entitats": {
                        "$ref": "1"
                    },
                    "esports": {
                        "$ref": "3"
                    },
                    "sexes": null,
                    "id": 9,
                    "nom": "Test 3",
                    "id_entitat": 1,
                    "id_categoria": 2,
                    "id_esport": 1,
                    "id_competicio": 2,
                    "id_categoria_competicio": null,
                    "id_sexe": 2,
                    "borrat": false
                },
                {
                    "$id": "6",
                    "activitats_concedides": [],
                    "activitats_demanades": [],
                    "categories": null,
                    "categories_competicio": null,
                    "competicions": null,
                    "entitats": {
                        "$ref": "1"
                    },
                    "esports": {
                        "$ref": "3"
                    },
                    "sexes": null,
                    "id": 10,
                    "nom": "prova",
                    "id_entitat": 1,
                    "id_categoria": 3,
                    "id_esport": 1,
                    "id_competicio": 2,
                    "id_categoria_competicio": null,
                    "id_sexe": 2,
                    "borrat": false
                }
            ],
            "id": 1,
            "nom": "Futbol"
        },
        "sexes": null,
        "id": 3,
        "nom": "Test 1",
        "id_entitat": 1,
        "id_categoria": 6,
        "id_esport": 1,
        "id_competicio": 1,
        "id_categoria_competicio": null,
        "id_sexe": 1,
        "borrat": false
    },
    {
        "$ref": "4" // These should be the "full" objects
    },
    {
        "$ref": "5"
    },
    {
        "$ref": "6"
    }
],
"telefons": [],
"id": 1,
"nom": "Futbol Club Sant Cugat del Valles",
"direccio": "Sample Carrer 1",
"cif": "B12345678",
"temporada": "2019                ",
"correu": "entitat1@test.com",
"facebook": null,
"instagram": null,
"twitter": null,
"password": "8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92",
"borrat": true}
  

Я не спрашивал команды по каждому виду спорта, поэтому я не знаю, почему он их показывает. То же самое происходит с объектом Teams, в данном случае это не проблема, потому что это не влияет на вывод, но в других случаях это так. Я полагаю, что это означает, что если он показывает вам объекты, которые вы «спросили», как можно ближе к началу, а затем в том месте, где они вам действительно нужны, он просто ссылается.

Если вы, ребята, знаете, что не так, я был бы очень признателен. Спасибо!

PD: Я безуспешно пытался изменить этот параметр, это только ухудшает ситуацию.

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

Комментарии:

1. Честно говоря, я думаю, вам не следует хранить команды в спортивных состязаниях, а вместо этого добавить эту функциональность в запрос. Если вы получаете sport для команды, вы также получите команды, которые относятся к спорту, потому что эти команды также хранятся в sport.. Вместо этого вы могли бы запросить команды и отфильтровать их по определенному виду спорта. Рассуждения, которые я использую для этого, следующие: команда не может существовать без спорта, но спорт может существовать без каких-либо команд. Я бы сказал, что нет необходимости хранить команды в виде спорта из-за этого, команды уже указывают вид спорта.

2. Проблема в том, что EF сгенерировал эту модель, я, конечно, могу ее изменить, но если бы я мог изменить атрибуты модели для этого конкретного контроллера, это было бы здорово. Моя главная проблема — это JSON, содержащий объекты, о которых я не просил.

3. У команд есть и другие классы, на самом деле их много, но они не отображаются, потому что я их не запрашивал. Похоже, что происходит то, что если у команды есть объект, который находится в JSON (где-нибудь еще, скажем, сущность), он показывает это, с другими объектами в команде этого не происходит.

Ответ №1:

Ваша проблема возникает из-за того, что вы слишком либерально относитесь к своим отношениям с данными. есть два способа решить эту проблему:

  1. приведите в порядок свои взаимосвязи с данными. Примером может служить ваш спортивный объект, его не нужно привязывать к каким-либо командам. У вас есть команды, отлично, с каждой командой связан вид спорта, на этом все заканчивается, есть отношения один на один и ничего больше. Затем вы можете легко создать запрос, который покажет вам все команды, с которыми связан определенный вид спорта.

  2. Сохраните свою структуру такой, какая она есть, но добавьте некоторые DTO для возврата из вашего API, что, честно говоря, и следует делать в первую очередь, какой бы вариант вы ни выбрали. Одна из причин, по которой вы никогда не должны возвращать объекты Entity Framework, заключается в том, что они поставляются со всеми видами данных, которые вам не нужны.

Итак, в вашем запросе, где вы выполняете свой выбор, создайте DTO, который содержит только те поля, которые вы хотите, а затем верните их, и ваша проблема будет решена.

select e становится

 select new EntityDTO {
     assign whatever fields you need here
}
  

Таким образом, вы разрываете свою ссылку на объекты entity Framework и все их зависимости.

Может быть , немного почитайте что — нибудь вроде этого : https://entityframework.net/knowledge-base/12568587/linq-to-sql-select-into-a-new-class