So I'm making a simple notes app using Entity Framework with ASP.Net Core for my backend and AngularJS for frontend.
The expected behaviour is that when the app initiates, it should load a list of notes that are already saved in my database (MySQL)
Thing is, when my app does the Get request it rertuns the following error:
Before this I had a problem with CORS that I solved by adding http:// to my connection string and after solving that, I got this. I've been looking all over the internet but I don't seem to find an answer.
This is my note.service.ts
import { HttpClient } from '#angular/common/http';
import { Injectable } from '#angular/core';
import { Observable } from 'rxjs';
import { Note } from '../note';
#Injectable({
providedIn: 'root'
})
export class NoteService {
private url: string = "http://localhost:44353/api/NotesLists";
constructor(private http: HttpClient) { }
getNotes(): Observable<Note[]> {
return this.http.get<Note[]>(this.url);
}
}
This is my home component (where I subscrirbe to get the response):
import { Component, OnInit } from '#angular/core';
import { NoteService } from '../services/note.service';
import { Note } from '../note';
#Component({
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.scss']
})
export class HomeComponent implements OnInit {
public notes: Note[] = [];
constructor(private noteService: NoteService) { }
ngOnInit(): void {
this.noteService.getNotes()
.subscribe(data => this.notes = data);
}
}
And my [HttpGet] request on .Net Core
[HttpGet]
public IActionResult Get()
{
try
{
var response = _datacontext.NotesList
.Include(notesList => notesList.Note)
.ToList();
if (response.Count == 0)
{
return NotFound();
}
return Ok(response);
}
catch (Exception e)
{
return StatusCode(500, e.Message);
}
}
And my DataContext for better context (Ha!)
using Microsoft.EntityFrameworkCore;
using noteAppAPI.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace noteAppAPI.Helpers
{
public class DataContext : DbContext
{
public DataContext(DbContextOptions<DataContext> option) : base(option)
{
}
public DbSet<NotesList> NotesList { get; set; }
public DbSet<Note> Notes { get; set; }
}
}
Thanks to #MarkHomer for his suggestion in the comments. The solution to this was:
Change connection string on note.service.ts from
private url: string = "http://localhost:44353/api/NotesLists";
to
private url: string = "http://localhost:44353/api/NotesLists";
This would lead me to have to enable CORS in my API so the HTTPS request would work.
To enable CORS in Startup.cs add in ConfigureServices method:
services.AddCors(c =>
{
c.AddPolicy("AllowOrigin", options => options.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader());
});
services.AddDbContext<DataContext>(option => {
option.UseMySql(connectionString, ServerVersion.AutoDetect(connectionString));
});
And also in Configure method in the same file:
app.UseCors(options => options.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader());
Related
I have a class in a webapi
public class Respuesta
{
public int Exito { get; set; }
public string Mensaje { get; set; }
public object Data { get; set; }
}
and have the following method in ASP.NetCore:
public IActionResult Get()
{ ..
using (NegociosAPIContext db = new NegociosAPIContext())
{
var lst = db.Cliente.ToList();
oRespuesta.Exito = 1;
oRespuesta.Data = lst;
return Ok(oRespuesta);
}
In the otherside (appAngular), I did the import in module.ts
import {HttpClientModule } from '#angular/common/http';
and it´s my code service:
Image
and on my controller
import { Component, OnInit } from '#angular/core';
import {ApiclienteService} from '../service/apicliente.service';
#Component({
selector: 'app-cliente',
...
})
export class ClienteComponent implements OnInit {
constructor(private apiCliente: ApiclienteService) {
apiCliente.getClientes().subscribe(response => {
console.log('respuesta:'+response);
})
}
…
}
If I make a call to the api in the browser, I get this
{
"exito":1,
"mensaje":" ",
"data":[
{
"id":1,
"nombre":"Liliana Torres"
},
{
"id":2,
"nombre":"Redmon Redinton"
}
]
}
Then in Angular app, I get only the {object Object}. When I try to put console.log('respuesta:'+response.json); this throws
undefined
An important that i forget was mi class in typescript; i have:
import { Icliente } from './ICliente';
export interface Response {
exito:number;
mensaje:string;
data:Icliente[];
}
Here is your json which is in response :
{
"exito":1,
"mensaje":" ",
"data":[
{
"id":1,
"nombre":"Liliana Torres"
},
{
"id":2,
"nombre":"Redmon Redinton"
}
]
}
To access to an attribute in this json, you can do (for example, for mensaje):
response.mensaje
To get Liliana Torres : response.data[0].nombre.
response.data[0] is equal to :
{
"id":1,
"nombre":"Liliana Torres"
}
and so on.
If you want to log the full json, use:
console.log('respuesta:', response);
or
console.log('respuesta:' + JSON.stringify(response));
The response you are getting is an object. So in order to get the data of the object, you can do it like this.
console.log('respuesta:' response['data']);
Let me know if this solves your issue. Thank you.
I have an component where i am adding a new object called customer by calling the api like this:
public onAdd(): void {
this.myCustomer = this.customerForm.value;
this.myService.addCustomer(this.myCustome).subscribe(
() => { // If POST is success
this.callSuccessMethod();
},
(error) => { // If POST is failed
this.callFailureMethod();
},
);
}
Service file:
import { HttpClient } from '#angular/common/http';
import { Injectable } from '#angular/core';
import { Observable, Subject } from 'rxjs';
import {ICustomer } from 'src/app/models/app.models';
#Injectable({
providedIn: 'root',
})
export class MyService {
private baseUrl : string = '....URL....';
constructor(private http: HttpClient) {}
public addCustomer(customer: ICustomer): Observable<object> {
const apiUrl: string = `${this.baseUrl}/customers`;
return this.http.post(apiUrl, customer);
}
}
As shown in component code, i have already subscribed the api call like this:
this.myService.addCustomer(this.myCustome).subscribe(
() => { // If POST is success
.....
},
(error) => { // If POST is failed
...
},
);
But,I want to subscribe the results in another component, I have tried like this:
public getAddedCustomer() {
this.myService.addCustomer().subscribe(
(data:ICustomer) => {
this.addedCustomer.id = data.id; <======
}
);
}
I am getting this lint error: Expected 1 arguments, but got 0 since i am not passing any parameter.
What is the right approach to subscribe the api call in other components? after POST operation.
Because i want to get added object id for other functionality.
Well it totally depends on the design of your application and the relation between components. You can use Subjects for multicasting the data to multiple subscribers.
import { HttpClient } from '#angular/common/http';
import { Injectable } from '#angular/core';
import { Observable, Subject } from 'rxjs';
import { ICustomer } from 'src/app/models/app.models';
#Injectable({
providedIn: 'root',
})
export class MyService {
private baseUrl : string = '....URL....';
private latestAddedCustomer = new Subject();
public latestAddedCustomer$ = this.latestAddedCustomer.asObservable()
constructor(private http: HttpClient) {}
public addCustomer(customer: ICustomer): Observable<object> {
const apiUrl: string = `${this.baseUrl}/customers`;
return this.http.post(apiUrl, customer).pipe(map((data) => this.latestAddedCustomer.next(data)));
}
}
and subscribing to the subject as follows
this.latestAddedCustomer$.subscribe()
should get you the latest added customer details. Even though i would not do this the way its written. I would basically write a seperate service to share the data between the components or would write a cache service if its used across the application. But the idea here is to use the concept of Subjects. You can read more about it Here
First of all, I am very new to Angular2 (or any other version actually) and I have followed several tutorials to get me started but I'm now in a dead end and I don't know how to proceed.
Here is the background: I am accessing a third party web API through a POST request (I did that in a service) and it returns HTML markup of the control I need to render on my page, so I made a component of it. It works fine (I had to create a custom pipe to work around the DOM sanitization though).
And here's my issue: in the markup I'm receiving from the web API there's JavaScript stuff to initialize the control that is supposed to execute as soon as it is on the page (it does in every other language I used this control in, PHP, Java, JavaScript, ASP.NET, etc) but for some reason, using Angular2 I can see the script in the DOM, properly inserted at the end of the markup but it does not execute so my control does not work.
Here is my component code:
import { Component, OnInit, ViewEncapsulation } from '#angular/core';
import { MyService } from './my.service'
#Component({
selector: 'mycontrol',
template: `<div style="width:1200px; height:1000px;" [innerHtml]="htmlContent | keepHtml"></div>`,
styleUrls: ['app/control-min.css'],
encapsulation: ViewEncapsulation.None
})
export class MyComponent implements OnInit {
htmlContent: any;
constructor(private myService: MyService) {
}
ngOnInit(): void {
this.myService.getControlMarkup().subscribe(
response => this.htmlContent = response["HtmlContent"],
error => this.htmlContent = <any>error
);
}
}
And here is my service code:
import { Injectable } from '#angular/core';
import { Http, Response, Headers, RequestOptions } from '#angular/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/Rx';
#Injectable()
export class MyService {
headers: Headers;
options: RequestOptions;
constructor(private http: Http) {
this.headers = new Headers({ 'Content-Type': 'application/json' });
this.options = new RequestOptions({ headers: this.headers });
}
getControlMarkup() {
let controlConfig = {
SessionId: "mySessionId",
ControlId: "MyControl1"
};
let body = JSON.stringify(controlConfig);
return this.http
.post('http://localhost:62968/api/GetControl', body, this.options)
.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);
return Observable.throw(errMsg);
}
}
Any idea how I can make this work?
I have a very strange problem. In angular (app built with ionic v1) I call some REST call built in java, but something goes wrong and chrome advise me with this error:
The code interesting is this, a REST service in angular js:
bankaccountsbyuser: function(_getbauser, _error){
var currentToken = _GetToken();
if(currentToken!=null){
var Headers = {
token: currentToken.tokenUser,
};
}
_timerTokenControl(currentToken, _error);
if (setupTime == null) {
console.log("token scaduto");
//modificare
//$window.location.href="login.html";
}
if (currentToken !== null) {
$http({
method : 'GET',
headers: Headers,
url : REST_URL+'bankaccount'
}).then(function successCallback(response) {
console.log(response)
_getbauser(response)
}, function errorCallback(response) {
console.log(response.statusText);
});
} else {
var alertPopup = $ionicPopup.alert({
title: 'Accesso negato!',
template: 'Devi essere un utente registrato, non sei loggato!'
});
console.log("NON SEI LOGGATO!!!");
}
},
debug:
How you can see, the get REST service returns an error, thus, let's see this REST service built in java:
package it.jack.fdd.services;
import java.util.List;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.HeaderParam;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import it.jack.fdd.dao.FactoryDao;
import it.jack.fdd.dao.impl.BankAccountDaoImpl;
import it.jack.fdd.dao.interfaces.BankAccountDao;
import it.jack.fdd.domain.BankAccount;
import it.jack.fdd.domain.User;
import it.jack.fdd.dto.TokenUserDto;
import it.jack.fdd.dto.UserDto;
import it.jack.fdd.util.ConverterDTO;
#Path("/bankaccount")
public class BankAccountServices {
#GET
#Produces(MediaType.APPLICATION_JSON)
public List<BankAccount> getBankAccountOfUser() {
BankAccountDao baDao = new BankAccountDaoImpl();
List<BankAccount> balist = baDao.getBAByUserId(1);
return balist;
}
I tryed to pass the number "1" in the method, just to simplify. The method is implemented below:
package it.jack.fdd.dao.impl;
import java.util.List;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;
import it.jack.fdd.dao.interfaces.BankAccountDao;
import it.jack.fdd.domain.BankAccount;
import it.jack.fdd.domain.Staff;
import it.jack.fdd.domain.User;
import it.jack.fdd.util.HibernateUtilLezione;
public class BankAccountDaoImpl extends BaseDaoImpl<BankAccount> implements BankAccountDao{
public List<BankAccount> getBAByUserId(int id) {
try{
Session session = HibernateUtilLezione.openSession();
Transaction tx = session.beginTransaction();
#SuppressWarnings("unchecked")
List<BankAccount> accounts = session.createQuery("from BankAccount b "
+ "where b.user= "+id).list();
tx.commit();
session.close();
return accounts;
}
catch(HibernateException e){
e.printStackTrace();
return null;
}
}
}
As you can see, the method ask for an id, and I put id 1 just to check, because in the database there is a field with that id. Trying in java, it returns me a list
[it.jack.fdd.domain.BankAccount#4f8d86e4]
And I checked also that the list has dimension 1 (thus, only one record, like in the database, only 1 record with that iduser)
Thus, trying to open this REST call using postman, the result is this:
The strange thing is that postman show me the same result to another REST call, that it worked before. But for this last REST call is not a problem, because strangely it works on my application, it doesn't work only in postman.
Thus, trying with Advanced REST Client I have a strange different result:
A strange, very big list that repeat every time the same field!! It is like a loop!
What happens? How I can solve?
Solved. The problem was in java's domain classes: when a domain class has a one-to-many relationship it's mandatory to put the tag #JsonIgnore to avoid these recurrent records in json file
Entity class:
package it.jack.fdd.domain;
// Generated 30-nov-2016 0.17.09 by Hibernate Tools 4.3.1.Final
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import static javax.persistence.GenerationType.IDENTITY;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
/**
* BankAccount generated by hbm2java
*/
#Entity
#Table(name = "bank_account", catalog = "fdd_dbproducts")
public class BankAccount implements java.io.Serializable {
private Integer idbankAccount;
private User user;
private String iban;
private String pin;
private String society;
private Date expiration;
public BankAccount() {
}
public BankAccount(User user, String iban, String pin, String society) {
this.user = user;
this.iban = iban;
this.pin = pin;
this.society = society;
}
public BankAccount(User user, String iban, String pin, String society, Date expiration) {
this.user = user;
this.iban = iban;
this.pin = pin;
this.society = society;
this.expiration = expiration;
}
#Id
#GeneratedValue(strategy = IDENTITY)
#Column(name = "idbank_account", unique = true, nullable = false)
public Integer getIdbankAccount() {
return this.idbankAccount;
}
public void setIdbankAccount(Integer idbankAccount) {
this.idbankAccount = idbankAccount;
}
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "fkuser_baccount", nullable = false)
public User getUser() {
return this.user;
}
public void setUser(User user) {
this.user = user;
}
#Column(name = "iban", nullable = false, length = 45)
public String getIban() {
return this.iban;
}
public void setIban(String iban) {
this.iban = iban;
}
#Column(name = "pin", nullable = false, length = 45)
public String getPin() {
return this.pin;
}
public void setPin(String pin) {
this.pin = pin;
}
#Column(name = "society", nullable = false, length = 45)
public String getSociety() {
return this.society;
}
public void setSociety(String society) {
this.society = society;
}
#Temporal(TemporalType.DATE)
#Column(name = "expiration", length = 10)
public Date getExpiration() {
return this.expiration;
}
public void setExpiration(Date expiration) {
this.expiration = expiration;
}
}
This question already has answers here:
How to return value from an asynchronous callback function? [duplicate]
(3 answers)
Closed 6 years ago.
Im having trouble merging 3 objects array. My objective is to merge 3 arrays to one and send HTTP POST to the server.
I have tried using concat but Im getting this error:
EXCEPTION: Error in ./PreviewEmailPage class PreviewEmailPage_Host - inline template:0:0 caused by: Cannot read property 'concat' of undefined
These are my codes:
import { Component } from '#angular/core';
import { NavParams, NavController, LoadingController } from 'ionic-angular';
import { Validators, FormGroup, FormControl } from '#angular/forms';
import { Http, Headers} from '#angular/http';
import 'rxjs/add/operator/map';
import { Storage } from '#ionic/storage';
#Component({
selector: 'preview-email-page',
templateUrl: 'preview-email.html',
})
export class PreviewEmailPage {
headers: Headers;
loading: any;
url: string;
preview: any[];
FirstArray: any[];
SecondArray: any[];
ThirdArray: any[];
PostData: any[];
constructor(
public nav: NavController,
public navParams: NavParams,
public loadingCtrl: LoadingController,
public localStorage: Storage,
public http: Http,
) {
this.localStorage.get('FirstArray').then((value) => {
this.FirstArray= value;
})
this.localStorage.get('SecondArray').then((value) => {
this.SecondArray= value;
})
this.localStorage.get('ThirdArray').then((value) => {
this.ThirdArray= value;
})
this.PostData = this.FirstArray.concat(this.SecondArray);
this.PostData = this.PostData.concat(this.ThirdArray);
this.loading = this.loadingCtrl.create();
}
ionViewWillEnter(){
this.headers = new Headers();
this.headers.append("Content-Type", "application/x-www-form-urlencoded");
console.log(this.PostData);
this.getPreview();
}
getPreview(){
this.loading.present();
this.url = 'https://domain.com/REST/getpreview.php';
this.http.post(this.url, this.PostData, {headers: this.headers}).map(res => res.json()).subscribe(res => {
console.log(res);
this.preview = res;
}, err => {
console.log('error');
})
}
}
Since this.localStorage.get is an async operation your this.FirstArray is not defined untill the then is executed.
What you can do is run them all in parallel with Promise.all:
Promise.all([this.localStorage.get('FirstArray'), this.localStorage.get('SecondArray'), this.localStorage.get('ThirdArray')]).then(values => {
this.FirstArray= values[0];
this.SecondArray= values[1];
this.ThirdArray= values[2];
this.PostData = this.FirstArray.concat(this.SecondArray);
this.PostData = this.PostData.concat(this.ThirdArray);
});