未加星标

Consume OData Restful Services in Angular 2

字体大小 | |
[前端(javascript) 所属分类 前端(javascript) | 发布者 店小二03 | 时间 2017 | 作者 红领巾 ] 0人收藏点击收藏

Today I want to speak about a feature which I think can be of a high importance in the near future, which is OData. And to create discussion, I will consume OData services with the oh so popular technology nowadays (and which I personally adore) Angular 2.

Introduction

As stated at the official OData website :

“OData (Open Data Protocol) is an OASIS standard that defines a set of best practices for building and consuming RESTful APIs. OData helps you focus on your business logic while building RESTful APIs without having to worry about the various approaches to define request and response headers, status codes, HTTP methods, URL conventions, media types, payload formats, query options, etc. …”

Now let’s take a look at what OData is from the perspective of the client (the application which is going to consume that service, and could be server or browser). For the client, OData standards allow to have access to trulyRestful services but in predictable and standard way. So no more messy and custom URIs where client should know how the service is implemented before being able to connect to it, but it can use calls from standard and be sure that it's going to receive the correct responses for all requests (we can say that responses are predictable).

OData is just a normal web service which should be accessed through HTTP. And given that the we will not need to create anything special but just a simple set of methods which will perform HTTP requests, in this tutorial, I will show you a handy and scalable way to create a client for Angular 2 which will consume the OData web service.

Getting started

So, to start, I will use the following tools (you may use tools of your choice):

Visual Studio Code, as Integrated Development Environment; Angular2 seed project, as a template to start; Node.Js, NPM, to make our life easier;

First let’s go to the following Github repo and download our template project: https://github.com/angular/angular2-seed .

Then you need to open that project in your local environment and run the command below from the project’s root folder.

npm install

Then, the code below will download all node modules necessary to work with our project. Pay attention that to have this step work correctly you must have node.js and NPM installed on your machine.

cd angular2-seed

Now if you run the npm start command, the local server will be launched and you will be able to see the result in the browser. The default URL is http://localhost:3000 , and if everything goes well until now, you should see this homepage in your browser:


Consume OData Restful Services in Angular 2

Now let’s go to the src -> app, and create additional folders there which will hold a component for our tests with OData requests. I will call that folder odata.

Inside that folder I'm going to create 4 files:

odata.component.ts ― which will be our component to interact with data; odata.component.html ― template for our component; odata.service.html ― service which will support us in calling the OData web services; odata.model.ts ― file to store our enums, classes, interfaces, and values for structure

The final result should look like this:


Consume OData Restful Services in Angular 2
Implementation

Now let’s dive to the implementation. Put the following code into component:

import { Component, OnInit } from [email protected]/core'; import { ODataService } from './odata.service'; import { RequestTypes } from './odata.model'; import { IUrlOptions } from './odata.model'; @Component({ selector: 'odata', templateUrl: 'odata.component.html' }) export class ODataComponent implements OnInit { public requestResult: any; constructor( private odata: ODataService ) { } ngOnInit() { } testGet() { let urlOptions: IUrlOptions = <IUrlOptions>{}; urlOptions.restOfUrl = "Products?$format=json"; this.odata.Request(RequestTypes.get, urlOptions).subscribe( data => this.requestResult = data, error => alert(error) ); } testPost() { let urlOptions: IUrlOptions = <IUrlOptions>{}; this.odata.Request(RequestTypes.post, urlOptions).subscribe( data => this.requestResult = data, error => alert(error) ); } testPut() { let urlOptions: IUrlOptions = <IUrlOptions>{}; this.odata.Request(RequestTypes.put, urlOptions).subscribe( data => this.requestResult = data, error => alert(error) ); } testPatch() { let urlOptions: IUrlOptions = <IUrlOptions>{}; this.odata.Request(RequestTypes.patch, urlOptions).subscribe( data => this.requestResult = data, error => alert(error) ); } testDelete() { let urlOptions: IUrlOptions = <IUrlOptions>{}; this.requestResult = this.odata.Request(RequestTypes.delete, urlOptions); } }

This is the simple component where we reference our template, inject the instance of our service and create methods which we will bind to the buttons on our template to test the action. Also, this contains an object which holds a response from the web service in JSON format, which we going to display in the template.

In the component’s template put the following code:

<div> <h2>Welcome to OData Component</h2> <button (click)="testGet()">Get Request</button> <br /> <button (click)="testPost()">Post Request</button> <br /> <button (click)="testPut()">Put Request</button> <br /> <button (click)="testPatch()">Patch Request</button> <br /> <button (click)="testDelete()">Delete Request</button> <br /> <h3>Request results will be displayed here</h3> <pre>{{requestResult | json}}</pre> </div>

As explained previously, the template will have several buttons to perform different test requests and sections to display the result of the requests.

Now let’s take a look at the service itself. Please copy-paste the following code into the service file:

import { Injectable } from [email protected]/core'; import { Http, RequestOptionsArgs, Response } from [email protected]/http'; import { Observable } from 'rxjs'; import { IUrlOptions } from './odata.model'; import { RequestTypes } from './odata.model'; @Injectable() export class ODataService { constructor( private host: string, private http: Http ) { } private constructUrl(urlOptions: IUrlOptions): string { return this.host + urlOptions.restOfUrl; } //T specifies a generic output of function public Request<T>(requestType: RequestTypes, urlOptions: IUrlOptions, body?: any, options?: RequestOptionsArgs) : Observable<T> { let response: Observable<Response>; //True in case of post, put and patch if (body && options) { response = this.http[RequestTypes[requestType]]( this.constructUrl(urlOptions), body, options); } //True in case of post, put and patch if options is empty else if (body) { response = this.http[RequestTypes[requestType]]( this.constructUrl(urlOptions), body); } //True in case of get, delete, head and options else if (options) { response = this.http[RequestTypes[requestType]]( this.constructUrl(urlOptions), options); } //True in case of get, delete, head and options, if options is empty else { response = this.http[RequestTypes[requestType]]( this.constructUrl(urlOptions), options); } return response.map((res) => <T>res.json()); } }

The first thing you'll notice here is that in our constructor, we have injected a host, which we will pass through the custom provider (we will create this in a moment).

Since OData is composed of three parts which are:

Service root URL Resource path Query options

And since we know that service root URL will always be the same, we can inject it as a dependency to our service (private host: string), and concentrate mostly on constructing a resource path and working with query options.

The second important thing to notice here is the Request method. In Angular 2's HTTP module, we have different types of requests (get, post, put, options, delete, etc…) and all of them are almost identical and the only thing that could change is body and query options. So, that's why I prefer to have only one method, the other reason to have only one method is that with Odata, we don’t need to do any additional manipulation before making a request, because all manipulations necessary is done on the request’s URL.

For that purpose I’ve created a method called constructUrl , which holds a responsibility to create the correct URL (I’ve made it very simple just to demonstrate you my idea, but it can be expanded in a generic way, just by adding new properties to urlOptions and to use them inside the constructUrl function).

The model file looks like this:

export enum RequestTypes { get, post, put, delete, patch, head, options } export interface IUrlOptions { restOfUrl: string, }

Now let’s create one more additional file to hold our custom provider for ODataServive class. I will call it odata.serviceProvider.ts . Please put the following code inside this file:

import { Http } from [email protected]/http'; import { ODataService } from './odata.service'; export function provideODataService(url: string) { return { provide: ODataService, useFactory: (http) => { return new ODataService(url, http); }, deps: [Http] } }

This is the way that we have to inject custom values into our service while instantiating it. So basically, what's going to happen here is that, when we will first request our service, it’s going to be created. During the creation, instead of using a default constructor, it will use a factory where we are going to inject our custom value for the host property.

Now go to the app.module.ts file and add: ODataComponent to the declarations list, and the following line of code to the providers list:

provideODataService("http://services.odata.org/V3/(S(pq1lpmgz0kuok05ubqtx1c2g))/OData/OData.svc/")

Pay attention that before adding these lines of code, you should import the references to the ODataComponent and provideODataService .

Info: in this tutorial I will use the test services provided by www.odata.org: http://services.odata.org/V3/(S(pq1lpmgz0kuok05ubqtx1c2g))/OData/OData.svc/

Now we need to add the route to our routing definition in order to be able to reach the component and send requests to web services. For that, go to the app.routes.ts and add the following line of code to the array of routes:

{ path: 'odata', component: ODataComponent }

(Again: don’t forget to import ODataComponent previously).

That it, work done!

Now hit npm start in your command line, to allow everything to be recompiled again. Go to the http://localhost:3000/#/odata URL and hit the Get Request button, and in the bottom of the page, you should see the response from the OData web service.


Consume OData Restful Services in Angular 2
Conclusion

In this tutorial, I only showed how to work with get requests, but the other types of request will work in a very similar way. So, I believe that at this moment, you have a good starting (and scallable) point to start working with OData web services in your Angular 2 application.

Thank you very much for your time, and if you have any question about OData orAngular 2 you can reach me through here at Codementor or post your feedback on the comment section below.

本文前端(javascript)相关术语:javascript是什么意思 javascript下载 javascript权威指南 javascript基础教程 javascript 正则表达式 javascript设计模式 javascript高级程序设计 精通javascript javascript教程

分页:12
转载请注明
本文标题:Consume OData Restful Services in Angular 2
本站链接:http://www.codesec.net/view/524489.html
分享请点击:


1.凡CodeSecTeam转载的文章,均出自其它媒体或其他官网介绍,目的在于传递更多的信息,并不代表本站赞同其观点和其真实性负责;
2.转载的文章仅代表原创作者观点,与本站无关。其原创性以及文中陈述文字和内容未经本站证实,本站对该文以及其中全部或者部分内容、文字的真实性、完整性、及时性,不作出任何保证或承若;
3.如本站转载稿涉及版权等问题,请作者及时联系本站,我们会及时处理。
登录后可拥有收藏文章、关注作者等权限...
技术大类 技术大类 | 前端(javascript) | 评论(0) | 阅读(109)