Angular 2 is not making http call from browser - asp.net-mvc

I have a problem in angular 2 in typescript that browser is not making HTTP Call. I dont see any HTTp call in network section in browser.
the angular code works when i dont have any http call in service and it brings data when i use HTTP it doenst make any http request
Following is my code.
<script src="~/lib/es6-shim.min.js"></script>
<script src="~/lib/system-polyfills.js"></script>
<script src="~/lib/shims_for_IE.js"></script>
<script src="~/lib/angular2-polyfills.js"></script>
<script src="~/lib/system.js"></script>
<script src="~/lib/Rx.js"></script>
<script src="~/lib/angular2.dev.js"></script>
<script src="~/lib/http.dev.js"></script>
<script src="~/lib/router.dev.js"></script>
SERVICE :
import {Injectable} from 'angular2/core';
import {Http, Response} from 'angular2/http';
import {Observable} from 'rxjs/Observable';
#Injectable()
export class AuthService {
private _authPath = 'http://api/Auth';
constructor(private http: Http) { }
getAuthSettings() {
return new Promise((resolve, reject) => {
return this.http.get(this._authPath).toPromise().then((val: Response) => resolve(val.text()));
});
}
private handleError(error: Response) {
// in a real world app, we may send the error to some remote logging infrastructure
// instead of just logging it to the console
console.error(error);
return Observable.throw(error.json().error || 'Server error');
}
}
main MODULE :
import { Component } from 'angular2/core';
import {AuthService} from './auth.service';
import {OnInit} from 'angular2/core';
import {HTTP_PROVIDERS} from 'angular2/http';
#Component({
selector: "main-app",
template: "{{title}}",
providers: [HTTP_PROVIDERS, AuthService]
})
export class AppComponent implements OnInit {
public title: string = '';
constructor(private _authService: AuthService) {
}
ngOnInit() {
//this.title = "aaa";
this._authService.getAuthSettings().then((val: string) => {
this.title = val;
});
//this._authService.getAuthSettings().subscribe((val: string) => this.title = val)
}
};

I dont see any HTTP call in network section in browser.
There might be some filters preventing you from seeing it. To be sure update the code as follows:
console.log('starting');
this._authService.getAuthSettings()
.then((val: string) => {
this.title = val;
console.log('success');
},() => console.log('fail'));
console.log('waiting');
And see which logs happen. Hopefully it helps. Sorry if it doesn't 🌹

Related

Angular 7 HttpClient POST - Bad request

Taking again the tutorial of the site Angular, I created in winamp a database with a table including a field {"id": id, "name": name} and I make 2 queries on this table with Symfony4:
1) A request to list heroes.
2) A request to create hero.
Executed from Angular 7, the query 1) works perfectly (route / listerHeroes).
Executed from Angular 7, query 2) does not work, it returns error 405 (route / ajouterHero). However launched from Postman, this query works.
I can not find any documentation to explain to me this bug on which I stumble for several days. A track please
Below copy of both classes: heroes.service.ts and component3.component.ts
// heroes.service.ts
import { Injectable } from '#angular/core';
import { HttpClient, HttpHeaders, HttpParams } from '#angular/common/http';
import { Observable, of } from 'rxjs';
import { catchError, map, tap } from 'rxjs/operators';
import { HttpErrorHandler, HandleError } from './http-error-handler.service';
import { Hero } from '../assets/Structure';
const httpOptions = {
headers: new HttpHeaders({
'Content-Type': 'application/json'
})
};
#Injectable({ providedIn: 'root' })
export class HeroesService {
heroesUrl = 'http://heroes/';
private handleError: HandleError;
constructor(private http: HttpClient, httpErrorHandler: HttpErrorHandler) {
this.handleError = httpErrorHandler.createHandleError('HeroesService');
}
getHeroes$(): Observable<Hero[]> {
return this.http.get<Hero[]>(`${this.heroesUrl}listerHeroes`, httpOptions);
}
addHero(hero: Hero): Observable<Hero> {
return this.http
.post<Hero>(`${this.heroesUrl}ajouterHero`, hero, httpOptions)
.pipe(catchError(this.handleError('addHero', hero)));
}
}
// component3.component.ts
import { Component, OnInit } from '#angular/core';
import { HeroesService } from '../heroes.service';
import { Hero } from '../../assets/Structure';
#Component({
selector: 'app-component3',
templateUrl: './component3.component.html',
styleUrls: ['./component3.component.css']
})
export class Component3Component implements OnInit {
heroes: Hero[];
editHero: Hero;
constructor(private heroesService: HeroesService) {}
ngOnInit() {
this.heroesService.getHeroes$().subscribe(res => (this.heroes = res));
}
addHero(name: string): void {
name = name.trim();
console.log('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF C3A name =', name);
if (!name) {
return;
}
const newHero: Hero = { 'id': 0, 'name': name } as Hero;
this.heroesService.addHero(newHero).subscribe(hero => {
console.log('GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG C3B hero= ', hero);
this.heroes.push(hero);
});
}
}
I found the solution:
The blocking was listed backend (Symfony4) which refused the pre-query OPTIONS. It was necessary to install and configure the bundle nelmio (https://github.com/nelmio/NelmioApiDocBundle) which allows the smooth running of the request.

How to display data from mvc controller using angular2

I have created a project including angular2 for front-end and i also created webapi project to consume data from database.
Controller Code return model:
UserInfo = JsonConvert.DeserializeObject<List<UsersVM>>(Response);
I want to iterate over this data model in my angular view. i trid creating angular http calls. but this not acceptable in my case. i need to call webapi from my mvc controllers and just to render that data from angular2 views.
Angular Model is :
export interface IUser {
Id: number;
ProductName: string;
ProductPrice: string;
}
Angular Service Code is:
import {
Injectable
} from '#angular/core';
import {
Http, Response, RequestOptions,
Request, RequestMethod, Headers
} from '#angular/http';
import {
IUser
} from './user';
import {
Observable
} from 'rxjs/Observable';
import 'rxjs/add/operator/do';
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/map';
#Injectable()
export class UserService {
private _productUrl = 'Home/GetAllProducts';
constructor(private _http: Http) { }
getProducts(): Observable<IUser[]> {
return this._http.get(this._productUrl)
.map((response: Response) => <IUser[]>response.json().value)
.catch(this.handleError);
}
private handleError(error: Response) {
console.error(error);
return Observable.throw(error.json().error || 'Server error');
}
}
Stuck in this, any links available in google doesn't correctly solve my issue.
Please guide.
Thanks
You have mentioned _productUrl as your API path, but it should be actual API URL with domain name and action call.
as :
private _productUrl = 'localhost:50962/products/';
Eg.
Service.ts
import { Injectable } from '#angular/core';
import { Http, Response, RequestOptions,Request, RequestMethod, Headers } from '#angular/http';
import { IUser } from './user';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/do';
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/map';
#Injectable()
export class UserService {
private _productUrl = 'localhost:50962/products/';
constructor(private _http: Http) { }
getProducts(): Observable<IUser[]> {
let header = this.initHeaders();
let options = new RequestOptions({ headers: header, method: 'get' });
return this._http.get(this._productUrl + 'getAllProducts', options)
.map((response: Response) => <IUser[]>response.json().value)
.catch(this.handleError);
}
private initHeaders(): Headers {
var headers = new Headers();
headers.append('Content-Type', 'application/json');
headers.append('Access-Control-Allow-Origin', '*');
return headers;
}
private handleError(error: Response) {
console.error(error);
return Observable.throw(error.json().error || 'Server error');
}
}
Also you can set environment variable for your API and use it in all your services. environment.API
export const environment = {
API: 'http://localhost:50962/',
WordPressAPI: 'http://localhost:58451/',
FacebookClientId: '45******',
}
return this._http.get(environment.API + 'products/getAllProducts', options)
.map((response: Response) => <IUser[]>response.json().value)
.catch(this.handleError);
You can use ngFor and the AsyncPipe
<div *ngFor="let user of getProducts() | async">
{{user.Id}}
{{user.ProductName}}
{{user.ProductPrice}}
</div>
A combination from both (use full path) Amol Bhor & Leon, and instead has the uri vars into env file use constants.ts file because for me environment is related to dev or prod environments. And to avoid memory leaks use asyn pipe, if not use unsubscribe into onDestroy method. Check docs for detail info.

Is it possible to create a Parser Class in Angular2(Typescript) to process response?

I know that i can make a component and a service in Angular 2(Typescript) and can parse the response in component, but i want my architecture to be like below as for any changes in response i will have to change only my parser:
Service : Do API call and fetch response. Has a get response method.
Parser : Gets Response and parses response and returns response in a usable form to the component.
Component : gets Response from the parser and display data to view.
For doing it i am using an observable from service and subscribing it in parser. And then using an observable from parser and subscribing it in component.
But getting a lot of errors while doing so. Do i miss any steps or is it the right approach to the problem.
Adding Code :
Component:::
import { AuthenticateParser } from './../../parsers/authenticate.parser';
import { Component, OnInit } from '#angular/core';
#Component({
selector: 'my-component',
moduleId: module.id,
templateUrl: './app.component.html',
providers : [AuthenticateParser]
})
export class AppComponent implements OnInit {
// Constructor Function
constructor(private _authenticationService: AuthenticateParser) {
}
ngOnInit(): void {
this._authenticationService.setAuthenticationToken();
}
}
Service :::
import { Observable } from 'rxjs/Observable';
import { IRequest } from './api.interaction.interface';
import { Http, Headers, RequestOptions, Response } from '#angular/http';
import { Injectable } from '#angular/core';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/do';
import 'rxjs/add/operator/catch';
#Injectable()
export class ApiInteractionService {
// Constructor Function
constructor(private _http: Http) {
}
getApiResponse(p_attr: IRequest): Observable<Response> {
// Set request url
let _authenticationUrl: string = p_attr.url;
// Set request body
let _body: any = p_attr.body;
// Set content type to JSON
let _headers = new Headers(p_attr.header);
// Set a request option
let _options = new RequestOptions({ headers: _headers });
return this._http[p_attr.method](_authenticationUrl, _body, _options)
.map((response: Response) => response.json()) ///... change response to JSON format
.do((data:any) => console.log('All : ' + JSON.stringify(data))) //... console response
.catch((error: any) => Observable.throw(error.json().error || 'Server error')); //...errors if any
}}
PARSER :::
import { Injectable, Component } from '#angular/core';
import { Observable } from 'rxjs/Observable';
import { IRequest } from './../services/api.interaction.interface';
import { ApiInteractionService } from './../services/api.interaction.service';
#Injectable()
export class AuthenticateParser {
private _authenticationToken: string = '';
// Constructor Function
constructor(private _authenticationService: ApiInteractionService) {
}
// Fetches Authentication Token
setAuthenticationToken(): void {
let p_url: string = 'http://10.5.214.82:8443/auth/authenticate';
let p_body: Object = {
"userId": "admin",
"password": "admin"
};
let p_header: Object = {
"Content-Type": "application/json"
};
let p_attrs: IRequest = {
'method': 'post',
'url': p_url,
'body': p_body,
'header': p_header
};
this._authenticationService.getApiResponse(p_attrs)
.subscribe(
response => this.parseSuccessResponse(response),
error => this.parseErrorResponse(error)
);
}
// Parses Token response and sets it.
parseSuccessResponse(p_response: any): void {
this._authenticationToken = p_response.data;
}
// Parses Error response and sets it.
parseErrorResponse(p_error: any): void {
this._authenticationToken = p_error.data;
}
// returns authentication token
getAuthenticationToken():string {
return this._authenticationToken;
}
}
Sounds like you want to make a parser as a service. Would have helped if you gave example code.
In your parser, you can subscribe to the http.get response, and then parse the response, and then publish the result to a subject. Then in your component you subscribe to the subject from parser.
Your parser will be something like:
import { Injectable, OnInit} from '#angular/core';
import { Subject } from 'rxjs/Subject';
import {YourService} from '....''
#Injectable()
export class ParseService implements OnInit {
public parseSubject: Subject<any> = new Subject <any>();
constructor(private service: YourService) {}
ngOnInit(){
this.service.yourGetFunction()
.map(res=> res.json())
.subscribe(
response => {
parse logic that stores result in parsedObj
parseSubject.next(parsedObj);
},
error => { this.errorMessage = <any>error});
}
}
Now in your component, you can import ParseService and subscribe to its parseSubject to get the parsed output

Getting Data with Header Authorization Ionic 2

I'm currently working on Ionic 2 with Ruby on Rails as a backend. The issue I face is that I have trouble understanding Observables and Promises. Are they related to each other? Right now I'm trying to retrieve the data after the POST request is authenticated with the header.
//clocks.ts (Provider)
import { Injectable } from '#angular/core';
import { Http, Headers, Response, RequestOptions } from '#angular/http';
import { Storage } from '#ionic/storage';
import 'rxjs/add/operator/map';
#Injectable()
export class Clocks {
baseUrl: string = "http://localhost:3000/api/v1"
token: any;
constructor(public http: Http, public storage: Storage) {}
getAttendanceInfo() {
return new Promise((resolve,reject) => {
// Load token
this.storage.get('token').then((value) => {
this.token = value;
let headers = new Headers();
headers.append('Authorization', 'Token ' + this.token);
this.http.get(this.baseUrl + '/attendances.json', {headers: headers})
.subscribe(res => {
resolve(res);
}, (err) => {
reject(err);
})
});
});
}
At Attendance Page
//attendance.ts (Page)
loadAttendance() {
this.clocks.getAttendanceInfo().then(res => {
let response = (<Response>res).json();
this.attendance = response.data;
console.log(this.attendance)
})
}
Here are my questions.
Could I use Observables in this case to achieve the same result as the getAttendanceInfo() method? How do they work?
And also, is there any way that I can retrieve the token from the storage for every page request without rewriting the same code for headers? Eg. One method that can always be used to retrieve the token from the storage and append at the header.
Greatly appreciate if you guys can clear my confusion.
I've found the solution.
You can create a authentication as part of the service provider. For this case, I'm using localStorage. For the remarks, the structure of the Token is dependent for your backend as well. For my case, I'm using authentication_with_http_token from Rails method, the structure is like this
GET /attendances HTTP/1.1
Host: localhost:3000
Authorization: Token token=123123123
We have to match that.
// ../providers/auth.ts
import { Injectable } from '#angular/core';
import { Http, Headers } from '#angular/http';
import 'rxjs/add/operator/map';
#Injectable()
export class Auth {
constructor(public http: Http) {}
createAuthorizationHeader(headers: Headers) {
headers.append('Authorization', 'Token ' + window.localStorage.getItem('token'));
}
}
Wen you return a http request, it was returned in a Observable format. Unless you want to convert into Promises, you don't have to do anything about it.
// ../pages/attendances/attendances.ts
import { Component } from '#angular/core';
import { NavController } from 'ionic-angular';
import { Auth } from '../../providers/auth';
#Component({
selector: 'page-home',
templateUrl: 'home.html'
})
const baseUrl: string = 'http://localhost:3000/api/v1/';
export class HomePage {
constructor(public navCtrl: NavController, public auth: Auth) {}
ionViewDidLoad() {
this.getAttendances();
}
getAttendances() {
return this.http.get(baseUrl + 'bookings.json', { headers: headers })
.map(data => {
// convert your data from string to json
data = data.json();
})
.subscribe(response => {
// to subscribe to the stream for the response
console.log(response);
// you can save your response in object based on how you want it
})
}

Passing asp.net server parameters to Angular 2 app

================================================================
EDIT : SOLUTION After upgrading to 2.0 Final - Passing server parameters to ngModule after RC5 upgrade
==================================================================
Any way to have server parameters passed to an Angular 2 application?
i.e. I would like to use the MVC object "HttpContext.User.Identity.Name" and have it injectable anywhere in my angular 2 app.
In angular 1 this was possible using ng ".constant" and serializing .Net objects to JSON in index.cshtml.
Looks like there's a way to pass params but this doesn't work with .Net code.
Define global constants in Angular 2
//HTML - Bootstrapping
<script>
System.import('app/main').then(null, console.error.bind(console));
//I WOULD LIKE TO PASS SOME PARAMS TO APP/MAIN HERE
</script>
FINAL SOLUTION: (big thanks to Thierry)
index.cshtml:
<script>
System.import('app/main').then(
module =>
module.main(
{
name: '#User.Identity.Name',
isAuthenticated: User.Identity.IsAuthenticated.ToString().ToLowerInvariant(),
}
),
console.error.bind(console)
);
</script>
main.ts:
...
import {provide} from '#angular/core';
...
export function main(params) {
bootstrap(AppComponent,
[
provide('Name', { useValue: params.name }),
provide('IsAuthenticated', { useValue: params.isAuthenticated }),
ROUTER_PROVIDERS,
HTTP_PROVIDERS,
LoggerService,
AuthenticationService
]);
}
Usage:
import {Component, Injectable, Inject} from '#angular/core';
import {ROUTER_DIRECTIVES} from '#angular/router';
#Component({
selector: 'navbar',
templateUrl: 'app/components/header/navbar.html',
directives: [ROUTER_DIRECTIVES]
})
export class SomeComponent {
constructor(#Inject('Name') public username: string) {
}
}
An option would be to add a method in the module you import. So you can then call it to provide the object you want.
Here is a sample of the app/main module:
import {bootstrap} from '...';
import {provide} from '...';
import {AppComponent} from '...';
export function main(params) {
let userIdentityName = params.name; // for example
bootstrap(AppComponent, [
provide('userIdentityName', { useValue: userIdentityName })
]);
}
Then you can import it from your HTML main page like this:
<script>
System.import('app/main').then((module) => {
module.main({
userIdentityName: 'something from asp.net'
});
});
</script>
Update
With latest versions of Angular, you need to leverage modules this way:
export const USER_IDENTITY_NAME_TOKEN =
new InjectionToken('userIdentityName');
#NgModule({
(...)
providers: [
{
provide: USER_IDENTITY_NAME_TOKEN,
useValue: userIdentityName
}
]
})
export class MainModule() { }
thanks for info, for those using platformBrowserDynamic to boot:
main.ts:
//platformBrowserDynamic().bootstrapModule(asstModule);
export function main(appSettings: any) {
platformBrowserDynamic([{ provide: 'AppSettings', useValue: appSettings }]).bootstrapModule(asstModule);
}
With a .NET Core server, I recommend to use a the IOptions<> and a ViewComponent
Startup.cs
public void ConfigureServices(IServiceCollection services)
{
// ...
services.AddOptions();
services.Configure<Models.EnvironmentSettings>(Configuration.GetSection("client"));
services.Configure<Models.EnvironmentSettings>(options =>
{
options.OtherSetting = "Other";
});
services.AddMvc();
}
Models/EnvironmentSettings.cs
public class EnvironmentSettings
{
public string OtherSetting { get; set; }
public string LoginUrl { get; set; }
}
appsettings.json
{
"client": {
"LoginUrl": "http://localhost:45290/Token"
}
}
Controllers/Components/BootstrapViewComponent.cs
public class BootstrapViewComponent : ViewComponent
{
private IOptions<EnvironmentSettings> environmentSettings;
public BootstrapViewComponent(
IOptions<EnvironmentSettings> environmentSettings
)
{
this.environmentSettings = environmentSettings;
}
public async Task<IViewComponentResult> InvokeAsync()
{
return View(environmentSettings.Value);
}
}
Views/Shared/Components/Bootstrap/Default.cshtml
#model YourApp.Models.EnvironmentSettings
<script>
System.import('app')
.then(function (module) {
module.main({
other: "#Model.OtherSetting",
loginUrl: "#Model.LoginUrl"
})
})
.catch(function (err) {
console.error(err);
});
</script>
Views/Shared/_Layout.cshtml
<head>
...
#await Component.InvokeAsync("Bootstrap")
</head>
main.ts
export function main(settings: any) {
platformBrowserDynamic([{ provide: 'EnvironmentSettings', useValue: settings }]).bootstrapModule(AppModule);
}

Resources