2014-08-18 2 views
0

Я разрабатываю REST API, используя EF 6.0 Code First, AutoMapper и WebApi 2.0.Проблема Seralization в WebApi 2.0

Я борюсь с сериализацией данных или, если быть более конкретным; выбирая то, что должно быть сериализовано при ответе на запрос.

Допустим, я создаю приложение для аа футбольной лиги, которая имеет следующие классы:

public class Player 
{ 
    public String Name { get; set; } 
    public virtual ICollection<Team> Teams { get; set; } // example 
} 

public class Team 
{ 
    public String Name { get; set; } 
    public virtual ICollection<Team> Players { get; set; } 
    public virtual ICollection<FootballGame> Games { get; set; } 
} 

public class FootballGame 
{ 
    public Team Team1 { get; set; } 
    public Team Team2 { get; set; } 
    public DateTime DateTime { get; set; } 
} 

У меня есть контроллер API с именем PlayersController, и нормальный Получить метод URL/API/игроков/идентификатор, который должен вернуть этого игрока.

Однако из-за LazyLoading, сериализации и многие-ко-многим отношений я получаю каждый объект, связанный с этим игроком вернулся:

{ 
    "$id": "1", 
    "Id": 1, 
    "Name": "Jon Jones", 
    "Teams": [ 
    { 
     "$id": "2", 
     "Id": 1, 
     "Name": "Liverpool", 
     "Players": [ 
     { 
      "$id": "3", 
      "Id": 2, 
      "Name": "James White", 
      "Teams": [ 
      { 
       "$ref": "2" 
      }, 
      { 
       "$id": "4", 
       "Id": 2, 
       "Name": "Man Utd", 
       "Players": [ 
       { 
        "$ref": "3" 
       }, 
       { 
        "$id": "5", 
        "Id": 3, 
        "Name": "John Snow", 
        "Teams": [ 
        { 
         "$ref": "2" 
        }, 
        { 
         "$ref": "4" 
        } 
        ] 
       }, 
       { 
        "$ref": "1" 
       } 
       ], 
       "Games": [ 
       { 
        "$id": "6", 
        "Id": 1, 
        "Team1": { 
        "$ref": "2" 
        }, 
        "Team2": { 
        "$ref": "4" 
        }, 
        "DateTime": "2014-08-18T23:20:01.7797942+02:00" 
       }, 
       { 
        "$id": "7", 
        "Id": 2, 
        "Team1": { 
        "$id": "8", 
        "Id": 3, 
        "Name": "Man City", 
        "Players": [ 
         { 
         "$ref": "1" 
         }, 
         { 
         "$ref": "3" 
         }, 
         { 
         "$id": "9", 
         "Id": 4, 
         "Name": "Elton John", 
         "Teams": [ 
          { 
          "$ref": "2" 
          }, 
          { 
          "$ref": "8" 
          } 
         ] 
         } 
        ], 
        "Games": [ 
         { 
         "$ref": "7" 
         }, 
         { 
         "$id": "10", 
         "Id": 5, 
         "Team1": { 
          "$ref": "2" 
         }, 
         "Team2": { 
          "$ref": "8" 
         }, 
         "DateTime": "2014-08-18T23:20:01.7807943+02:00" 
         } 
        ] 
        }, 
        "Team2": { 
        "$ref": "4" 
        }, 
        "DateTime": "2014-08-18T23:20:01.7807943+02:00" 
       } 
       ] 
      }, 
      { 
       "$ref": "8" 
      } 
      ] 
     }, 
     { 
      "$ref": "5" 
     }, 
     { 
      "$ref": "9" 
     } 
     ], 
     "Games": [ 
     { 
      "$ref": "6" 
     }, 
     { 
      "$ref": "10" 
     } 
     ] 
    }, 
    { 
     "$ref": "4" 
    } 
    ] 
} 

Как я могу в простой способ выбрать только вернуть игрока, и для команд, а возвращает URL, где можно можно получить данные команды, что-то вроде:

{ 
    "Id": 1, 
    "Name": "Jon Jones", 
    "Teams": "http://url/api/player/1/teams/" 
} 

Edit: по disabeling lazyloading как было предложено, я просто получаю:

Если это так, то есть ли «лучшая практика», чтобы добавить ури, чтобы получить там команды?

+0

Пожалуйста, просмотрите эту тему: http://stackoverflow.com/questions/25333143/asp-net-web-api-response-looping-data/25333375#25333375 – ntl

ответ

1

Вы должны отключить ленивую загрузку при создании веб-сервисов - это хорошо, чтобы заставить вас быть явным о том, какие данные извлекаются. Альтернативой является сбросить атрибуты [JsonIgnore] на свойства ваших классов, на которые вы не хотите смотреть сериализатор.

0

Как предложил Роберт Леви, вы должны отключить ленивую загрузку. Или вы должны определить DTO (объекты передачи данных) в дополнение к вашим объектам. Это простые объекты, которые не являются частью структуры сущности. Их цель - дать вам возможность определить внешний API, который может отличаться от вашей базы данных. Итак, тогда вы будете запрашивать свои сущности и писать код для сопоставления содержимого ваших POCOs с вашими DTO.

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

Для чего-либо нетривиального, хотя, это может быть полезно для развязывания базы данных дизайн из топологии вашего API.