help a noob out, I am building a MEAN stack app and i ran into a problem where I cannot read a response from the express server but the response is generated when I use postman, here is my code
auth.service.ts
import { Injectable } from '#angular/core';
import { Http, Headers } from '#angular/http';
import { map } from 'rxjs/operators';
#Injectable({
providedIn: 'root'
})
export class AuthService {
authToken: any;
user: any;
constructor(private http:Http) { }
registerUser(user){
let headers = new Headers();
headers.append('Content-Type','application/json');
return this.http.post('http://localhost:3000/users/register',user,
{headers: headers})
.pipe(map(res => res.json));
}
authenticateUser(user){
let headers = new Headers();
headers.append('Content-Type','application/json');
return this.http.post('http://localhost:3000/users/authenticate',user,
{headers: headers})
.pipe(map(res => res.json));
}
}
login.component.ts
import { Component, OnInit } from '#angular/core';
import { AuthService } from '../../services/auth.service';
import { Router } from '#angular/router';
import { FlashMessagesService } from 'angular2-flash-messages';
#Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.css']
})
export class LoginComponent implements OnInit {
username: String;
password: String;
constructor(private authService: AuthService,
private router: Router,
private flashMessage: FlashMessagesService
) { }
ngOnInit() {
}
onLoginSubmit(){
const user = {
username: this.username,
password: this.password
}
this.authService.authenticateUser(user).subscribe(data => {
console.log(data);
});
}
}
Chrome Console
ƒ () { login.component.ts:29
if (typeof this._body === 'string') {
return JSON.parse(this._body);
}
if (this._body instanceof ArrayBuffer) {
return JSON.parse(this.text());
Below is the response in Postman :
The error is in your pipe function.
pipe(map( res => res.json ))
You need to call res.json() inside your map. Convert it to
pipe(map( res => res.json() ))
However, converting the response to JSON is not required over Angular v5.
Correct code is as below:-
authenticateUser(user){
let headers = new Headers();
headers.append('Content-Type','application/json');
return this.http.post('http://localhost:3000/users/authenticate',user,
{headers: headers})
.pipe(map(res => res.json()));
}
Looks like data coming from authenticateUser is a function. Have you tried calling it?
Related
I am getting really weird behavior trying to call the Controller in .net 5 MVC project from the angular 12.
I am getting 200 status code and even get the data that I suppose to get but at the same response I am getting the error message **"Unexpected token e in JSON at position 0"**.enter image description here
I am able to use the postman and call the controller with no problem so that makes me think the problem is with the Angular.
Here is how my angular side looks like:
data.service.ts:
import { Injectable } from '#angular/core';
import { HttpClient, HttpHeaders } from '#angular/common/http';
import { Token } from './models/token';
import { Observable } from 'rxjs';
#Injectable({
providedIn: 'root'
})
export class DataService{
constructor(private http: HttpClient) { }
getEco(input:string):Observable<string>{
return this.http.get<string>(`home/${input}`,{ headers: this.headers});
}
getToken(): Observable<Token> {
return this.http.post<Token>("token/generate", {headers: this.headers })
}
private headers: HttpHeaders = new HttpHeaders({ 'Content-Type': 'application/json' });
component:
import { Component, OnInit } from '#angular/core';
import { DataService } from './data-service.service';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
title = 'ClientApp';
constructor(private dataService: DataService){}
ngOnInit(): void {
this.dataService.getEco("ahanahui").subscribe((res) =>{
console.log(res);
});
this.dataService.getToken().subscribe(res => console.log(res));
}
}
I was missing the NewtonsoftJson that would serialize response for me newtonsoft.com/json
public static class ConfigurationExtensions
{
public static IServiceCollection ConfigureMVC(this IServiceCollection services)
{
services.AddNewtonsoftJson(options =>
{
options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
options.SerializerSettings.ContractResolver = new DefaultContractResolver();
});
return services;
}
}
I have created a MEAN stack application which does the basic job of inserting,delete,update and viewing the data from mongoDB.
first of all i cloned this MEAN stack application from github. the application was based on the employee, but i renamed all the components, routing, etc from 'employee' to 'sensor'. what i have done literally is changed the word 'employee' to 'sensor'.
and i had not issues in compiling the code.
the build was successful.
but when i launched localhost:4200 , the first page was displayed properly,which is insert component. the data is inserted into mongodb. so this component has no issues.
but when i click on view sensor component,it shows a blank page.
so when i checked on chrome console by clicking on f12,it showed a list of errors.
please check for the errors in the below screenshot.4
the service.api code is below
import { Injectable } from '#angular/core';
import { throwError } from 'rxjs';
import { Observable } from 'rxjs/Observable';
import { catchError, map } from 'rxjs/operators';
import { HttpClient, HttpHeaders, HttpErrorResponse } from '#angular/common/http';
#Injectable({
providedIn: 'root'
})
export class ApiService {
baseUri:string = 'http://localhost:4000/api';
headers = new HttpHeaders().set('Content-Type', 'application/json');
getSensors: any;
constructor(private http: HttpClient) { }
// Create
createSensor(data): Observable<any> {
let url = `${this.baseUri}/create`;
return this.http.post(url, data)
.pipe(
catchError(this.errorMgmt)
)
}
// Get Sensor
getSensor(id): Observable<any> {
let url = `${this.baseUri}/read/${id}`;
return this.http.get(url, {headers: this.headers}).pipe(
map((res: Response) => {
return res || {}
}),
catchError(this.errorMgmt)
)
}
// Update Sensor
updateSensor(id, data): Observable<any> {
let url = `${this.baseUri}/update/${id}`;
return this.http.put(url, data, { headers: this.headers }).pipe(
catchError(this.errorMgmt)
)
}
// Delete Sensor
deleteSensor(id): Observable<any> {
let url = `${this.baseUri}/delete/${id}`;
return this.http.delete(url, { headers: this.headers }).pipe(
catchError(this.errorMgmt)
)
}
// Error handling
errorMgmt(error: HttpErrorResponse) {
let errorMessage = '';
if (error.error instanceof ErrorEvent) {
// Get client-side error
errorMessage = error.error.message;
} else {
// Get server-side error
errorMessage = `Error Code: ${error.status}\nMessage: ${error.message}`;
}
console.log(errorMessage);
return throwError(errorMessage);
}
}
SENSOR-LIST.COMPONENT.TS is below
import { Component, OnInit } from '#angular/core';
import { ApiService } from './../../service/api.service';
#Component({
selector: 'app-Sensor-list',
templateUrl: './Sensor-list.component.html',
styleUrls: ['./Sensor-list.component.css']
})
export class SensorListComponent implements OnInit {
Sensor: any = [];
constructor(private apiService: ApiService) {
this.readSensor();
}
ngOnInit() {}
readSensor() {
this.apiService.getSensors.subscribe ((data) => {
this.Sensor = data;
});
}
removeSensor(Sensor, index) {
if (window.confirm('Are you sure?')) {
this.apiService.deleteSensor(Sensor._id).subscribe((data) => {
this.Sensor.splice(index, 1);
}
);
}
}
}
some of the screenshots
img 12
img 23
img 34
please help me out in this problem
getSensors is not a function first of all. You declared it in ApiService as a variable of type any. So if you want the list of sensors. Create the getSensors() method which will allow you to retrieve the list of sensors via the URL intended for it
In Postman the profile is authorized and a json object is returned.
But on the front-end, I'm getting this error.
HttpErrorResponse {headers: HttpHeaders, status: 401, statusText: "Unauthorized", url: "http://localhost:3000/users/profile", ok: false, …}
Here is my auth.service.ts file:
import { Injectable } from '#angular/core';
import { HttpClient, HttpHeaders } from '#angular/common/http';
import { Observable, Subject } from 'rxjs';
import 'rxjs/add/operator/map';
interface data{
success: boolean;
msg: string;
token: string;
user: any;
}
export class AuthService {
authToken: any;
user: any;
constructor(private http: HttpClient) { }
getProfile() {
let headers = new HttpHeaders();
this.loadToken();
headers.append('Authorization', this.authToken);
headers.append('Content-Type', 'application/json');
return this.http.get<data>('http://localhost:3000/users/profile', {headers: headers})
.map(res => res);
}
loadToken(){
const Token = localStorage.getItem('id_token');
this.authToken = Token;
}
}
profile.ts file:
import { Component, OnInit } from '#angular/core';
import { AuthService } from '../../services/auth.service';
import { Router } from '#angular/router';
#Component({
selector: 'app-profile',
templateUrl: './profile.component.html',
styleUrls: ['./profile.component.css']
})
export class ProfileComponent implements OnInit {
user: Object;
constructor(
private authService: AuthService,
private router: Router,
) { }
ngOnInit() {
this.authService.getProfile().subscribe(profile => {
this.user = profile.user;
},
err => {
console.log(err);
return false;
});
}
}
this is happening because this.loadToken() returns you the token. you have to wait till you this.loadToken() function returns you the authToken.
for this, you can use async and await for your function or else just return the value from this.loadToken like
getProfile() {
let headers = new HttpHeaders();
this.authToken = this.loadToken();
headers.append('Authorization', this.authToken);
headers.append('Content-Type', 'application/json');
return this.http.get<data>('http://localhost:3000/users/profile', {headers: headers})
.map(res => res);
}
loadToken(){
const Token = localStorage.getItem('id_token');
return Token;
}
Not sure this will help but try to enable CORS in your WebAPI project:
WebApiConfig.cs (Register Method):
EnableCorsAttribute cors = new EnableCorsAttribute("*", "*", "*");
config.EnableCors(cors);
user.js
router.post('/register', (req, res) => {
let newUser = new User({
name: req.body.name,
email: req.body.email,
username: req.body.username,
password: req.body.password
});
User.addUser(newUser, (err, user) => {
if (err) {
res.json({ "success": false, msg: 'Failed to register User' })
} else {
res.json({ "success": true, msg: "User Added" })
}
})
});
authservice.ts
import { catchError,map } from 'rxjs/operators';
import { Injectable } from '#angular/core';
import {HttpClient,HttpHeaders,HttpErrorResponse} from '#angular/common/http';
#Injectable({
providedIn: 'root'
})
export class AuthService {
constructor(private http:HttpClient) { }
registerUser(user){
let headers = new HttpHeaders();
headers.append('content-type','application/json');
return this.http.post('http://localhost:8080/users/register',user,
{headers:headers})
}
}
register.component.ts
import { ValidateService } from './../../services/validate.service';
import { Component, OnInit } from '#angular/core';
import { FlashMessagesService } from 'angular2-flash-messages';
import {AuthService} from '../../services/auth/auth.service';
import {Router } from '#angular/router';
#Component({
selector: 'app-register',
templateUrl: './register.component.html',
styleUrls: ['./register.component.css']
})
export class RegisterComponent implements OnInit {
name:String;
username:String;
email:String;
password:String;
constructor(private _validate:ValidateService,
private _flashMessagesService: FlashMessagesService,
private _authservice:AuthService,
private _router:Router) { }
ngOnInit() {
}
onRegisterSubmit(){
const user={
name:this.name,
username:this.username,
email:this.email,
password:this.password,
}
this._authservice.registerUser(user)
.subscribe(data =>{
console.log(data);
**if(data.success){**
this._flashMessagesService.show('Registration Succesfull ! ',{cssClass:'alert-success',timeout:3000})
this._router.navigate(['/login']);
}else{
this._flashMessagesService.show('Oops Something went wrong! ',{cssClass:'alert-danger',timeout:3000})
this._router.navigate(['/register'])
}
})
}
}
Error
ERROR in src/app/components/register/register.component.ts(49,17): error TS2339: Property 'success' does not exist on type 'Object'.
The data is submitting succesfully and even the angular is redirecting succesfully to the next component but this is giving error. in register.component.ts while subscribing the property success of the returned object in if statement if(data.success)
You can using code below:
dataRegister:any={}
//Function register
this._authservice.registerUser(user)
.subscribe(data =>{
this.dataRegister = data;
if(this.dataRegister.success){
//
}
else{
//
}
}
You can use type checking on your responses to avoid such errors.
Create a RegisterResponse class that will contain the structure of your HTTP response.
export class RegisterResponse {
public success: boolean;
public msg: string;
}
Then pass it to your http.post() method as generic parameter:
import { RegisterResponse } from './RegisterResponse'; // Or wherever it is..
export class AuthService {
constructor(private http:HttpClient) { }
registerUser(user){
let headers = new HttpHeaders();
headers.append('content-type','application/json');
return this.http.post<RegisterResponse>('http://localhost:8080/users/register', user, {headers:headers});
}
}
The registerUser() method will return you an Observable<RegisterResponse> type, so when you subscribe to it, you data variables will be of type RegisterResponse. But you can also specify the type if you want:
this._authservice.registerUser(user)
.subscribe((data: RegisterResponse) => {
if (data.success) {
// ...
}
else {
// ...
}
});
Hope it helps.
Service.ts code
import { Injectable } from '#angular/core';
import { HttpClient } from '#angular/common/http';
#Injectable({
providedIn: 'root'
})
export class ClientService {
constructor(private http: HttpClient) { }
getClients() {
return this.http.get<any>('http://localhost:8080/admin-api/client?count=15&page=0&q=', { withCredentials: true })
}
}
Component.ts code
import { Component, OnInit } from '#angular/core';
import { LazyLoadEvent } from 'primeng/api'
import { ClientService } from '../../services/client.service';
#Component({
selector: 'app-client',
templateUrl: './client.component.html',
styleUrls: ['./client.component.css']
})
export class ClientComponent implements OnInit {
constructor(private clientService: ClientService) { }
ngOnInit() {
this.loading = true
this.clientService.getClients().subscribe(data => {
console.log(data)
}, error => {
console.log(error)
})
}
}
The error I get when I run this
I don't understand why the same request can succeed using axios but not with the HttpClient in Angular.
Apparently, Axios adds the "X-XSRF-TOKEN" header when it detects the "XSRF-TOKEN" cookie whereas the HttpClient in Angular doesn't.
So you have to read the value of the "XSRF-TOKEN" cookie and set it as the header "X-XSRF-TOKEN" when sending your requests.