Ember-Data: как работают "сопоставления"

В настоящее время я пытаюсь скомпоновать что-то вместе с ember + emberdata + router + asp.net web api. Большинство из них, похоже, работают, однако я застрял в сообщении об ошибке, которое я получаю, когда данные ember-data пытаются выполнить findAll через адаптер для моих моделей.

В моем бэкенде у меня есть такая модель (С#):

public class Genre {
    [Key]
    public int Id { get; set; }
    [Required]
    [StringLength(50, MinimumLength=3)]
    public string Name { get; set; }
}

Что в моем приложении я представляю это так, используя ember-data:

App.Genre = DS.Model.extend({
    id: DS.attr("number"),
    name: DS.attr("string")
}).reopenClass({
    url: 'api/genre'
});

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

App.store = DS.Store.create({
    revision: 4,
    adapter: DS.RESTAdapter.create({
        bulkCommit: false
    })
});

И магазин используется в моем контроллере, как показано ниже:

App.GenreController = Ember.ArrayController.extend({
    content: App.store.findAll(App.Genre),
    selectedGenre: null
});

Маршрутизатор определяется как

App.router = Em.Router.create({
    enableLogging: true,
    location: 'hash',
    root: Ember.Route.extend({
        //...

        genre: Em.Route.extend({
            route: '/genre',
            index: Ember.Route.extend({
                connectOutlets: function (router, context) {
                    router.get('applicationController').connectOutlet('genre');
                }
            })
        }),

        //...
    })
})

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

Неисправность Ошибка: утверждение не выполнено: ваш сервер вернул хэш с ключ 0, но у вас нет сопоставлений

Для справки, здесь json возвращает сервис:

[
  {
    "id": 1,
    "name": "Action"
  },
  {
    "id": 2,
    "name": "Drama"
  },
  {
    "id": 3,
    "name": "Comedy"
  },
  {
    "id": 4,
    "name": "Romance"
  }
]

Я не могу точно сказать, в чем проблема, и поскольку в утверждении упоминается, что мне нужно сопоставление, я хотел бы знать:

  • Какое это отображение и как его использовать.
  • Так как возвращенный json - это массив, должен ли я использовать контроллер другого типа в своем приложении или что-нибудь, что я должен знать о работе с этим типом json в ember-data? или мне нужно изменить параметры JsonFormatter на сервере?

Любая помощь приветствуется.

Я могу определенно добавить дополнительную информацию, если вы чувствуете, что этого недостаточно, чтобы понять проблему.

РЕДАКТИРОВАТЬ: я изменил несколько вещей в моем бэкэнд, и теперь мое эквивалентное действие findAll() на сервере сериализует вывод как следующий json:

{
  "genres": [
      { "id": 1, "name": "Action" },
      { "id": 2, "name": "Drama" },
      { "id": 3, "name": "Comedy" },
      { "id": 4, "name": "Romance" }
   ]
}

Но я все еще не могу заставить его заполнять мои модели в клиенте, и мое сообщение об ошибке изменилось на это:

Неисправность Ошибка: утверждение не выполнено: ваш сервер вернул хэш с ключевые жанры, но у вас нет сопоставлений

Не уверен, что еще я могу сделать неправильно.

Метод, который генерирует это исключение, sideload и проверяет такие сопоставления:

sideload: function (store, type, json, root) {
        var sideloadedType, mappings, loaded = {};

        loaded[root] = true;

        for (var prop in json) {
            if (!json.hasOwnProperty(prop)) { continue; }
            if (prop === root) { continue; }

            sideloadedType = type.typeForAssociation(prop);

            if (!sideloadedType) {
                mappings = get(this, 'mappings');
                Ember.assert("Your server returned a hash with the key " + prop + " but you have no mappings", !!mappings);
//...

Этот вызов sideloadedType = type.typeForAssociation(prop); возвращает undefined, а затем я получаю сообщение об ошибке. Метод typeForAssociation() проверяет ключ for 'associationsByName', который возвращает пустой Ember.Map.

Пока нет решения для этого на данный момент.

Кстати...

Мое действие теперь выглядит следующим образом:

    // GET api/genres
    public object GetGenres() {
        return new { genres = context.Genres.AsQueryable() };
    }

    // GET api/genres
    //[Queryable]
    //public IQueryable<Genre> GetGenres()
    //{
    //    return context.Genres.AsQueryable();
    //}

Мне пришлось удалить исходную реализацию, которая сериализуется json.NET, поскольку я не смог найти параметры конфигурации для создания json-вывода, который ожидает Ember-Data (as в {resource_name : [json, json,...]}). Побочным эффектом этого является то, что я потерял встроенную поддержку OData, но я хотел бы сохранить ее. Кто-нибудь знает, как я могу настроить его для создания другого json для коллекции?

Ответ 1

Отображение может быть определено в DS.RESTAdapter. Я думаю, вы могли бы попытаться определить что-то вроде этого:

App.Store = DS.Store.extend({
  adapter: DS.RESTAdapter.create({
    bulkCommit: true,
    mappings: {
      genres: App.Genre
    },
    // you can also define plurals, if there is a unregular plural
    // usually, RESTAdapter simply add a 's' for plurals.
    // for example at work we have to define something like this
    plurals: {
      business_process: 'business_processes' 
      //else it tries to fetch business_processs
    }
  }),
  revision: 4
});

Надеюсь, что это решает вашу проблему.

Update:

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

Ответ 3

Я использую Ember Data rev. 11, и кажется, что конфигурация plurals в DS.RESTAdapter.create никогда не работает. Я просмотрел коды и нашел решение следующим образом:

App.Adapter = DS.RESTAdapter.extend({
  bulkCommit: false
})

App.Adapter.configure('plurals', {
  series: 'series'
})