Create the Angular Application
Create Project
- Create Project Folder named SuperHeroNG

- Download Node.js

- Open project forder in Visual Studio Code
- Set powershell policy with
Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy RemoteSigned
- Download Angular CLI with
npm install -g @angular/cli
- Create new angular projekt skeleton with
ng new SuperHero.UI
in SuperHeroNG folder



- Add
components
,models
andservices
folders in src/app - Run angular with
ng serve -o
in SuperHero.UI folder


Add the Super Hero Model to the Client
Download Extensions
- Download
Angular Language Service
in Visual Studio Code

Super Hero Model
- SuperHero.UI/src/app/models/super-hero.ts
export class SuperHero {
id?: number;
name = "";
firstName = "";
lastName = "";
place = "";
}
Generate an Angular Service
Service
- Move to app\services
- Create super-hero service with
ng g s super-hero --skip-tests

- SuperHero.UI/src/app/services/super-hero.service.ts
...
export class SuperHeroService {
constructor() { }
public getSuperHeroes() : SuperHero[] {
let hero = new SuperHero();
hero.id = 1;
hero.name = "Spider Man";
hero.firstName = "Peter";
hero.lastName = "Parker";
hero.place = "New York City";
return [hero];
}
...
Component
-
Clear app/app.component.html
-
SuperHero.UI/src/app/app.component.ts
...
export class AppComponent {
title = 'SuperHero.UI';
heroes: SuperHero[] = [];
constructor(private superHeroService: SuperHeroService) {}
ngOnInit() : void {
this.heroes = this.superHeroService.getSuperHeroes();
console.log(this.heroes);
}
...
Run
- Run with
ng serve -o


Implement a Table to Show the Hero List
- SuperHero.UI/src/app/app.component.html
<table>
<thead>
<th>Name</th>
<th>First Name</th>
<th>Last Name</th>
<th>Place</th>
</thead>
<tbody>
<tr *ngFor="let hero of heroes">
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
</tbody>
</table>

Create the .Net 6 Web API Project
- Create a ASP.NET CORE WEB API project named SuperHeroAPI on same folder with UI in Visual Studio

Add the Super Hero Model to the API
- SuperHeroAPI/SuperHero.cs
public class SuperHero
{
public int Id { get; set; }
public string Name { get; set; } = string.Empty;
public string FirstName { get; set; } = string.Empty;
public string LastName { get; set; } = string.Empty;
public string Place { get; set; } = string.Empty;
}
Add the Super Hero Controller
- SuperHeroAPI/Controller/SuperHeroController.cs
[Route("api/[controller]")]
[ApiController]
public class SuperHeroController : ControllerBase
{
[HttpGet]
public async Task<ActionResult<List<SuperHero>>> GetSuperHeroes()
{
return new List<SuperHero>
{
new SuperHero
{
Name = "Spider Man",
FirstName = "Peter",
LastName = "Parker",
Place = "New York City"
}
};
}
}
Call the Web API from the Angular 14 Client
-
Copy your Web API url and paste on your angular.
-
SuperHero.UI/src/environment/environment.ts
export const environment = {
production: false,
apiUrl: "https://localhost:7169/api"
};
- SuperHero.UI/src/app/services/super-hero.service.ts
...
export class SuperHeroService {
private url = "SuperHero";
constructor(private http: HttpClient) { }
public getSuperHeroes() : Observable<SuperHero[]> {
return this.http.get<SuperHero[]>(`${environment.apiUrl}/${this.url}`);
}
}
...
- SuperHero.UI/src/app/app.module.ts
...
import { HttpClientModule } from '@angular/common/http';
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
AppRoutingModule,
HttpClientModule
],
...
- SuperHero.UI/src/app/components/app.component.ts
...
ngOnInit() : void {
this.superHeroService
.getSuperHeroes()
.subscribe((result: SuperHero[]) => (this.heroes = result));
}
...
Enable CORS(Cross-Origin Resource Sharing)
- SuperHero.API/Program.cs
builder.Services.AddCors(options => options.AddPolicy(name: "SuperHeroOrigins", // To Access the Origins
policy =>
{
policy.WithOrigins("http://localhost:4200").AllowAnyMethod().AllowAnyHeader();
}));
...
app.UseCors("SuperHeroOrigins");
...

Add Entity Framework Core 6
-
Create Data folder in SuperHeroAPI
-
SuperHero.API/Data/DataContext.cs
public class DataContext : DbContext
{
public DataContext(DbContextOptions<DataContext> options) : base(options)
{
}
public DbSet<SuperHero> SuperHeroes => Set<SuperHero>();
}
- Download
Microsoft.EntityFrameworkCore.Design
andMicrosoft.EntityFrameworkCore.SqlServer
in Nuget Package manager

Add the Connection String for the SQL Server Database
- SuperHero.API/appsettings.json
...
"ConnectionStrings": {
"DefaultConnection": "server=localhost\\sqlexpress;database=superherodb;trusted_connection=true"
},
...
Install the EF Core Tools
- Download Dotnet EntityCore Tools with
dotnet tool install --global dotnet-ef
and check withdotnet ef


Register the DataContext in the Program.cs
- SuperHero.API/Program.cs
builder.Services.AddDbContext<DataContext>(options =>
{
options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection"));
});
Run the Initial Migration using Code-First Migration
- Migration data table with
dotnet ef migrations add Initial

- Update database with
dotnet ef database update

Get Super Heroes from the Database
- SuperHero.API/Controllers/SuperHeroController.cs
[Route("api/[controller]")]
[ApiController]
public class SuperHeroController : ControllerBase
{
private readonly DataContext _context;
public SuperHeroController(DataContext context)
{
_context = context;
}
[HttpGet]
public async Task<ActionResult<List<SuperHero>>> GetSuperHeroes()
{
return Ok(await _context.SuperHeroes.ToListAsync());
}
}
- Add a row in database

Implement Create, Update and Delete in the SuperHeroController
- SuperHero.API/Controllers/SuperHeroController.cs
...
[HttpPost]
public async Task<ActionResult<List<SuperHero>>> CreateSuperHero(SuperHero hero)
{
_context.SuperHeroes.Add(hero);
await _context.SaveChangesAsync();
return Ok(await _context.SuperHeroes.ToListAsync());
}
[HttpPut]
public async Task<ActionResult<List<SuperHero>>> UpdateSuperHero(SuperHero hero)
{
var dbHero = await _context.SuperHeroes.FindAsync(hero.Id);
if (dbHero == null)
return BadRequest("Hero not found.");
dbHero.Name = hero.Name;
dbHero.FirstName = hero.FirstName;
dbHero.LastName = hero.LastName;
dbHero.Place = hero.Place;
await _context.SaveChangesAsync();
return Ok(await _context.SuperHeroes.ToListAsync());
}
[HttpDelete("{id}")]
public async Task<ActionResult<List<SuperHero>>> DeleteSuperHero(int id)
{
var dbHero = await _context.SuperHeroes.FindAsync(id);
if (dbHero == null)
return BadRequest("Hero not found.");
_context.SuperHeroes.Remove(dbHero);
await _context.SaveChangesAsync();
return Ok(await _context.SuperHeroes.ToListAsync());
}
...
Build a Edit-Hero Component with Angular
- Add a new component with
ng n c edit-hero --skip-tests
in app\components

- SuperHero.UI/src/app/components/edit-hero.component.ts
...
export class EditHeroComponent implements OnInit {
@Input() hero?: SuperHero;
...
updateHero(hero:SuperHero){
}
deleteHero(hero:SuperHero){
}
createHero(hero:SuperHero){
}
...
- SuperHero.UI/src/app.module.ts
...
imports: [
BrowserModule,
AppRoutingModule,
HttpClientModule,
FormsModule
],
...
- SuperHero.UI/src/app/components/edit-hero.component.ts
<div *ngIf="hero">
<h2></h2>
<div>
Name:
<input [(ngModel)]="hero.name" placeholder="Name"/>
</div>
<div>
First Name:
<input [(ngModel)]="hero.firstName" placeholder="First Name"/>
</div>
<div>
Last Name:
<input [(ngModel)]="hero.lastName" placeholder="Last Name"/>
</div>
<div>
Place:
<input [(ngModel)]="hero.place" placeholder="Place"/>
</div>
<button (click)="updateHero(hero)" *ngIf="hero.id">Save</button>
<button (click)="deleteHero(hero)" *ngIf="hero.id">Delete</button>
<button (click)="createHero(hero)" *ngIf="!hero.id">Create</button>
</div>
Add the Edit-Hero Form to the Parent Form
- SuperHero.UI/src/app/app.component.html
<button (click)="initNewHero()">Create New Hero</button>
<table>
<thead>
<th>Name</th>
<th>First Name</th>
<th>Last Name</th>
<th>Place</th>
</thead>
<tbody>
<tr *ngFor="let hero of heroes">
<td></td>
<td></td>
<td></td>
<td></td>
<td><button (click)="editHero(hero)">Edit</button></td>
</tr>
</tbody>
</table>
<app-edit-hero [hero]="heroToEdit"></app-edit-hero>
- SuperHero.UI/src/app/app.component.ts
export class AppComponent {
title = 'SuperHero.UI';
heroes: SuperHero[] = [];
heroToEdit?: SuperHero;
constructor(private superHeroService: SuperHeroService) {}
ngOnInit() : void {
this.superHeroService
.getSuperHeroes()
.subscribe((result: SuperHero[]) => (this.heroes = result));
}
initNewHero(){
this.heroToEdit = new SuperHero();
}
editHero(hero: SuperHero){
this.heroToEdit = hero;
}
}

Implement Web Service Calls on the client
- SuperHero.UI/src/app/services/super-hero.service.ts
export class SuperHeroService {
private url = "SuperHero";
constructor(private http: HttpClient) { }
public getSuperHeroes() : Observable<SuperHero[]> {
return this.http.get<SuperHero[]>(`${environment.apiUrl}/${this.url}`);
}
public upgradeHero(hero: SuperHero) : Observable<SuperHero[]> {
return this.http.put<SuperHero[]>(`${environment.apiUrl}/${this.url}`, hero);
}
public createHero(hero: SuperHero) : Observable<SuperHero[]> {
return this.http.post<SuperHero[]>(`${environment.apiUrl}/${this.url}`, hero);
}
public deleteHero(hero: SuperHero) : Observable<SuperHero[]> {
return this.http.delete<SuperHero[]>(`${environment.apiUrl}/${this.url}/${hero.id}`);
}
}
Call the Service in the EditHero Component
- SuperHero.UI/src/app/components/edit-hero.component.ts
export class EditHeroComponent implements OnInit {
@Input() hero?: SuperHero;
@Output() heroesUpdated = new EventEmitter<SuperHero[]>();
constructor(private superHeroService: SuperHeroService) { }
ngOnInit(): void {}
updateHero(hero:SuperHero){
this.superHeroService.upgradeHero(hero).subscribe((heroes: SuperHero[]) => this.heroesUpdated.emit(heroes));
}
deleteHero(hero:SuperHero){
this.superHeroService.deleteHero(hero).subscribe((heroes: SuperHero[]) => this.heroesUpdated.emit(heroes));
}
createHero(hero:SuperHero){
this.superHeroService.createHero(hero).subscribe((heroes: SuperHero[]) => this.heroesUpdated.emit(heroes));
}
}
Update the Super Hero Table
- SuperHero.UI/src/app/app.component.ts
export class AppComponent {
...
updateHeroList(heroes: SuperHero[]){
this.heroes = heroes;
}
...
- SuperHero.UI/src/app/app.component.html
...
<app-edit-hero [hero]="heroToEdit" (heroesUpdated)="updateHeroList($event)"></app-edit-hero>
UI
Read

Create


Update

Delete
