在服务器端,我正在使用带有OData路由约定的Web API,这意味着获取单个实体的路由如下所示:
/api/v1/Products(1)
而不是:
/api/v1/Products/1
通常情况下,在Restangular中,我可以得到一个像这样的实体:
Restangular.one('Product', 1);
但这对我的OData端点不起作用。我查看过customGET
和setRequestInterceptor
,但我似乎无法找到一个示例或弄清楚如何更改匹配我的端点的路由。最好是全局的,因为我的所有实体都具有相同的格式。
非常感谢任何帮助。
答案 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。