I dont know how to make an API call to such a method:
[HttpGet]
[ActionName("GetSupport")]
public HttpResponseMessage GetSupport(int projectid)
Because it is GET but still got a parameter to pass, how to do this?
Would it be something like this?
let headers = new Headers();
headers.append('Content-Type', 'application/json');
headers.append('projectid', this.id);
this.http.get('http://localhost:63203/api/CallCenter/GetSupport', { headers: headers })
Having something like this:
let headers = new Headers();
headers.append('Content-Type', 'application/json');
headers.append('projectid', this.id);
let params = new URLSearchParams();
params.append("someParamKey", this.someParamValue)
this.http.get('http://localhost:63203/api/CallCenter/GetSupport', { headers: headers, search: params })
Of course, appending every param you need to params. It gives you a lot more flexibility than just using a URL string to pass params to the request.
EDIT(28.09.2017): As Al-Mothafar stated in a comment, search is deprecated as of Angular 4, so you should use params
EDIT(02.11.2017): If you are using the new HttpClient there are now HttpParams, which look and are used like this:
let params = new HttpParams().set("paramName",paramValue).set("paramName2", paramValue2); //Create new HttpParams
And then add the params to the request in, basically, the same way:
this.http.get(url, {headers: headers, params: params});
//No need to use .map(res => res.json()) anymore
More in the docs for HttpParams and HttpClient
For Angular 9+ You can add headers and params directly without the key-value notion:
const headers = new HttpHeaders().append('header', 'value');
const params = new HttpParams().append('param', 'value');
this.http.get('url', {headers, params});
Above solutions not helped me, but I resolve same issue by next way
private setHeaders(params) {
const accessToken = this.localStorageService.get('token');
const reqData = {
headers: {
Authorization: `Bearer ${accessToken}`
},
};
if(params) {
let reqParams = {};
Object.keys(params).map(k =>{
reqParams[k] = params[k];
});
reqData['params'] = reqParams;
}
return reqData;
}
and send request
this.http.get(this.getUrl(url), this.setHeaders(params))
Its work with NestJS backend, with other I don't know.
Just offering up a helpful piece of code for anyone interested in the HttpParams direction mentioned in the answer from 2017.
Here is my go-to api.service which kind of "automates" params into that HttpParams for requests.
import { HttpClient, HttpParams } from '#angular/common/http';
import { Injectable } from '#angular/core';
import { Params } from '#angular/router';
import { Observable } from 'rxjs';
import { environment } from '#env';
#Injectable({
providedIn: 'root'
})
export class ApiService {
constructor(private http: HttpClient) { }
public get<T>(path: string, routerParams?: Params): Observable<T> {
let queryParams: Params = {};
if (routerParams) {
queryParams = this.setParameter(routerParams);
}
console.log(queryParams);
return this.http.get<T>(this.path(path), { params: queryParams });
}
public put<T>(path: string, body: Record<string, any> = {}): Observable<any> {
return this.http.put(this.path(path), body);
}
public post<T>(path: string, body: Record<string, any> = {}): Observable<any> {
return this.http.post(this.path(path), body);
}
public delete<T>(path: string): Observable<any> {
return this.http.delete(this.path(path));
}
private setParameter(routerParams: Params): HttpParams {
let queryParams = new HttpParams();
for (const key in routerParams) {
if (routerParams.hasOwnProperty(key)) {
queryParams = queryParams.set(key, routerParams[key]);
}
}
return queryParams;
}
private path(path: string): string {
return `${environment.api_url}${path}`;
}
}
An easy and usable way to solve this problem
getGetSuppor(filter): Observale<any[]> {
return this.https.get<any[]>('/api/callCenter/getSupport' + '?' + this.toQueryString(filter));
}
private toQueryString(query): string {
var parts = [];
for (var property in query) {
var value = query[propery];
if (value != null && value != undefined)
parts.push(encodeURIComponent(propery) + '=' + encodeURIComponent(value))
}
return parts.join('&');
}
Related
I have a little issue from an Angular app to get a code from my own server.
I´ve built up a little Spotify App for learning more about Angular 10 and have a little backend that I only use for get the Bearer code to call the Spotify API, but the fact is that in my Angular front I can´t save the code.
Tis is my service call code to the back:
import { Injectable } from '#angular/core';
import { HttpClient, HttpHeaders } from '#angular/common/http';
import { map } from 'rxjs/operators';
import { environment } from '../../environments/environment';
#Injectable({
providedIn: 'root'
})
export class SpotifyService {
token: any;
constructor(private http: HttpClient) {
console.log('Spotify service ready');
this.getAccesToken().subscribe(data => this.token = data['access_token']);
}
getAccesToken(){
return this.http.get(environment.server + `${environment.client_id}/${environment.client_secret}`)
.pipe(
map(res => res)
);
}
getQuery(query: any){
const headers = new HttpHeaders({
'Authorization': `Bearer ${this.token}`
});
const url = `https://api.spotify.com/v1/${query}`;
return this.http.get(url, {headers});
}
I´ve checked the recibed data and I get the request perfectly, but can´t save the data of the suscriber into a variable.
Thanks in advance!
Assuming your component code looks like below, you can make some adjustments and try it.
export class SomeComponent implements OnInit {
spotifyData;
user;
token;
constructor(private spotifyService: SpotifyService, private http: HttpClient) { }
ngOnInit() {
this.user = JSON.parse(localStorage.getItem('user'));
console.log(this.user);
this.token = this.user.token;
this.getSpotifyData();
}
getSpotifyData() {
this.spotifyService.getQuery(this.user, { headers: new HttpHeaders().set('Authorization', 'Bearer ' + this.token) }).subscribe(res => {
console.log(res);
if (res) {
spotifyData = res;
} else {
spotifyData = []
}
});
}
I'm sending a request to an API, it returns an array of data, but I don't know how to extract the headers from that url, this is what i've tried in my service
#Injectable()
export class ResourcesService {
private resourcesurl = "http://localhost:9111/v1/resources";
constructor(private http: Http) { }
getResources() {
let headers = new Headers();
headers.append("api_key", "123456");
return this.http.get(this.resourcesurl, { headers: headers
}).map(this.extractData).catch(this.handleError);
}
getresourceheaders(){
let headers = new Headers();
headers.append("api_key", "123456");
let options = new RequestOptions();
let testsss = options.headers
let headerapi = this.http.request(this.resourcesurl, options);
let test = this.http.get(this.resourcesurl, { headers: headers });
console.log(headerapi);
}
private extractData(res: Response) {
let body = res.json();
return body.data || {};
}
private handleError(error: Response | any) {
let errMsg: string;
if (error instanceof Response) {
const body = error.json() || '';
const err = body.error || JSON.stringify(body);
errMsg = `${error.status} - ${error.statusText || ''} ${err}`;
} else {
errMsg = error.message ? error.message : error.toString();
}
console.error(errMsg);
return Observable.throw(errMsg);
}
}
I want to get the headers from that response that in this case is resourceurl
any idea?
Clear angular 5 answer
By default, this.http.whatever's returned observable will be on the data returned, not the HttpResponse.
If you have a peak at: https://angular.io/api/common/http/HttpClient
You'll notice the options take an "observe" parameter of a HttpObserve type. While it's not documented what the HttpObserve is, if you put it as "response" then you will instead receive an instance of HttpResponse<T>(https://angular.io/api/common/http/HttpResponse)
So, here's an example request:
this.http.get(url, {observe: 'response'})
.subscribe(resp => console.log(resp.headers))
Note: Due to browser cors security, you will not be-able to see headers unless the API provides Access-Control-Expose-Headers: with your custom headers if your api and angular app do not have the same domain.
The headers are part of the Response class, so you should be able to see them in a handler like
http.get('/path/to/resource')
.subscribe((res:Response) => {
console.log(res.headers);
// you can assign the value to any variable here
});
When you do .map(this.extractData) the let body = res.json() from this.extractData function takes out everything from the response except the body.
Instead if you do following, .map((res: Response) => res), that will return the whole response and you can access all the attributes and assign them to variables.
Here's a Plunker demo.
A bit more of an exotic example in Angular 5 shown below. Using HttpClient to post to a GraphQL server, read the response and then extract a response header value and a response body value. The header is Total-Count in this case. cars is a field (array of Car) under another field data in the body. Also shows use of the rxjs first operator.
import { HttpClient, HttpHeaders, HttpResponse } from '#angular/common/http';
import { first } from 'rxjs/operators/first';
import { Car, CarPage } from '../models/car';
..........
..........
public find(filter: string, sort: string, limit: number): Observable<CarPage> {
let headers = new HttpHeaders().set("Content-Type", "application/graphql");
let carPage: CarPage = { cars: [], totalCount: 0 };
return this.http.post<HttpResponse<any>>('/graphql',
`query cars { cars(filter: "${filter}", sort: "${sort}", limit: ${limit}) {
id
make
model
year
}
}`,
{ headers: headers, observe: "response" }
)
.first((_, index) => index === 0, (response: HttpResponse<any>) => {
let totalCountHeaderValues = response.headers.getAll("Total-Count");
carPage.totalCount = (totalCountHeaderValues.length > 0) ? parseInt(totalCountHeaderValues[0]) : 0;
carPage.cars = response.body.data.cars;
return carPage;
})
}
The return type of the angular Http.get method returns a Response type. This object has a headers object that contains information about the headers. It also has a url property.
this.http.get(url).map(resp => console.log(resp));
Can anyone help what I am doing incorrect, anything missing?
I am getting undefined for --'this.ack.length'
this._activeChannelService.requestChannelChange(this.selectedchannel.channelName)
.subscribe(
ack => {
this.ack= ack;
console.log(" test: ", this.ack.length);
},
err => {
console.log(err);
});enter code here
ack is of time
ack:Iack[];
Iack has two field of type string. result and message
I need to iterate through array of Iack[] to get the result and message
if message=success then call the another service
service
requestChannelChange (name: string): Observable<Iack[]> {
alert('in servicerequestChannelChange');
let headers = new Headers({'Content-Type': 'application/json'});
let options = new RequestOptions({headers: headers});
let postchannelname = "channelName=" + name;
let requestt = new IRequest(name);
console.log(JSON.stringify(requestt));
return this._http.post(this._activateChangeUrl, JSON.stringify(requestt),{ headers: headers })
//.map(this.extractData)
.map((res:Response) => res.json() as Iack[])
.do(data => console.log("All: " + JSON.stringify(data)))
.catch(this.handleError);
}
You can use observable in your TS service:
import { Injectable } from '#angular/core';
import { IPost } from './IPost';
import { Http, Response, RequestOptions, Headers } from '#angular/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/do';
import 'rxjs/add/operator/catch';
#Injectable()
export class PostServices {
private _webApiBaseUrl = "http://localhost:62806/v1/Posts"
private _http : Http;
constructor(http : Http){
this._http = http;
}
getAll(): Observable<IPost[]> {
return this._http.get(this._webApiBaseUrl + '/all', this.getHeaders())
.map((response: Response) => response.json())
.do(data => console.log(`All Data: \n ${ JSON.stringify(data) }`))
.catch(this.handleError);
}
private handleError(error: Response){
console.error(error);
return Observable.throw(error.json().error || 'Server Error');
}
private getHeaders()
{
let headers = new Headers();
headers.append("Authorization", "");
headers.append("Content-Type", "application/json");
return new RequestOptions({ headers: headers });
}
}
Usage in your TS class:
import { Component, OnInit } from '#angular/core';
import { IPost } from './IPost';
import { PostServices } from './posts.service';
#Component({
selector: 'app-posts',
templateUrl: './posts.component.html',
styleUrls: ['./posts.component.css']
})
export class PostsComponent implements OnInit {
posts: IPost[];
errorMessage: string;
private _postService: PostServices;
constructor(postService: PostServices) {
this._postService = postService;
}
ngOnInit() {
this._postService.getAll()
.subscribe(
data => {this.posts = data; console.log("data.length: " + data.length)}, // here
error => this.errorMessage = <any>error
);
}
}
enter code here is executed before this.ack= ack; is executed
This is a function
ack => {
this.ack= ack;
console.log(" test: ", this.ack.length);
}
that you pass to subscribe(...) and the observable calls it when the data arrives which can take a looong time when it's a call to a server.
enter code here is executed immediately.
You'll have to check for success within the service subscription. An observable is an asynchronous call, so any calls you want to make regarding the data in that async call must be made within it to remain a safe call.
So, make your seconds service call, within the subscription.
I am taking the field of a form and passing it to a service as this.form.value when I am logging this.form.value on the console I am getting Object { email: "zxzx", password: "zxzxx" } when I am sending the same thing to the service and calling the server like :
import {Http} from 'angular2/http';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/toPromise';
import {Injectable} from 'angular2/core'
import {Post} from './post';
import {Observable} from 'rxjs/Observable';
#Injectable()
export class PostService {
//dependency injection
private _url = "http://127.0.0.1/accounts/login_user/";
constructor(private _http:Http) {
}
createPost(post){
return this._http.post(this._url,JSON.stringify(post))
.map(res=>res.json());
}
}
The server is being called but the values are not being passed. When I am logging the response on the console I am getting :
Object { _isScalar: false, source: Object, operator: Object }
Can somebody please help me solve this issue?
Thank you.
Your console.log prints the observable corresponding to your request but not its result. If you want to print this result, you can use the do operator:
createPost(post){
return this._http.post(this._url,JSON.stringify(post))
.map(res=>res.json())
.do(data => {
console.log(data);
});
}
You said that the request is executed. It's actually the case if you subscribe on the observable:
this.service.createPost(...).subscribe(() => {
(...)
});
Edit
You also need to set the Content-Type header:
createPost(post){
var headers = new Headers();
headers.append('Content-Type', 'application/json');
return this._http.post(this._url,JSON.stringify(post), { headers })
.map(res=>res.json())
.do(data => {
console.log(data);
});
}
Edit2
If you want to send an url-encoded form:
You also need to set the Content-Type header:
createPost(post){
var headers = new Headers();
headers.append('Content-Type', 'application/x-www-form-urlencoded');
let content = new URLSearchParams();
content.set('prop', post.prop);
(...)
return this._http.post(this._url, content.toString(), { headers })
.map(res=>res.json())
.do(data => {
console.log(data);
});
}
You need to subscribe() otherwise the observable won't do anything:
createPost(post){
return this._http.post(this._url,JSON.stringify(post))
.map(res=>res.json())
.do(val => console.log(val));
}
...
this.createPost(...).subscribe(data => console.log(data));
I'm using Angular2 with Typescript. Say I have a dummy login component and an authentication service to do token authentication. I'm going to set the authenticated variable in one of the map function as soon as I get the token from backend server.
The question is that I can't access the instance variable inside the chaining function. The this inside the chaining function is actually the subscriber of this observable. I know this's a scope issue but can't figure it out.
export class AuthenticationService {
authenticated:boolean = false; //this is the variable I want to access
constructor(public http: Http) {
this.authenticated = !!sessionStorage.getItem('auth_token');
}
login(username, password) {
let headers = new Headers();
headers.append('Content-Type', 'application/json');
return this.http
.post(
'http://localhost:8080/token-auth',
JSON.stringify({ username, password }),
{ headers }
)
.map(res => res.json())
.map((res) => {
if (res) {
this.authenticated = true; //this is where I want to access the instance variable
sessionStorage.setItem('auth_token', res.token);
}
return res;
});
}
The dummy-login component where the above login() method is called is like this:
export class DummyLoginComponent {
constructor(private auth: AuthenticationService, private router: Router) {
}
onSubmit(username, password) {
this.auth.login(username, password).subscribe((result) => {
if (result) {
this.router.navigate(['Dashboard']);
}
})
}
}
You can just subscribe to the observable instead of mapping it
login(username, password) {
let headers = new Headers();
headers.append('Content-Type', 'application/json');
let res = this.http
.post(
'http://localhost:8080/token-auth',
JSON.stringify({ username, password }),
{ headers }
)
.map(res => res.json());
res.subscribe(
(res) => {
this.authenticated = true; //this is where I want to access the instance variable
sessionStorage.setItem('auth_token', res.token);
});
return res;
}