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();
}
从网络流量中捕获的 URL:
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 版。