I am working with angular 6 trying to send a post request using httpclient , but always receive null body on the server side.
save( rules:RuleModel[]){
let _headers: HttpHeaders = new HttpHeaders({
'Content-Type': 'application/json; charset=utf-8'
});
return this._httpClient.post(AppConfig.BaseUrl,JSON.stringify(rules), {headers:_headers} ); }
and API function
[HttpPost]
public List<Rule> AddTemplateTextRules( [FromBody]Rule[] Rules)
{
try
{
return RuleManager.AddRule(Rules);
}
catch (Exception e)
{
return null;
}
return null;
}
To make a post request in Angular 6 with standard practice you need to do followings:
In the service class:
import {throwError, Observable } from 'rxjs';
import {catchError} from 'rxjs/operators';
import { Injectable } from '#angular/core';
import { HttpClient, HttpHeaders, HttpParams, HttpErrorResponse } from '#angular/common/http';
import { Rule } from 'path';
#Injectable()
export class RuleService {
constructor(private httpClient: HttpClient) { }
private baseUrl = window.location.origin + '/api/Rule/';
createTemplateTextRules(rules: Rules[]): Observable<boolean> {
const body = JSON.stringify(rules);
const headerOptions = new HttpHeaders({ 'Content-Type': 'application/json' });
return this.httpClient.post<boolean>(this.baseUrl + 'AddTemplateTextRules', body, {
headers: headerOptions
}).pipe(catchError(this.handleError.bind(this));
}
handleError(errorResponse: HttpErrorResponse) {
if (errorResponse.error instanceof ErrorEvent) {
console.error('Client Side Error :', errorResponse.error.message);
} else {
console.error('Server Side Error :', errorResponse);
}
// return an observable with a meaningful error message to the end user
return throwError('There is a problem with the service.We are notified &
working on it.Please try again later.');
}
}
In the Component:
export class RuleComponent implements OnInit {
constructor(private ruleService: RuleService) { }
createTemplateTextRules(): void {
this.ruleService.createTemplateTextRules(rules).subscribe((creationStatus) => {
// Do necessary staff with creation status
}, (error) => {
// Handle the error here
});
}
}
Then in the ASP.NET Core API Controller:
[Produces("application/json")]
[Route("api/Rule/[action]")]
public class RuleController : Controller
{
[HttpPost]
public Task<IActionResult> AddTemplateTextRules( [FromBody]Rule[] Rules)
{
try
{
return RuleManager.AddRule(Rules);
}
catch (Exception e)
{
return false;
}
return Json(true);
}
}
Hope it will help you.
With the latest RxJS(Angular 14) here is the way:
Service
Login(phone:string,password:string)
{
let _headers: HttpHeaders = new HttpHeaders({
'accept': 'application/json'
});
return this.http.post(this.url,{username,password},{headers:_headers})
.pipe(map(response=>response));
}
Component
async Login(phone:string,password:string)
{
let token$ = this.authService.Login(phone,password);
let token = await lastValueFrom(token$);
}
Since I was returning just text and not Json from the API, this was my code to handle text response type in the Service. If you're getting a response parse error, explicitly defining the responseType will help since Json is default.
Login(phone:string,password:string)
{
let _headers: HttpHeaders = new HttpHeaders({
'accept': 'text/plain'
});
return this.http.post(this.url+'security/login?phone='+phone+'&password='+password,null,{headers:_headers,responseType:'text'})
.pipe(map(response=>response));
}
Related
I am using Angular 9 (localhost:4200) and WebAPI with dotnet Core 3.1 (localhost:5000). During user registration I pass user data from Client to Server and then in Register method I send him an email to verify. After user clicks the link it redirects him to localhost:5000 to VerifyEmail method.
How to create a link in Registration function so the code could hit the client function first and then confirm verification on server?
Or there is better way to confirm email with Angular/dotnet core WebApi?
Client Side:
import { Injectable } from '#angular/core';
import { HttpClient } from '#angular/common/http';
import { User } from '../_models/user';
import { environment } from '../../environments/environment';
#Injectable({
providedIn: 'root'
})
export class AuthService {
baseUrl = environment.apiUrl + 'auth/';
constructor(private http: HttpClient) {}
register(user: User) {
return this.http.post(this.baseUrl + 'register', user);
}
}
verifyEmail(data: any) { // not used
return this.http.post(this.baseUrl + 'VerifyEmail', data);
}
Server Side:
[HttpPost("register")]
public async Task<IActionResult> Register(UserForRegisterDto userForRegisterDto)
{
var code = string.Empty;
var userToCreate = _mapper.Map<User>(userForRegisterDto);
try
{
var userExists = await _userManager.FindByNameAsync(userToCreate.UserName);
if (userExists == null)
{
var result = await _userManager.CreateAsync(userToCreate, userForRegisterDto.Password);
code = await _userManager.GenerateEmailConfirmationTokenAsync(userToCreate);
if (result.Succeeded)
{
//some code
}
}
else
{
var emailConfirmed = await _userManager.IsEmailConfirmedAsync(userExists);
code = await _userManager.GenerateEmailConfirmationTokenAsync(userExists);
if (emailConfirmed)
{
return Ok();
}
}
var link = Url.Action(nameof(VerifyEmail), "Auth", new { userId = userToCreate.Id, code }, Request.Scheme, Request.Host.ToString());
await _emailService.SendAsync("test#test.com", "email verify", $"Verify Email", true);
}
catch (Exception ex)
{
throw;
}
return Ok();
}
public async Task<IActionResult> VerifyEmail(string userId, string code)
{
if (string.IsNullOrEmpty(userId) || string.IsNullOrEmpty(code))
{
return BadRequest();
}
var user = await _userManager.FindByIdAsync(userId);
if (user == null)
{
return BadRequest();
}
if (user.EmailConfirmed)
{
//return Ok();
}
var result = await _userManager.ConfirmEmailAsync(user, code);
if (result.Succeeded)
{
return Ok();
}
return BadRequest();
}
Thank you in advance for any help and your time!
I'd create a new angular component that resolves to /verify-email route and from there called AuthService
import { Component, OnInit } from '#angular/core';
#Component({
selector: 'email-verification',
template: '<h1>{{status}}</h1>',
styleUrls: [ './email-verification.component.css' ]
})
export class EmailVerificationComponent implements OnInit {
status: string = "Verifying...";
constructor(private authService: AuthService){}
ngOnInit() {
this.authService.verifyEmail().subscribe(_ => this.status = "Email verified!");
//redirect to another component
}
}
I am using a service to get user ids in HTML DropDownList and it works fine. Here am using an Angular service to get the user details and for back-end, ASP.NET Web Api. So far this is what I've done so far:
Web Api - C#:
[Route("api/values/GetUserInfo")]
[Authorize]
[HttpGet]
public List<User> GetUserInfo(string type)
{
List<User> lst = null;
if (type!= null)
{
lst = GetUserInfo().Where(c => c.userType== type).ToList();
}
else
{
lst = GetUserInfo().ToList();
}
return lst;
}
Angular: Service - UserService
GetUserInfo(dept: string) {
debugger;
this.Url = 'http://localhost:53743/api/values/';
var a = this.Url + 'GetUserInfo';
var headers_object = new HttpHeaders().set("Authorization", "Bearer " + localStorage.getItem('Token')); //Set JWT Token
let params = new HttpParams().set("type", type);
return this.http.get<any>(a, { headers: headers_object, params: params }); //Get request to retrieve the user details from database server
}
Finally in the Angular Component:
public empIds: any[];
constructor(private dataservice: UserService, private appComponent: AppComponent, private sanitizer: DomSanitizer, private route: Router, private http: HttpClient) { //UserService injected in the constructor
}
ngOnInit() {
this.LoadUserData('');
}
LoadUserData(dept: string) {
debugger;
this.dataservice.GetUserInfo(dept).subscribe(result => { //Calling the `Angular` service here
this.empIds = result; //Keeping the result set here
}, error => console.error(error));
}
So far, these are my done work and was wondering if I can manage the header initiated once in every HTTP request. Like a class that handles all the post and get request and I did some research on it searching goggle but bit confused how could I make it work accordingly? Below is what I've been studying so far and trying to implement in my code sample. But the issue is when there are parameters how I could handle them with the following code sample.
Angular - httpService:
import { Injectable } from '#angular/core';
import { Http, Headers } from '#angular/http';
import { HttpClient, HttpHeaders, HttpParams } from '#angular/common/http';
#Injectable({
providedIn: 'root'
})
export class HttpClientService {
value: any;
constructor(private http: HttpClient) { }
createAuthorizationHeader(headers: HttpHeaders) {
//headers.append('content-type', 'application/json');
//headers.append("Authorization", "Bearer " + localStorage.getItem('Token'));
}
get(url, value, type) {
debugger;
let params = new HttpParams().set("dept", dept);
var headers_object = new HttpHeaders().set("Authorization", "Bearer " + value);
const httpOptions = {
headers: headers_object
};
return this.http.get<any>(url, {
headers: headers_object, params: params
});
}
post(url, data, value) {
let params = new HttpParams();
let headers_object = new HttpHeaders();
headers_object.append('content-type', 'application/json');
headers_object.append("Authorization", "Bearer " + value);
//this.createAuthorizationHeader(headers);
return this.http.post<any>(url, data, {
headers: headers_object, params: params
});
}
}
As an example below in the component:
this.httpService.get(a, localStorage.getItem('Token'), dept).subscribe(result => {
this.empIds = result;
}, error => console.error(error));
N.B: I am almost novice to Angular and it's working flow, trying to figure out the things in a better way - Thanks.
You should use interceptor.
If you want to add the specific headers in every request you have to do like the following : (Here I add Accept Header in every http request)
#Injectable()
export class ExampleAuth implements HttpInterceptor {
intercept(request: HttpRequest<any>, next: HttpHandler):
Observable<HttpEvent<any>> {
request = request.clone({ headers: request.headers.set('Accept', 'application/json') }); // Here you can add your special headers
return next.handle(request);
}
}
then add the interceptor in the provider section of your app module as below :
#NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
HttpClientModule
],
providers: [
{ provide: HTTP_INTERCEPTORS, useClass: ExampleAuth, multi: true }
],
bootstrap: [AppComponent]
})
export class AppModule { }
Now whenever a new HTTP request will be made, this Interceptor will modify the Headers of request.
More Explanations:
Angular Interceptor is a powerful feature which can be used in many ways for securing and handling many HTTP related phenomena.
What we can do using Interceptors?
Interceptors can be used in a number of ways in an application.
– Set request headers in HTTP calls like Content-Type or send any custom headers.
– Authenticate HTTP calls by setting Security tokens
– Show Spin Loaders/ Progress Bars as HTTPS calls are in progress.
– Handle Errors in HTTP calls at one place
– Show Response messages using Notifications/ Toasts
EDIT:
According to your example,In your HttpClientService , you have to remove the following lines because they will add automatically to the http request headers in the interceptor:
var headers_object = new HttpHeaders().set("Authorization", "Bearer " + value);
headers_object.append('content-type', 'application/json');
Modify your HttpClientService as below:
import { Injectable } from '#angular/core';
import { Http, Headers } from '#angular/http';
import { HttpClient, HttpHeaders, HttpParams } from '#angular/common/http';
#Injectable({
providedIn: 'root'
})
export class HttpClientService {
value: any;
constructor(private http: HttpClient) { }
get(url, value, type) {
debugger;
let params = new HttpParams().set("dept", dept);
const options = {
params: params
};
return this.http.get<any>(url, options);
}
post(url, data, value) {
let params = new HttpParams();
const options = {
params: params
};
return this.http.post<any>(url, data, options);
}
}
Then in the Interceptor we have to add the headers that we have just removed from HttpClientService
#Injectable()
export class ExampleAuth implements HttpInterceptor {
intercept(request: HttpRequest<any>, next: HttpHandler):
Observable<HttpEvent<any>> {
request = request.clone({ headers: request.headers.set('content-type', 'application/json') });
request = request.clone({ headers: request.headers.set("Authorization", "Bearer " + localStorage.getItem('Token') ) });
return next.handle(request);
}
}
Then register the interceptor in app module.
You can do it with HttpInterceptor which can intercept all your requests you make and all their responses.
You can thus also use it to display consistent error messages on each failed request.
You can have a look at Angular's documentation to see how to implement it.
The example the give is very similar to what you need:
import { AuthService } from '../auth.service';
#Injectable()
export class AuthInterceptor implements HttpInterceptor {
constructor(private auth: AuthService) {}
intercept(req: HttpRequest<any>, next: HttpHandler) {
// Get the auth token from the service.
const authToken = this.auth.getAuthorizationToken();
// Clone the request and replace the original headers with
// cloned headers, updated with the authorization.
const authReq = req.clone({
headers: req.headers.set('Authorization', authToken)
});
// send cloned request with header to the next handler.
return next.handle(authReq);
}
}
Iam getting a 401 unauthorized error while authorizing an user to consume an api on .net core and angular 7 application.
My angular service has a function :-
getUserProfile() {
var tokenHeader = new HttpHeaders({'Authorization':'Bearer ' + localStorage.getItem('token')});
console.log(tokenHeader)
return this.http.get('/api/ApplicationUser/UserProfile', { headers: tokenHeader});
}
on tokenHeader I am sending the user jwt token.
My api is
[HttpGet]
[Authorize]
[Route("UserProfile")]
//'api/userProfile'
public async Task<Object> GetUserProfile()
{
string userId = User.Claims.First(c => c.Type == "UserID").Value;
var user = await _userManager.FindByIdAsync(userId);
return new { user.fullName, user.Email, user.UserName };
}
I have tried some answers from other questions but nothing helps.
Any helps appreciated.
Your code should be like this
const httpOptions = {
headers: new HttpHeaders({
'Authorization': `Bearer ${localStorage.getItem('token')}`
})
};
return this.http.get('/api/ApplicationUser/UserProfile', httpOptions);
Also make sure you have this line in your controller
[Authorize(AuthenticationSchemes = "Bearer")]
Can you share your request from network tab.
Also I recommend to use interceptors for make it global
#Injectable()
export class TokenInterceptor implements HttpInterceptor {
private isRefreshing = false;
private refreshTokenSubject: BehaviorSubject<any> = new BehaviorSubject<any>(null);
constructor(public authService: AuthService) { }
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
if (this.authService.getJwtToken()) {
request = this.addToken(request, this.authService.getJwtToken());
}
return next.handle(request).pipe(catchError(error => {
if (error instanceof HttpErrorResponse && error.status === 401) {
return this.handle401Error(request, next);
} else {
return throwError(error);
}
}));
}
private addToken(request: HttpRequest<any>, token: string) {
return request.clone({
setHeaders: {
'Authorization': `Bearer ${token}`
}
});
}
private handle401Error(request: HttpRequest<any>, next: HttpHandler) {
if (!this.isRefreshing) {
this.isRefreshing = true;
this.refreshTokenSubject.next(null);
return this.authService.refreshToken().pipe(
switchMap((token: any) => {
this.isRefreshing = false;
this.refreshTokenSubject.next(token.jwt);
return next.handle(this.addToken(request, token.jwt));
}));
} else {
return this.refreshTokenSubject.pipe(
filter(token => token != null),
take(1),
switchMap(jwt => {
return next.handle(this.addToken(request, jwt));
}));
}
}
}
Full example https://github.com/bartosz-io/jwt-auth-angular/blob/master/src/app/auth/token.interceptor.ts
I am calling a WCF service from my angular 6 code and the data that is returned is in JSON. But when I am accepting the returned data it is throwing some error like :
Cannot find a differ supporting object '[{"Company_Prefix":"SCL","Company_Name":"Smart Chip Private Limited","Company_Code":"SCL"},{"Company_Prefix":"SYS","Company_Name":"Syscom Corporation Private Limited","Company_Code":"SYS"},{"Company_Prefix":"V-SCL","Company_Name":"Vihaan Infrasystems India Limited","Company_Code":"V-SCL"},{"Company_Prefix":"OT","Company_Name":"OT Morpho","Company_Code":"OT"}]' of type 'string'. NgFor only supports binding to Iterables such as Arrays.
I have tried MAP and It doesn't help.
TS file:
import { CompanyModel } from './../Models/app.CompanyModel';
import { CommonService } from './../../Shared/Common.service';
import { Component, OnInit } from '#angular/core';
import { CreateEmployeeModel } from '../Models/app.create-EmployeeModel';
#Component({
selector: 'app-create-employee',
templateUrl: './create-employee.component.html',
styleUrls: ['./create-employee.component.css',
'../../Content/vendor/bootstrap/css/bootstrap.min.css']
})
export class CreateEmployeeComponent implements OnInit {
private _employeeModel : CreateEmployeeModel;
UserName:string = sessionStorage.getItem('UserName');
companies: CompanyModel[];
departments: string[];
errorMessage: any;
constructor(private _CommonService:CommonService) { }
ngOnInit(): void {
debugger;
this._employeeModel = new CreateEmployeeModel();
this._employeeModel.UserName=this.UserName;
this._CommonService.BindCompany(this._employeeModel)
.subscribe(data =>
{
debugger;
this.companies=data;
},
error => this.errorMessage = <any>error);
// this._CommonService.BindDepartment(this._employeeModel).subscribe(data=>this.departments=data);
}
**Service:**
import { CompanyModel } from './../HR/Models/app.CompanyModel';
import { CreateEmployeeModel } from './../HR/Models/app.create-EmployeeModel';
import { Injectable } from '#angular/core';
import { Observable, throwError } from 'rxjs';
import { catchError, tap, map } from 'rxjs/operators';
import { HttpClient, HttpEvent, HttpHandler, HttpInterceptor, HttpRequest, HttpErrorResponse, HttpHeaders } from '#angular/common/http';
import { Router } from '#angular/router';
#Injectable({
providedIn: 'root'
})
export class CommonService {
private _parse;
private _response;
private data: any;
constructor(private _http: HttpClient, private _Route: Router) { }
private api='http://localhost:10704/CommonService.svc';
BindCompany(EmployeeModel: CreateEmployeeModel): Observable<CompanyModel[]>
{
let headers = new HttpHeaders({ 'Content-Type': 'application/json' });
debugger;
return this._http.get<CompanyModel[]>( this.api+'/BindCompany/' + EmployeeModel.UserName, { headers: headers } )
.pipe(tap(data=>{
debugger;
// this._parse=JSON.parse(data);
console.log(data);
if(data!=null)
{
return (data);
}
else
{
return null;
}
}),
catchError(this.handleError)
);
}
`````````````````````````````````````````````````````````````````````````
**JSON DATA THAT API RETURNS:**
`````````````````````````````````````````````````````````````````````````
[{"Company_Prefix":"XXX",
"Company_Name":"XXX Private Limited",
"Company_Code":"XXX"},
{"Company_Prefix":"XXX",
"Company_Name":"XXX Corporation Private Limited",
"Company_Code":"XXX"},
{"Company_Prefix":"V-XXX",
"Company_Name":"XXX Infrasystems India Limited",
"Company_Code":"V-XXX"},
{"Company_Prefix":"XXX",
"Company_Name":"OT XXX",
"Company_Code":"XXX"}]
It seems that you're not parsing the response. Make amend to your service while referring to the code below.
return this._http.get<CompanyModel[]>( this.api+'/BindCompany/' + EmployeeModel.UserName, { headers: headers } )
.pipe(tap(data=>{
if(data!=null)
{
return JSON.parse(data);
}
else
{
return null;
}
}),
catchError(this.handleError)
);
Ok I'm really confused about this one. I have a angular2 app and it successfully does a http GET request to my localhost server. I implement a return type of IHttpActionResult with a return status of Ok and send some content back but when I look at the response on my console the content is blank but ti is retrieving the appropriate status code ie(200 ok). I need to find a way to send back json to my andular2 service.
Below is my WebAPI2 controller:
[Route("api/login")]
public class LoginController : ApiController
{
[HttpGet]
public IHttpActionResult Login()
{
//return Content(HttpStatusCode.OK, Json(new { success = true }));
//return Json(new { success = true });
List<int> myValues = new List<int>(new int[] { 1, 2, 3 });
return Ok(myValues);
}
}
My angular2 Service:
import { Injectable } from '#angular/core';
import { Http, Headers, Response } from '#angular/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map'
#Injectable()
export class AuthService {
isLoggedIn = false;
private _url = "http://localhost:61333/";
constructor(private _http: Http) { }
login(login) {
return this._http.get(this._url + "api/login").map(res => res.json());
}
logout() {
this.isLoggedIn = false;
}
}
And my angular2 component that is invoking my login function in my service
import { Component, OnInit } from '#angular/core';
import { Router } from '#angular/router';
import { FormGroup } from '#angular/forms';
// Services
import { AuthService } from '../../_services/auth.service';
// Models
import { Login } from '../../_models/login.class';
#Component({
styles: [require('./login.component.css')],
template: require('./login.component.html')
//providers: [AuthService]
})
export class LoginComponent implements OnInit {
loginObj = new Login();
constructor(private _authService: AuthService, private _router: Router) {
}
login(form) {
this.loginObj.email = form.form._value.email;
this.loginObj.password = form.form._value.password;
this._authService.login(this.loginObj).subscribe(
value => { console.log("SUC:" + value); }
);
}
}
Thanks you.
Ross