Restangular中的自定义(OData)路线

时间:2014-02-28 21:28:56

标签: angularjs asp.net-web-api restangular

在服务器端,我正在使用带有OData路由约定的Web API,这意味着获取单个实体的路由如下所示:

/api/v1/Products(1)

而不是:

/api/v1/Products/1

通常情况下,在Restangular中,我可以得到一个像这样的实体:

Restangular.one('Product', 1);

但这对我的OData端点不起作用。我查看过customGETsetRequestInterceptor,但我似乎无法找到一个示例或弄清楚如何更改匹配我的端点的路由。最好是全局的,因为我的所有实体都具有相同的格式。

非常感谢任何帮助。

2 个答案:

答案 0 :(得分:1)

Restangular文档详细介绍了如何创建自定义配置,您可以通过编辑源restangular.js来做同样的事情,但是这个可扩展性点允许我们保持一个干净的实现,该实现应该与大多数自定义或RestAngular的未来版本兼容允许并行标准REST API和OData v4 API。

How to create a Restangular service with a different configuration from the global one

// Global configuration
app.config(function(RestangularProvider) {
  RestangularProvider.setBaseUrl('http://localhost:16486');
  RestangularProvider.setRestangularFields({ id: 'Id' });
});

// Restangular service targeting OData v4 on a the specified route
app.factory('ODataRestangular', function(Restangular) {
  return Restangular.withConfig(function(RestangularConfigurer) {
    RestangularConfigurer.setBaseUrl(RestangularConfigurer.baseUrl + '/odata');

    // OData v4 controller(key) Item Route convention
    RestangularConfigurer.urlCreatorFactory.path.prototype.base = function(current) {
      var __this = this;
      return _.reduce(this.parentsArray(current), function(acum, elem) {
        var elemUrl;
        var elemSelfLink = RestangularConfigurer.getUrlFromElem(elem);
        if (elemSelfLink) {
          if (RestangularConfigurer.isAbsoluteUrl(elemSelfLink)) {
            return elemSelfLink;
          } else {
            elemUrl = elemSelfLink;
          }
        } else {
          elemUrl = elem[RestangularConfigurer.restangularFields.route];

          if (elem[RestangularConfigurer.restangularFields.restangularCollection]) {
            var ids = elem[RestangularConfigurer.restangularFields.ids];
            if (ids) {
              // Crude Implementation of 'several', don't try this with more than
              // 60 Ids, performance degrades exponentially for large lists of ids.
              elemUrl += '?$filter=((Id eq ' + ids.join(')or(Id eq ') + '))';
            }
          } else {
            var elemId;
            if (RestangularConfigurer.useCannonicalId) {
              elemId = RestangularConfigurer.getCannonicalIdFromElem(elem);
            } else {
              elemId = RestangularConfigurer.getIdFromElem(elem);
            }

            if (RestangularConfigurer.isValidId(elemId) && !elem.singleOne) {
              elemUrl += '(' + (RestangularConfigurer.encodeIds ? encodeURIComponent(elemId) : elemId) + ')';
            }
          }
        }
        acum = acum.replace(/\/$/, '') + '/' + elemUrl;
        return __this.normalizeUrl(acum);

      }, RestangularConfigurer.baseUrl);
    };

    // add a response interceptor for OData v4:
    RestangularConfigurer.addResponseInterceptor(function(data, operation, what, url, response, deferred) {
      var extractedData;
      // Collection requests are 'getList' operations
      if (operation === "getList") {
        // return the value array
        extractedData = data.value;
      } else {
        // return the first item in the array
        if(data.value.length > 0)
          extractedData = data.value[0];
      }
      // pass the metadata back
      if(extractedData) {
        extractedData.meta = { context: data['@odata.context'] };
        if(data['@odata.count'])
          extractedData.meta.count = data['@odata.count'];
      }
      return extractedData;
    });
  });
});

实施例:

// Controller for list route
function ListCtrl($scope, ODataRestangular) {
  $scope.providers = ODataRestangular.all("providers").getList({ $count:true }).$object;
  $scope.some = ODataRestangular.several("providers", 15,16,17,18).getList();
  $scope.single = ODataRestangular.one("providers", 15).get();
}

从网络流量中捕获的网址:

http://localhost:16486/odata/providers?$count=true

http://localhost:16486/odata/providers?$filter=((Id eq 15)or(Id eq 16)or(Id eq 17)or(Id eq 18))

http://localhost:16486/odata/providers(15)

  

我努力尝试编写一个自定义服务工厂并修改BreezeJS以使用OData v4并且最近偶然发现了Restangular,我现在可以非常欣赏进入restangular的可扩展设计,一般缺乏记录的客户端框架支持一直是阿基里斯的脚跟,阻碍了OData v4的广泛采用。我希望这个答案有助于让更多的开发人员加入第4版。

答案 1 :(得分:0)

Restangular没有明确支持OData API。您可以使基础工作,但您可能最好使用支持查询OData API的库,例如breeze.js