Loading...

how to connect angular 9 App with asp net core web api 3

Published
08-04-2020

intro

In this article we will go through the steps required in Angular to connect an Angular App with a DotNetCore API.

So far, we have created an Angular App which gets data from an internal or mock API. To replace this internal API we created a DotNetCore API using Web API and then installed CORS to permit connections from remote clients.

This article is part of a series which starts here. However, you can start from the end of the last article by downloading the Angular repo and the DotNetCore Web API repo.

run the API

To run from the API you will need to have installed DotNetCore 3.1.

If you are using Visual Studio run the API using F5. Navigate to the country endpoint and you will see something like the following:

Note the port number, you will need it in the next step to configure the Angular project to call the API correctly.

You can run the project from the command line by opening the command prompt at the project level and typing "dotnet run". The API will then be running at https://localhost:5001/. 

edit environment config

In the Angular project, edit the "environment.ts" to replace the existing apiUrl line which maps to the internal API. You should replace the existing line with the following, using your port number (either 5001 or whatever Visual Studio allocated - 44399 in the above image), so that it maps to the DotnetCore API:

apiUrl:"https://localhost:44399/"

 

edit Financials Service to use the DotNetCore API

We no longer want to load a json file from the internal API. Instead we want to call the country endpoint of the DotNetCore API.

Edit the "financials.service.ts" file to replace the countryUrl declaration line with the following:

countryUrl = `${environment.apiUrl}country`;
 
 
Also, we want to return an array of the "Country" object rather then the "MockAPICountryList" object . Replace the "getCountrys" method so that it contains the following:
 
getCountrys():Observable{
    return this.httpClient.get(this.countryUrl);
}

Fix any import references.

edit "country-list" component "ngOnInit" method

In the "country-list" component we were expecting the "MockAPICountryList" to be returned from the service. The "MockAPICountryList" contained a "countrys" property which we mapped to our "countrys" object in the component. However, since our service is now returning an array of "Country" objects we need to make a change.

Change the "ngOnInit" method of the "country-list" component so that it becomes :
 
this.financialsService.getCountrys().subscribe(x => {
  this.countrys = x;
});
Our component should now work. Check that it is and if not fix any errors.
 

check the results in Developer Tools

You may find it helpful to look in Developer Tools. Click on the "Network" tab and you should see something like the following:
 
 

In the "Network" tab click on the "country" line and you should see something like the following in the "Heading" tab:

 

and the following in the "Preview" tab (of the Network tab):

 

where have we got to now?

We have just replaced our internal, Angular only API, which delivered a list of countries, with an external API. An external API is almost certainly what a Angular App would connect to in the real world.

what's next?

We now need to populate our "stocks-list" and "funds-list" components with data from the API. When we created the external API we also created endpoints for stocks by country and funds by country. In the real world it's likely that the amount of data requested from the server is restricted in some way, as too much data might overload the database or make the client too slow. A view by country is a common implementation.

We want the "funds-list" and "stock-list" to populate based on the country selected in the "country-list", however at the moment these components know nothing about each other. The next step therefore is too introduce a way of communicating between components using Rxjs.

To implement the changes we have to extend our "financialsService" so that it :

  • keeps track of the selected country;
  • broadcasts a message when the selected country changes so that the fund and stock list components can request data for the country selected;
  • has a method to request stocks for a country from the API;
  • has a method to request funds by country from the API;

After that we will connect the "stock-list" and "fund-list" components to also use the "financialsService" and get data from the DotNetCore API.

add the stock and fund URLs to "financialsService"

Add the following lines below the countryUrl declaration line:

stockUrl = environment.apiUrl + "stock?countryId=";
fundUrl = environment.apiUrl + "fund?countryId=";

 

add a "SelectedCountry" subject to "financialsService"

Add an rxJs subject so that when "selectedCountry" changes we can broadcast the new value out to our components:

selectedCountry = new Subject();

 

add a "SelectCountry" method to "financialsService"

Add the following so that we can change the "selectedCountry" value when required eg from our "country-list":

selectCountry(countryId:number){
    this.selectedCountry.next(countryId);
}

 

add the "getStocks" and "getFunds" methods to "financialsService"

Add the methods that get stocks and funds and return an observable of those types:

getStocks(countryId:number):Observable{
    return this.httpClient.get(this.stockUrl + countryId);
}

getFunds(countryId:number):Observable{

    return this.httpClient.get(this.fundUrl + countryId);
}

 

modify "country-list" component to comunicate the "selectedCountry"

At the moment the "country-list" component doesn't do anything with the value that the user chooses. We need to amend the "onChange" method so that when a user chooses a country, it communicates that value with the outside world. We have added a method in "financialsService" for this purpose. Therefore when the user chooses a new value in the "country-list" component we will call that new method in "financialsService".

Modify the onChange method in "country-list.component.ts" to be the following:

onChange(){
  this.financialsService.selectCountry(this.SelectedCountryId);
}

 

connect the "stock-list" component to the "financialsService"

First add a stocks collection to hold the data from the "financialsService":

  stocks:Stock[];

Next, add a method towards the bottom of the "stock-list.component.ts" to call the getStocks method on the "financialsService" and map the data to our "stocks" array:

getData(countryId:number){
    this.financialsService.getStocks(countryId).subscribe(x => this.stocks = x);
}
However, as you can see the "getData" method needs a "countryId" value to call the "financialsService". The value we need comes from the "country-list" component, which is a completely unconnected component. However, we modified that component to provide the selected value to "financialsService". Therefore, we need add code to listen to "financialsService" for changes in the value of the "selectedCountry" variable, and then call the "getData" method with that new value. We do that by changing the constructor of the "stock-list.component.ts" to the following:
 
constructor(private financialsService:FinancialsService) {
financialsService.selectedCountry.subscribe(x =>
{
      this.getData(x);
});
}

 

change the template of "stock-list" component

Implement a simple list to iterate over the "stocks" array in the component. To do this, replace the existing contents of "stock-list.component.html" with the following:

connect the Fund list component to the service

Implement the same changes in the "fund-list" component as we made to the "stock-list" component. 

The App should now look like this when The "Funds" route is selected and a country has been selected:

summary

Our App is now connected to the API and displaying a list of countries, as well as a list of stocks and funds by country. We haven't made any changes to the DotNetCore API but you can access the finished Angular Git Repo here.

next

Managing the State of an Angular App becomes increasingly difficult as an App gets larger. The first approach I will look at is managing Application State using RxJS.


Latest posts