Ember-Data:“映射”如何工作

时间:2012-08-29 16:53:07

标签: javascript asp.net-web-api ember.js ember-data ember-old-router

我目前正试图将其与ember + emberdata + router + asp.net web api放在一起。其中大部分似乎都有效,但是我遇到了一个错误消息,当ember-data通过我的模型的适配器尝试findAll时,我得到了这个消息。

在我的后端,我有一个这样的模型(C#):

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"
  }
]

我无法确切地知道问题是什么,因为断言提到我需要映射,我想知道:

  1. 此映射以及如何使用它。
  2. 由于返回的json是一个数组,我应该在我的应用程序中使用不同类型的控制器,还是在ember-data中使用这种类型的json时我应该知道什么?或者我应该更改服务器中的JsonFormatter选项?
  3. 欢迎任何帮助。

    如果您认为这还不足以理解问题,我肯定可以添加更多信息。

    编辑:我在后端更改了一些内容,现在服务器中的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序列化的原始实现,因为我找不到配置选项来生成jmber输出,如Ember-Data所期望的那样(如{resource_name : [json, json,...]}中所示)。这样做的副作用是我失去了内置的OData支持,但我想保留它。有谁知道如何配置它来为集合生成不同的json?

3 个答案:

答案 0 :(得分:12)

可以在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
});

希望这可以解决您的问题。

<强> 更新

目前,这还没有很好的记录,我不记得我们是否通过自己阅读代码找到了它,或者也许汤姆戴尔指出它。
无论如何,这是plurals的要点 对于映射,我认为我们被与你一样的错误所驱使,而且我们要么尝试过,要么汤姆告诉我们这个。

答案 1 :(得分:8)

RESTAdapter期望返回的JSON格式为:

{
  "genres": [{
    "id": 1,
    "name": "action"
  },{
    "id": 2,
    "name": "Drama"
  }]
}

测试是一个很好的文档来源,请参阅https://github.com/emberjs/data/blob/master/packages/ember-data/tests/unit/rest_adapter_test.js#L315-329

答案 2 :(得分:3)

我正在使用Ember数据rev. 11,似乎plurals中的DS.RESTAdapter.create配置无法正常工作。我查看了代码并找到了以下解决方案:

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

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