Angular 4 and ASP.Net MVC 5 : returns an Empty JSON in response - asp.net

after merging angular app with asp.net MVC calling API from angular returns an empty JSON.
The angular and asp.net are in the same domain.
If I call the API With PostMan, I have a JSON with the result. but if I call it in the angular app my JSON result is empty.
Are there any tips for communicating angular app with asp.net MVC after merging and serving in the same domain?
Update 1:
The code that used to calling Webservice:
getSheets(): Observable<Sheet[]> {
return this.http.get(this.config.apiUrl + '/api/SheetsRelationAPI',
this.jwt())
.map(this.extractData)
.do(data => console.log('SheetsData:', data)) // debug
.catch(this.handleError);
}
/**
* Handle HTTP error
*/
private handleError(error: any) {
// In a real world app, we might use a remote logging infrastructure
// We'd also dig deeper into the error to get a better message
const errMsg = (error.message) ? error.message :
error.status ? `${error.status} - ${error.statusText}` : 'Server error';
console.error(errMsg); // log to console instead
return Observable.throw(errMsg);
}
// private helper methods
private jwt() {
// create authorization header with jwt token
const currentUser = JSON.parse(atob(this.cookie.getCookie('currentUser')));
if (currentUser && currentUser.access_token) {
const headers = new Headers({ 'Authorization': 'Bearer ' + currentUser.access_token},
);
return new RequestOptions({ headers: headers });
}
}
private extractData(res: Response) {
const body = res.json();
return body || [];
}
Update 2:
I notice that my API if I called it from outside domain it respond 2 times:
inspecting network with google chrome inspect element:
the first response is "zone.js" initiator and the second response is an "other" initiator
If I call the API from inside of the Domain I just have a response from "zone.js" initiator and it returns an empty JSON.
Update 3
export class OtherComponent implements OnInit {
sheets: Sheet[] = [];
errorMessage: string;
constructor(private httpService: HttpService) {
// this.sheets = this.ichartHttp.getSheets();
// console.log(this.sheets);
}
getSheets() {
this.httpService.getSheets()
.subscribe(
sheets => this.sheets = sheets,
error => this.errorMessage = <any>error
);
}
ngOnInit() {
this.getSheets();
}
}

The Problem is with my Authentication methods,
I use two types of authentication, MVC and WebAPI they conflict if I send a request to API under the same Domain.
So my Answer is: Your Angular Code looks good, take a look at your middleware project

Related

How to get new access token by using refresh token in AspNet.Security.OpenIdConnect.Server (ASOS)

I am using React as client and Web API core for back end interaction.
For Authentication we are using Token based authentication using AspNet.Security.OpenIdConnect.Server (ASOS).
I have to implement refresh token scenario where on expiration of access token we use refresh token (returned by ASOS) to get new access Token.
I know one way to achieve by calling method on client is in AXIOS interceptor like below.
httpPromise.interceptors.response.use(undefined, err => {
const { config, response: { status } } = err;
const originalRequest = config;
if (status === 401) {
var refresh_Token = JSON.parse(window.localStorage.getItem('refreshToken'));
fetch(globalConstant.WEB_API_BASE_PATH + "authtoken,
{
method: "POST",
headers: new Headers({
'Content-Type': 'application/json',
})
},
data:{grant-type:"refresh_Token",refresh_token:"refresh Token ....."
)
....other logic to set new access token and make call again to existing
request.
}
})
I want to done it in WEB API Core side, so that in middle ware or in authentication pipeline it detects access token expiration and return new access token. The glimpse of WEB API code is like below.
Startup.cs
public void ConfigureServices(IServiceCollection services)
{
.... some code
serives.AddAuthentication(o =>
{
o.DefaultAuthenticateScheme = OAuthValidationDefaults.AuthenticationScheme;
})
serives.AddOAuthValidation()
serives.AddOpenIdConnectServer(options =>
{
options.ProviderType = typeof(AuthorizationProvider);
options.Provider = new AuthorizationProvider(new SecurityService());
options.TokenEndpointPath = "/authtoken";
options.UserinfoEndpointPath = "/userInfo";
options.AllowInsecureHttp = true;
options.ApplicationCanDisplayErrors = true;
});
..some code
}
The links i followed How to handle expired access token in asp.net core using refresh token with OpenId Connect and https://github.com/mderriey/aspnet-core-token-renewal/blob/master/src/MvcClient/Startup.cs

Angular2 http get result empty for custom post types wordpress toolset

I am using wordpress rest api and angular2 to build simple one page app. I created a custom post type with toolset. All is working fine and I can see the data returning fine.
http://tncorp.biffapps.com/wp-json/wp/v2/downloads/?filter[product]=Pico
Screenshot
When try to request the data in my Angular application, the response body is empty.
Response
_body
:
"[]"
headers
:
Headers
ok
:
true
status
:
200
statusText
Does anyone know why this is happing?
Code for the http get:
getProductDownloads($id): Observable<any> {
this.ProductsDownloads = this.http.get(this.wpurl + 'downloads/?filter[product]='+$id)
.map(res => {
console.log('GET DOWNLOAD',res)
return this.ProductsDownloads = this.extractData(res)
})
.catch(this.handleError);
return this.ProductsDownloads;
}
You want to return the Observable itself:
getProductDownloads($id): Observable<any> {
return this.http.get(this.wpurl + 'downloads/?filter[product]='+$id)
.map(res => {
console.log('GET DOWNLOAD',res)
return this.ProductsDownloads = this.extractData(res)
})
.catch(this.handleError);
}
Then when you're calling it, you subscribe to the Observable.
// I'm using "this" here, but if you have it in a -service- you'd put that there
this.getProductDownloads(id).subscribe(result => {
this.products = result;
});
Also, you could do it the following way and incorporate the | async pipe in your template instead of manually subscribing & unsubscribing.
this.products = this.getProductDownloads(id);
// template:
{{ products | async }}

Chaining RxJS Observables with interval

my first question to the community out here!
i'm working on an app which does communicates to the API in the following way
step1: create request options, add request payload --> Post request to API
API responds with a request ID
Step2: update request options, send request ID as payload --> post request to API
final response: response.json
Now the final response can take a bit of time, depending on the data requested.
this can take from anywhere between 4 to 20 seconds on an average.
How do i chain these requests using observables, i've tried using switchmap and failed (as below) but not sure how do i add a interval?
Is polling every 4 second and unsubscribing on response a viable solution? how's this done in the above context?
Edit1:
End goal: i'm new to angular and learning observables, and i'm looking to understand what is the best way forward.. does chaining observable help in this context ? i.e after the initial response have some sort of interval and use flatMap
OR use polling with interval to check if report is ready.
Here's what i have so far
export class reportDataService {
constructor(private _http: Http) { }
headers: Headers;
requestoptions: RequestOptions;
payload: any;
currentMethod: string;
theCommonBits() {
//create the post request options
// headers, username, endpoint
this.requestoptions = new RequestOptions({
method: RequestMethod.Post,
url: url,
headers: newheaders,
body: JSON.stringify(this.payload)
})
return this.requestoptions;
}
// report data service
reportService(payload: any, method: string): Observable<any> {
this.payload = payload;
this.currentMethod = method;
this.theCommonBits();
// fetch data
return this._http.request(new Request(this.requestoptions))
.map(this.extractData)
.catch(this.handleError);
}
private extractData(res: Response) {
let body = res.json();
return body || {};
}
private handleError(error: any) {
let errMsg = (error.message) ? error.message :
error.status ? `${error.status} - ${error.statusText}` : 'Server error';
console.error(errMsg); // log to console instead
return Observable.throw(errMsg);
}
in my component
fetchData() {
this._reportService.reportService(this.payload, this.Method)
.switchMap(reportid => {
return this._reportService.reportService(reportid, this.newMethod)
}).subscribe(
data => {
this.finalData = data;
console.info('observable', this.finalData)
},
error => {
//console.error("Error fetcing data!");
return Observable.throw(error);
}
);
}
What about using Promise in your service instead of Observable, and the .then() method in the component. You can link as much .then() as you want to link actions between them.

How to recognise an existing Google OAuth authentication made via Firebase and perform a Google Directory API request in Angular 2?

I want to use my existing authentication and be able to use that same authentication to perform a get request to the Google Directory API. Here's my current code:
login() {
this.firebaseRef = new Firebase('https://xxx.firebaseio.com');
this.firebaseRef.authWithOAuthPopup("google", (error, authData) => {
if (error) {
console.log("Login Failed!", error);
} else {
console.log("Authenticated successfully with payload:", authData);
}
}, {
scope: "https://www.googleapis.com/auth/admin.directory.user.readonly"
});
}
getData() {
// TO-DO
// Recognise existing OAuth and perform a GET request to
// https://www.googleapis.com/admin/directory/v1/users?domain=nunoarruda.com
}
You could leverage the getAuth method on the firebaseRef instance. Something like that:
getData() {
var authData = this.firebaseRef.getData();
var provider = authData.provider;
// In your case provider contains "google"
}
See this documentation: https://www.firebase.com/docs/web/api/firebase/getauth.html.
I've found the solution. I need to use the current access token in the http request headers for the GET request.
import {Http, Headers} from 'angular2/http';
getData() {
// get access token
let authData = this.firebaseRef.getAuth();
let oauthToken = authData.google.accessToken;
console.log(oauthToken);
// set authorization on request headers
let headers = new Headers();
headers.append('Authorization', 'Bearer ' + oauthToken);
// api request
this.http.get('https://www.googleapis.com/admin/directory/v1/users?domain=nunoarruda.com',{headers: headers}).subscribe((res) => {
console.log(res.json());
});
}

create a synchronous http.get()

Im trying to handle a login via promises and http.get but i fail so hard I get following error :
Object doesn't support property or method 'toPromise'
My code is :
return this.http.get('http://localhost:5000/login/', {
headers: authHeader
}).map((response) => {
return response.json()
}).toPromise(null);
ive got it from :
https://github.com/johnpapa/angular2-there-and-back-again/blob/master/src/app/core/character.service.ts
UPDATE :
JohnPapa updated his project my friends
https://github.com/johnpapa/angular2-there-and-back-again/blob/master/app/core/character.service.ts
I wonder if you actually use promise since the HTTP support of Angular relies on Observables.
To get the response, you simply need to return the observable for your call:
getSomething() {
return this.http.get('http://localhost:5000/login/', {
headers: authHeader
}).map((response) => {
return response.json()
})
}
When calling the method, you can then register callbacks using the subscribe method:
getSomething().subscribe(
data => handleData(data),
err => reject(err));
If you really want to use promises (with the toPromise method), you should import this:
import 'rxjs/Rx';
See this issue for more details: https://github.com/angular/angular/issues/5632#issuecomment-167026172.
Otherwise, FYI calls aren't synchronous regarding HTTP in browsers...
Hope it helps you,
Thierry
If you want, you can use a TypeScript wrapper for sync-request library.
This TypeScript strongly-typed, fluent wrapper library is ts-sync-request.
ts-sync-request on npm
With this library, you can make sync http calls like below:
Your TypeScript classes:
class Request
{
Email: string;
}
class Response
{
isValid: boolean;
}
Install package in project:
npm i ts-sync-request
Then
import { SyncRequestClient } from 'ts-sync-request/dist'
GET:
let email = "jdoe#xyz.com";
let url = "http://localhost:59039/api/Movies/validateEmail/" + email;
var response = new SyncRequestClient()
.addHeader("Authorization", "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1NDc2OTg1MzgsIm5iZiI6MTU0NzY5NDIxOCwiaHR0cDovL3NjaGVtYXMueG1sc29hcC5vcmcvd3MvMjAwNS8wNS9pZGVudGl0eS9jbGFpbXMvbmFtZSI6InN0cmluZyIsImh0dHA6Ly9zY2hlbWFzLm1pY3Jvc29mdC5jb20vd3MvMjAwOC8wNi9pZGVudGl0eS9jbGFpbXMvcm9sZSI6InN0cmluZyIsIkRPQiI6IjEvMTcvMjAxOSIsImlzcyI6InlvdXIgYXBwIiwiYXVkIjoidGhlIGNsaWVudCBvZiB5b3VyIGFwcCJ9.qxFdcdAVKG2Idcsk_tftnkkyB2vsaQx5py1KSMy3fT4")
.get<Response>(url);
POST:
let url = "http://localhost:59039/api/Movies/validateEmailPost";
let request = new Request();
request.Email = "jdoe#xyz.com";
var response = new SyncRequestClient()
.addHeader("Authorization", "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1NDc2OTg1MzgsIm5iZiI6MTU0NzY5NDIxOCwiaHR0cDovL3NjaGVtYXMueG1sc29hcC5vcmcvd3MvMjAwNS8wNS9pZGVudGl0eS9jbGFpbXMvbmFtZSI6InN0cmluZyIsImh0dHA6Ly9zY2hlbWFzLm1pY3Jvc29mdC5jb20vd3MvMjAwOC8wNi9pZGVudGl0eS9jbGFpbXMvcm9sZSI6InN0cmluZyIsIkRPQiI6IjEvMTcvMjAxOSIsImlzcyI6InlvdXIgYXBwIiwiYXVkIjoidGhlIGNsaWVudCBvZiB5b3VyIGFwcCJ9.qxFdcdAVKG2Idcsk_tftnkkyB2vsaQx5py1KSMy3fT4")
.post<Request, Response>(url, request);
Hope this helps.

Resources