[英]Custom (OData) routes in Restangular
On the server side, I'm using Web API with the OData routing convention, which means that my route for getting a single entity looks something like this: 在服务器端,我将Web API与OData路由约定一起使用,这意味着我获取单个实体的路线如下所示:
/api/v1/Products(1)
rather than: 而不是:
/api/v1/Products/1
Normally, in Restangular, I'd be able to get a single entity with something like this: 通常,在Restangular中,我将能够获得具有以下内容的单个实体:
Restangular.one('Product', 1);
But that doesn't work for my OData endpoint. 但这不适用于我的OData端点。 I've looked at
customGET
, and setRequestInterceptor
but I can't seem to find an example of or figure out how to change the route to match my endpoint. 我看过
customGET
和setRequestInterceptor
但似乎找不到示例或弄清楚如何更改路由以匹配我的端点。 Preferably globally since all of my entities will have this same format. 最好在全球范围内使用,因为我的所有实体都将采用这种相同的格式。
Any help is greatly appreciated. 任何帮助是极大的赞赏。
Restangular documentation details how to create a custom configuration, you could do the same by editing the source restangular.js but this extensibility point allows us to keep a clean implementation that should be compatible with most customisations or future versions of RestAngular as well as allowing side-by-side standard REST APIs and OData v4 APIs. Restangular文档详细介绍了如何创建自定义配置,您可以通过编辑源代码restangular.js来执行此操作,但是此可扩展性点使我们能够保持整洁的实现,该实现应与大多数定制或RestAngular的未来版本兼容,并且允许并行标准REST API和OData v4 API。
How to create a Restangular service with a different configuration from the global one 如何使用与全局配置不同的配置创建Restangular服务
// 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;
});
});
});
Implementation example: 实施示例:
// 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();
}
Captured URLs from network Traffic: 从网络流量中捕获的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)
I struggled to try to write a custom service factory and to modify BreezeJS to work with OData v4 and only recently stumbled into Restangular, I can now really appreciate the extensible design that went into restangular, the general lack of documented client side framework support has been the Achilles heel that has prevented a wider adoption of OData v4.
我一直努力尝试编写一个自定义服务工厂,并修改BreezeJS以使其与OData v4一起使用,直到最近才偶然发现Restangular,现在我真的很欣赏进入restangular的可扩展设计,因为通常缺少文档化的客户端框架支持阿基里斯之heel阻止了OData v4的广泛采用。 I hope this answer contributes to getting more developers onboard with version 4.
我希望这个答案有助于使更多的开发人员使用版本4。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.