Angular2 With ASP.NET WebAPI2 Controller sending blank content back - c#

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

Related

Can not get data from api in my angular 11 project

I develop a web API using .NET Core web API and then try to get data from it to my Angular11.
these are the codes
shared.service.ts
import { Injectable } from '#angular/core';
import { HttpClient } from '#angular/common/http';
import { observable, Observable } from 'rxjs';
#Injectable({
providedIn: 'root'
})
export class SharedService {
readonly APIUrl = "http://localhost:5000/api";
readonly PhotoUrl = "http://localhost:5000/photos";
constructor(private http: HttpClient) { }
getSecList(): Observable<any[]> {
return this.http.get<any>(this.APIUrl + '/section');
}}
show-sec.component.ts
import { Component, OnInit } from '#angular/core';
import { SharedService } from './../../shared.service';
#Component({
selector: 'app-show-sec',
templateUrl: './show-sec.component.html',
styleUrls: ['./show-sec.component.css']
})
export class ShowSecComponent implements OnInit {
constructor(private service: SharedService) { }
SectionList: any = [];
ngOnInit(): void {
this.refreshSecList();
}
refreshSecList() {
this.service.getSecList().subscribe(data => {
this.SectionList = data;
console.log(this.SectionList);
});
}
}
but I can not get data from api it shows following error in console.
how to fix this.

Not able to set the options of the dropdown to the fields returned by the api in json format

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)
);

Angular 6 Post Request to .NET Core API

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));
}

How to make a post and get works in a MVC project

I have an ASP.NET MVC app and I'm struggling with the connection between the typescript and the C#.
I can see that the C# is giving the response in the Inspect, the value is there but I don't know how to treat in Typescript.
C# Code:
namespace TEST.Controllers
{
[Route("api/[controller]")]
public class TestController : Controller
{
// GET api/GetTest
[HttpGet("GetTest")]
public IEnumerable<string> GetTest()
{
return new string[] { "Teste1", "Teste2" };
}
}
}
TypeScript SERVICE Code:
public getTest(): Observable<any> {
return this.dataService.get(this.baseUrl + '/GetTest')
.map((response: Response) => <any>response.json())
// .do(data => console.log("All: " + JSON.stringify(data)))
.catch(this.handleError);
}
Data Service Code (TypeScript):
public get<T>(url: string, params?: any): Observable<T> {
const options = new DataServiceOptions();
options.method = RequestMethod.Get;
options.url = url;
options.params = params;
return this.request(options);
}
private request(options: DataServiceOptions): Observable<any> {
options.method = (options.method || RequestMethod.Get);
options.url = (options.url || '');
options.headers = (options.headers || {});
options.params = (options.params || {});
options.data = (options.data || {});
this.interpolateUrl(options);
this.addXsrfToken(options);
this.addContentType(options);
this.addAuthToken(options);
// this.addCors(options);
const requestOptions = new RequestOptions();
requestOptions.method = options.method;
requestOptions.url = options.url;
requestOptions.headers = options.headers;
requestOptions.search = this.buildUrlSearchParams(options.params);
requestOptions.body = JSON.stringify(options.data);
this.pendingCommandsSubject.next(++this.pendingCommandCount);
const stream = this.http.request(options.url, requestOptions)
.catch((error: any) => {
this.handleErrors(error);
return Observable.throw(error);
})
.map(this.unwrapHttpValue)
.catch((error: any) => {
return Observable.throw(this.unwrapHttpError(error));
})
.finally(() => {
this.pendingCommandsSubject.next(--this.pendingCommandCount);
});
return stream;
}
The Calling:
private getDataBase() {
this.service.getTest().subscribe((res) => {
console.log(res);
this._proceduresImportData = res;
});
}
OBS: I also can console the observable, but I cannot treat it.
The best way to approach this is to have a generic request service and encapsulate your service calls, then inject that in where you need it. Taking get for an example (this can be expanded upon)
request.service.ts
import { Injectable } from "#angular/core";
import { Http, Response } from "#angular/http";
import { Observable } from "rxjs/Observable";
import "rxjs/add/operator/map";
import { WindowRef } from "./window.service";
#Injectable()
export class RequestService {
private baseUrl: string;
constructor(private http: Http, private windowRef: WindowRef) {
this.baseUrl = this.getBaseUrl();
}
public get<T>(resource: string): Observable<T> {
return this.http.get(this.baseUrl + resource)
.map<Response, T>(this.extractData);
}
private extractData(response: Response) {
return response.json();
}
private getBaseUrl(): string {
if (this.windowRef.getNativeWindow().location.hostname === "localhost") {
return "http://localhostAddress/api/";
} else if (this.windowRef.getNativeWindow().location.hostname === "anotherEnviroment") {
return "https://anotherAddress/api/";
}
}
}
window.service.ts
import { Injectable } from "#angular/core";
#Injectable()
export class WindowRef {
public getNativeWindow(): any {
return window;
}
}
This then returns an observable of the object you are expecting, used with a resolver or onInit it can be subscribed to where needed.
get-stuff.service.ts
import { Injectable } from "#angular/core";
import { Observable } from "rxjs/Observable";
import { RequestService } from "../common/request.service";
#Injectable()
export class Service {
constructor(private requestService: RequestService) { }
public getTestService(): void {
let requestedStuff: Observable<string[]> = this.requestService.get<string[]>(`GetTest`);
requestedStuff.subscribe(stuff: string[]) => {
//do stuff with your string
}
}
}
Then subscribe and use your data
Hope that helps

How to handle async data in ngOnInit (routing with parameter) Angular 4

I am trying to load data from my web api controller.
Currently I am using my API service which I call from the ngOnInit function of the component.
But, nothing return in the view because it's an asynchronous data
Web api controller
[HttpGet("[action]")]
public async Task<UserModel> GetUserById(int id)
{
Response.StatusCode = 200;
try
{
_context = new AuthentificationDbContext();
UserModel user = await _context.User.SingleOrDefaultAsync(m => m.id == id);
if (user == null)
{
return null;
}
else
return (user);
}
catch (SqlException ex)
{
throw ex;
}
}
userService.ts
getUserId(id: number) : Observable<User>{
return this.http.get(this.url + 'userApi/GetUserById/?id=' + id)
.map(res => <User>res.json())
.catch(this.handleError);
}
app.routing.ts
{ path: 'user/:id', component: UserComponent}
export const routing = RouterModule.forRoot(appRoutes,{
enableTracing:true});
export const routedComponents = [UserComponent];
user.component.ts
export class UserComponent implements OnInit {
private user: User;
constructor(private userService: UserService, private route: ActivatedRoute, private router: Router) { }
ngOnInit() {
this.route.paramMap
.switchMap((params: ParamMap) =>
this.userService.getUserId(+params.get('id')))
.subscribe((user: User) => {
this.user = user;
});
}
}
user.cshtml
<div *ngIf="user">{{ user.name}}</div>
But, when I tried with that example, that's work because not asynchronous
import { Injectable, Inject } from '#angular/core';
import { Http, Response, RequestOptions, Headers } from '#angular/http';
import { Observable } from 'rxjs/Observable';
export class User {
constructor(public id: number, public name: string) { }
}
let Users = [
new User(11, 'Mr. Nice'),
new User(12, 'Narco')
];
let usersPromise = Promise.resolve(Users);
#Injectable()
export class UserService {
constructor( #Inject(Http) public http: Http) { }
getUserId(id: number | string) {
return usersPromise
.then(users => users.find(user => user.id === +id));
}
}
My question : how to load async data in ngOnInit?
I used by promise also, but doesn't work
If you use
{{user.view}}
in the components template, you'll get an error, because user isn't available immediately.
{{user?.view}}
(safe-nativation operator) avoids this error by not throwing an exception when user is null.
I can resolve my problem (it's related to routing) :
my code just need to insert this :
<script>document.write('<base href="' + document.location + '" />');</script>
at the top of the 'head' section.
And to insert in constructor from app.component.ts, this methode:
click() {
this.router.navigate(['', { foo: 'bar' }]);
}

Categories