A Guide for Building Angular SPA with ASP.NET Core 5 Web API
Tags: angular, aspnetcore, webapi, spa
Published: 2021-10-20 18:42:12

These days, it is a common trend to build a single page application (SPA) using a modern front-end web framework such as Angular, React, Vue, etc., and a server-side backend Web API. In this tutorial, I will walk you through a complete example of creating a single page application using Angular that will connect a server-side ASP.NET Core 5 Web API to fetch data from a SQL Server database using Entity Framework Core (Code First). At the end of this tutorial, you will be able to display some useful stats related to football players.

[Download Source Code](https://github.com/ezzylearning/AspNetCoreAngularSpaDemo)

## What is a Single Page Application (SPA)

A single page application (SPA) is a type of web application that doesn’t load entire new pages from the server in an old and traditional way but instead loads data and contents from the server dynamically. SPA loads all necessary HTML, JavaScript, and CSS with a single page load, and the remaining resources are loaded dynamically usually from a backend Web API, and added to the page on different user actions. This technique results in an improved user experience because the user stays on the same page and control is never transferred to another page. Some popular examples of SPAs are Gmail, Facebook, Google Maps, Twitter, Pinterest, etc. There are many front-end frameworks to build SPAs and the most popular ones are [React](https://reactjs.org/) by Facebook and [Angular](https://angular.io/) by Google. Angular is the go-to option for developers who want to develop cross-platform, efficient, and sophisticated single-page apps using HTML, CSS, and TypeScript.

![Single Page Application (SPA)](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7d7ciwshy78djrqvkyo6.png)

## Creating Angular SPA in Visual Studio 2019

Open Visual Studio 2019 and create a standard ASP.NET Core Web Application project. Make sure ASP.NET Core 5.0 version is selected and you are choosing **ASP.NET Core with Angular** template as shown in the following screenshot.

![Create Angular Project in ASP.NET Core 5](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jz4oum66kqcqcapev4o3.png)

The above project template will generate a standard ASP.NET Core Web Application and a folder called **ClientApp** that contains the Angular client-side application.

![Angular Application Root Folder ClientApp in Visual Studio 2019](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6vm51g1z4jrfqjbj8pxc.png)

You will also notice that a default Web API controller named **WeatherForecastController** is also created for us in the Controllers folder that simply returns a list of **WeatherForecast** objects that contains some random forecast information.
```
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
    private static readonly string[] Summaries = new[]
    {
        "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
    };

    [HttpGet]
    public IEnumerable<WeatherForecast> Get()
    {
        var rng = new Random();
        return Enumerable.Range(1, 5).Select(index => new WeatherForecast
        {
            Date = DateTime.Now.AddDays(index),
            TemperatureC = rng.Next(-20, 55),
            Summary = Summaries[rng.Next(Summaries.Length)]
        }).ToArray();
    }
}
```
Before we start our implementation, the first thing we need to make sure is that we can run our Angular App in the browser and the app can load weather forecast information on the page. To do this, you need to install Angular CLI and need to run some commands.

Right-click on the **ClientApp** folder and choose the **Open in Terminal** command from the context menu.

![Developer Powershell Window in Visual Studio 2019](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5wz5s5fvkeqw520bytbt.png)

Visual Studio will open the Developer PowerShell window that can be used to run basic **npm** package manager commands. Let’s install the Angular CLI with the following command.
```
npm install -g @angular/cli
```
![Install Angular CLI using Developer Powershell in Visual Studio 2019](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/czmwm78j9x3qmxy7bmwt.png)

Next, run the following command that will serve the Angular SPA in the browser.
```
npm run ng serve
```
![Run Angular App from Developer Powershell](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zr8lyoakbfsld8bpbpn5.png)

Press F5 to start debugging and now you should be able to see the Angular SPA app opening in the browser. The default Angular App has three pages **Home**, **Counter,** and **Fetch data**. You can click the links shown on the navigation bar to navigate to these pages and notice that when you are navigating from one page to another page, there is no full page load from the server and the app is loading pages very quickly without a full postback to the server. Open the Fetch data page and you will notice that this page is calling the back end ASP.NET Core Web API and displaying weather information.

![ASP.NET Core Angular SPA running in Browser](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/toase80306pxuzfxzb26.png)

So far, we haven’t written a single line of code and we are just running the default Angular SPA app created by Visual Studio. It is now time to implement our custom feature in this application. I will create a new page that will display the following information about some Football players.  

![Angular Component Displaying Data from ASP.NET Core API](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uuiaaciyief9d5ul3zyd.png)

## Setting Up Database with Entity Framework Core (Code First)

We need to set up a database to store the player’s information and I have decided to use Entity Framework Code First approach for this tutorial. Install [Microsoft.EntityFrameworkCore.SqlServer](https://www.nuget.org/packages/Microsoft.EntityFrameworkCore.SqlServer/), [Microsoft.EntityFrameworkCore.Design](https://www.nuget.org/packages/Microsoft.EntityFrameworkCore.Design) and [Microsoft.EntityFrameworkCore.Tools](https://www.nuget.org/packages/Microsoft.EntityFrameworkCore.Tools/) NuGet packages in the project to perform some EF Core related development tasks.

Next, we need to create our entity models and we normally put our models in the **Models** folder by convention so let’s create a Models folder in the project root folder and create the following **Player** model class. Notice, how I used **[NotMapped]** attributes with some computed properties as I don’t want EF Core to generate database columns for those properties. The values of these properties can be calculated at runtime using the data available in other properties that’s why we normally don’t save such properties in the database.
```
public class Player
{
    [Key]
    public int Id { get; set; }

    [Required]
    public string Name { get; set; }
    
    public int ShirtNo { get; set; }
    public int Appearances { get; set; }
    public int Goals { get; set; }
    public PlayerPositions Position { get; set; }

    [NotMapped]
    public string PositionName => Position.ToString();

    [NotMapped]
    public decimal GoalsPerMatch => Math.Round((decimal)Goals / (decimal)Appearances, 2);
}
```
The Player class also has a property Position which is an Enum type property so create the following enum in the Models folder.
```
public enum PlayerPositions
{
    Goalkeeper,
    Defender,
    Midfielder,
    Forward
}
```
Next, create a **Data** folder in the project and create the DbContext class named **FootballDbContext** in this folder. The DbContext is the most important class of Entity Framework because an instance of DbContext represents a session with the database which can be used to query and save instances of our entities to a database. I am also overriding the **OnModelCreating** method to seed some player's information into the database table.
```
public class FootballDbContext : DbContext
{
    public FootballDbContext(DbContextOptions<FootballDbContext> options)
        : base(options)
    {

    }

    public DbSet<Player> Players { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Player>().HasData(
            new Player() { Id = 1, Name = "Juan Mata", ShirtNo = 8, Appearances  = 268, Goals = 54, Position = PlayerPositions.Forward},
            new Player() { Id = 2, Name = "Paul Pogba", ShirtNo = 6, Appearances  = 130, Goals = 28, Position = PlayerPositions.Midfielder},
            new Player() { Id = 3, Name = "David de Gea", ShirtNo = 1, Appearances  = 335, Goals = 0, Position = PlayerPositions.Goalkeeper},
            new Player() { Id = 4, Name = "Phil Jones", ShirtNo = 4, Appearances  = 200, Goals = 2, Position = PlayerPositions.Defender }
        );
    }
}
```
Next, we need to define our database connection string and we can save the connection string in the **appsettings.json** file. Please note that you need to specify your database server name instead of **DB_SERVER** in the following connection string.
```
"ConnectionStrings": {
    "DefaultConnection": "Server=DB_SERVER; Database=FootballDb; Trusted_Connection=True; MultipleActiveResultSets=true"
}
```
Next, we need to register the SQL Server database provider in **Startup.cs** file using the UseSqlServer method. The **UseSqlServer** method requires a database connection string and we can pass this information using the GetConnectionString method.
```
public void ConfigureServices(IServiceCollection services)
{
    services.AddControllersWithViews();

    // In production, the Angular files will be served from this directory
    services.AddSpaStaticFiles(configuration =>
    {
        configuration.RootPath = "ClientApp/dist";
    });

    services.AddDbContext<FootballDbContext>(options =>
        options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
}
```
Finally, we are ready to generate our database with the help of EF Core migrations. Migrations allow us to easily create a new database and then incrementally update the database schema to keep it in sync with the application models. You can run migrations using [.NET Core CLI tools](https://docs.microsoft.com/en-us/ef/core/cli/dotnet) outside Visual Studio or you can use [Package Manager Console tools](https://docs.microsoft.com/en-us/ef/core/cli/powershell) available in Visual Studio. For this tutorial, I will use Package Manager Console tools so let open Package Manager Console and add the following migration.
```
Add-Migration InitialDbCreateAndSeedData
```
EF Core will create a directory called **Migrations** in the project and will also generate some files in the folder. We are now ready to create our database and **Player** table using the migrations code generated by EF Core. This can be done by running the following command in Package Manager Console.
```
Update-Database
```
Open SQL Server database and you should see a new database **FootballDb** in the list of databases and if you will open the **Players** table you will see all of our data is seeded in the table. 

![Players Database Created using EF Core Code First Migrations](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2hcgu9394cnquryh3kwp.png)

If you want to learn EF Code First in detail then you can read my post [Data Access in ASP.NET Core using EF Core (Code First)](https://www.ezzylearning.net/tutorial/data-access-in-asp-net-core-using-ef-core-code-first). I also have a post about EF Core Database First  [Data Access in ASP.NET Core using EF Core (Database First)](https://www.ezzylearning.net/tutorial/data-access-in-asp-net-core-using-ef-core-database-first) in case you are interested.

## Creating ASP.NET Core Web API for Angular SPA

Angular apps can make Ajax based server-side calls and load and display data from backend APIs. We need to create an ASP.NET Core Web API to return Player's data that can be consumed by the Angular front-end app. Let’s create an API Controller **PlayerController** in the Controllers folder and inject **FootballDbContext** in the constructor.
```
[ApiController]
[Route("api/[controller]")]
public class PlayerController : ControllerBase
{
    private readonly FootballDbContext _context;

    public PlayerController(FootballDbContext context)
    {
        _context = context;
    }
}
```
Next, implement the following **GetPlayers** method which is simply returning all players from the Player table we created above.
```
[HttpGet]
public async Task<ActionResult<IEnumerable<Player>>> GetPlayers()
{
    return await _context.Players.ToListAsync();
}
```
Open the browser and test the API by adding **api/Player** in the URL as shown below. You should be able to see the player's data in JSON format.

![ASP.NET Core Web API in Angular SPA Application](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bpyoa6njz0t15zc99xkw.png)

If you want to learn more about ASP.NET Core Web APIs then read my tutorial [A Developer’s Guide for Creating Web APIs with ASP.NET Core 5](https://www.ezzylearning.net/tutorial/a-developers-guide-for-creating-web-apis-with-asp-net-core-5)

## Creating Angular Component to Consume ASP.NET Core Web API

Angular is a modular framework which means modules are the basic building block of the angular app. Each app must have at least one module which is called the root module and by default, it is defined in the **app.module.ts** file available in **ClientApp/src/app** folder

![app folder in angular application](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ax1ktmh9ov86ljh7fe11.png)

Angular modules can define both the components and services in them. Components are used to define different parts of the application. For example, in the above screenshot, you can see that all three pages of our Angular App **Home**, **Counter,** and **Fetch data** are defined as components and all of these components have their folders within the **app** folder with the names **home**, **counter,** and **fetch-data.**

A component consists of a view and a TypeScript class where the view defines the look and feel of the component using HTML and CSS and the class defines the functionality/behavior of the component using TypeScript. Every app must have at least one component also called root components and usually available in **app.component.ts** file also shown in the above screenshot.

For our app, we want to add another component **player** that will display all players coming from a backend Web API. You can add a new component from the command prompt using the following Angular CLI command
```
ng generate component player
```
If you don’t want to use Angular CLI you can also add a **player** folder in the **app** folder and add the following two files manually.

- player.component.ts
- player.component.html

Open the player.component.ts file and define your component as follows.
```
import { Component, Inject } from '@angular/core';
import { HttpClient } from '@angular/common/http';

@Component({
  selector: 'app-player',
  templateUrl: './player.component.html'
})
export class PlayerComponent {
  public players: Player[];

  constructor(http: HttpClient, @Inject('BASE_URL') baseUrl: string) {
    http.get<Player[]>(baseUrl + 'api/Player').subscribe(result => {
      this.players = result;
    }, error => console.error(error));
  }
}

interface Player {
  id: number;
  name: string;
  shirtNo: number;
  appearances: number;
  goals: number;
  positionName: number;
  goalsPerMatch: number;
}
```
The **PlayerComponent** class is calling our **api/Player** Web API using **HttpClient** and initializing the **player's** property of the class with the data loaded from the backend. We can now use this **player's** property in the view file **player.component.html** attached with the component using the **templateUrl** option.
```
<h1 id="tableLabel">Football Players</h1>
<p *ngIf="!players"><em>Loading...</em></p>
<table class='table table-striped' aria-labelledby="tableLabel" *ngIf="players">
   <thead>
      <tr>
         <th>Shirt No</th>
         <th>Name</th>
         <th>Position</th>
         <th>Appearances</th>
         <th>Goals</th>
         <th>Goals per match</th>
      </tr>
   </thead>
   <tbody>
      <tr *ngFor="let player of players">
         <td>{{ player.shirtNo }}</td>
         <td>{{ player.name }}</td>
         <td>{{ player.positionName }}</td>
         <td>{{ player.appearances }}</td>
         <td>{{ player.goals }}</td>
         <td>{{ player.goalsPerMatch }}</td>
      </tr>
   </tbody>
</table>
```
The above view code is also pretty straightforward. I am using **ngif** directive to render Loading… if players' property is not yet initialized. The ngif directive conditionally includes a template based on the value of an expression. If the expression evaluates to true, Angular renders the template.
```
<p *ngIf="!players"><em>Loading...</em></p>
```
The next important piece of code is where I am using **ngFor** to iterate all the **players** and displaying each player property in standard HTML **td** element.
```
<tr *ngFor="let player of players">
   <td>{{ player.shirtNo }}</td>
   <td>{{ player.name }}</td>
   <td>{{ player.positionName }}</td>
   <td>{{ player.appearances }}</td>
   <td>{{ player.goals }}</td>
   <td>{{ player.goalsPerMatch }}</td>
</tr>
```
Once our player component is complete, we need to register it in app.module where all application modules are declared.
```
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { HttpClientModule } from '@angular/common/http';
import { RouterModule } from '@angular/router';

import { AppComponent } from './app.component';
import { NavMenuComponent } from './nav-menu/nav-menu.component';
import { HomeComponent } from './home/home.component';
import { CounterComponent } from './counter/counter.component';
import { FetchDataComponent } from './fetch-data/fetch-data.component';
import { PlayerComponent } from './player/player.component';

@NgModule({
  declarations: [
    AppComponent,
    NavMenuComponent,
    HomeComponent,
    CounterComponent,
    FetchDataComponent,
    PlayerComponent
  ],
  imports: [
    BrowserModule.withServerTransition({ appId: 'ng-cli-universal' }),
    HttpClientModule,
    FormsModule,
    RouterModule.forRoot([
      { path: '', component: HomeComponent, pathMatch: 'full' },
      { path: 'counter', component: CounterComponent },
      { path: 'fetch-data', component: FetchDataComponent },
      { path: 'player', component: PlayerComponent }
    ])
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }
```
Finally, you need to add a new menu item on top of the page so that you can navigate to the players component and see list of players. Open the **nav-menu.component.html** file and declare the **Players** menu item as shown below:
```
<ul class="navbar-nav flex-grow">
	<li class="nav-item" [routerLinkActive]="['link-active']" [routerLinkActiveOptions]="{ exact: true }"> <a class="nav-link text-dark" [routerLink]="['/']">Home</a> </li>
	<li class="nav-item" [routerLinkActive]="['link-active']"> <a class="nav-link text-dark" [routerLink]="['/counter']">Counter</a> </li>
	<li class="nav-item" [routerLinkActive]="['link-active']"> <a class="nav-link text-dark" [routerLink]="['/fetch-data']">Fetch data</a> </li>
	<li class="nav-item" [routerLinkActive]="['link-active']"> <a class="nav-link text-dark" [routerLink]="['/player']">Players</a> </li>
</ul>
```
We have written lots of code and it is now time to see everything in action. Run the application using the method specified at the start of this tutorial and click the Players menu item shown on top of the page. You should see the page similar to the following with all player’s information.

![Angular Component Displaying Data from ASP.NET Core API](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uuiaaciyief9d5ul3zyd.png)

## Summary

Angular is a powerful front-end framework for building interactive model applications and when you combine this with the ASP.NET Core Web APIs backend, you can build some seriously amazing apps. In this tutorial, I have just covered the basics of combining Angular with ASP.NET Core. There is a lot more to explore and I will try to write more useful posts on these two technologies. If you have enjoyed this post, please share it with others and spread the knowledge.