In this tutorial, we’ll discuss the process of building a comprehensive login page using Angular 16 and .NET Core 7. Our approach will involve following a step-by-step methodology within the context of clean architecture.
Pre-requisite
- Install .NET SDK 7
- VS Code or Visual Studio
- Angular 16
Creating WebAPI using ASP.Net Core
Dotnet new – Create a new project based on the specified template
.NET CLI
dotnet new webapi -n Login_Out_DotNet_AngularInstall the Packages
- Microsoft.EntityFrameworkCore
- Microsoft.EntityFrameworkCore.Tools
- Microsoft.EntityFrameworkCore.Sqlite
- Microsoft.AspNetCore.Identity
Project folder structure
Create Core Folder
Create a model in the Entities folder inside Core Folder
Path:/Core/Entities/Users.cs
using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Identity; namespace Login_Out_DotNet_Angular.Core.Entities { public class Users : IdentityUser { public string DisplayName { get; set; } public Address Address { get; set; } } }
Path:/Core/Entities/Address.cs
using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; using System.Threading.Tasks; namespace Login_Out_DotNet_Angular.Core.Entities { public class Address { public int Id { get; set; } public string FirstName { get; set; } public string LastName { get; set; } public string Street { get; set; } public string City { get; set; } public string State { get; set; } public string ZipCode { get; set; } [Required] public string UserId { get; set; } public Users User { get; set; } } }
Create Infrastructure Folder
Create a DbContext class that communicates to the database.
Path:/ Infrastructure/Data/AppIdentityDbContext.cs
using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Login_Out_DotNet_Angular.Core.Entities; using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Identity.EntityFrameworkCore; using Microsoft.EntityFrameworkCore; namespace Login_Out_DotNet_Angular.Infrastructure.Data { public class AppIdentityDbContext : IdentityDbContext<Users> { public AppIdentityDbContext(DbContextOptions<AppIdentityDbContext> options) : base(options) { } protected override void OnModelCreating(ModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); } }
Configure AppSettings.json
{ "Logging": { "LogLevel": { "Default": "Information", "Microsoft.AspNetCore": "Warning" } }, "ConnectionStrings": { "Connection" :"Data Source = Identity.db" }, "AllowedHosts": "*" }
Create the Extension folder
Path:/ Extensions/ApplicationServiceExtension.cs
using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Login_Out_DotNet_Angular.Core.Entities; using Login_Out_DotNet_Angular.Infrastructure.Data; using Microsoft.AspNetCore.Identity; using Microsoft.EntityFrameworkCore; namespace Login_Out_DotNet_Angular.Extensions { public static class ApplicationServiceExtension { public static IServiceCollection AddIdentityService(this IServiceCollection services, IConfiguration config) { services.AddEndpointsApiExplorer(); services.AddSwaggerGen(); services.AddDbContext<AppIdentityDbContext>(option => { option.UseSqlite(config.GetConnectionString("Connection")); }); services.AddIdentity<Users, IdentityRole>(opt => { // add identity option opt.Password.RequiredLength = 8; opt.Password.RequireNonAlphanumeric = false; opt.Password.RequireDigit = false; opt.Password.RequireUppercase = false; }) .AddEntityFrameworkStores<AppIdentityDbContext>() .AddUserManager<UserManager<Users>>() .AddSignInManager<SignInManager<Users>>() .AddDefaultTokenProviders(); services.AddCors(Opt => { Opt.AddDefaultPolicy(opt=> { opt.AllowAnyHeader().AllowAnyMethod().AllowAnyOrigin(); }); // Opt.AddDefaultPolicy("CorsPolicy", policy => // { // policy.AllowAnyHeader().AllowAnyMethod().WithOrigins("http://localhost:4200/"); // }); }); return services; } } }
Configure the Program.cs class
Path:/ Program.cs
using Login_Out_DotNet_Angular.Core.Entities; using Login_Out_DotNet_Angular.Extensions; using Login_Out_DotNet_Angular.Infrastructure.Data; using Microsoft.AspNetCore.Identity; using Microsoft.EntityFrameworkCore; var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.AddControllers(); // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle builder.Services.AddIdentityService(builder.Configuration); var app = builder.Build(); // Configure the HTTP request pipeline. if (app.Environment.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(); } app.UseHttpsRedirection(); app.UseAuthorization(); app.MapControllers(); app.UseCors(); app.Run();
Now run Migrations
dotnet ef migrations add initialcreate -o Migrations dotnet ef database update
Create folder DTO
Create folder DTO and inside the folder create classes LoginDto, UserDto, RegisterDto.
path: / DTO/LoginDto.cs
using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; namespace Login_Out_DotNet_Angular.DTO { public class LoginDto { public string Email { get; set; } public string Password { get; set; } } }
Path:/ DTO/UserDto.cs
using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; namespace Login_Out_DotNet_Angular.DTO { public class UserDto { public string Email { get; set; } public string DisplayName { get; set; } } }
path:/ DTO/ RegisterDto.cs
using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; namespace Login_Out_DotNet_Angular.DTO { public class RegisterDto { public string Email { get; set; } public string Password { get; set; } public string DisplayName { get; set; } } }
Create Controller
The Now create Account Controller in the Controller folder.
Path:/Controllers/AccountController.cs
using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Login_Out_DotNet_Angular.Core.Entities; using Login_Out_DotNet_Angular.DTO; using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; namespace Login_Out_DotNet_Angular.Controllers { [Route("api/[controller]")] [ApiController] public class AccountController : ControllerBase { private readonly UserManager<Users> _userManager; private readonly SignInManager<Users> _signInManager; public AccountController(UserManager<Users> userManager, SignInManager<Users> signInManager) { _userManager = userManager; _signInManager = signInManager; } [HttpPost("login")] public async Task<ActionResult<UserDto>> Login(LoginDto loginDto) { var user = await _userManager.FindByEmailAsync(loginDto.Email); if (user == null) return Ok("User Doest Not Exist"); var result = await _signInManager.CheckPasswordSignInAsync(user, loginDto.Password, false); if (!result.Succeeded) return BadRequest("Please check Credential try again...!"); return new UserDto { Email = user.Email, DisplayName = user.DisplayName }; } [HttpPost("register")] public async Task<ActionResult<UserDto>> register(RegisterDto registerDto) { var user = new Users { DisplayName = registerDto.DisplayName, Email = registerDto.Email, UserName = registerDto.Email }; var result = await _userManager.CreateAsync(user, registerDto.Password); if (!result.Succeeded) return BadRequest("Please check...!"); return new UserDto { DisplayName = registerDto.DisplayName, Email = registerDto.Email }; } } }
Now Test API using Postman
Creating a User Interface using Angular 16
Now Create Client Side User Interface using Angular 16
To create an Angular project first we need to install Node.js and angular
Download the Node.js installer here
Install angular 16
npm install -g @angular/cli
Create a Project
Ng new client cd client ng serve
install the bootstrap
ng add ngx-bootstrap
then add then bootstrap in angular.json file
"styles": [ "./node_modules/ngx-bootstrap/datepicker/bs-datepicker.css", "./node_modules/bootstrap/dist/css/bootstrap.min.css", "src/styles.css" ],
Create components using CLI command
ng g c home/home --flat --skip-tests ng g c account/login/login --flat --skip-tests Creating Ng routing module ng g m account/account-routing --flat create Ng module ng g m account/account --flat Create Ng service ng g s account/account --flat --skip-tests
Now in the app-routing.module update routes
path:/ app/ app-routing.module.ts
import { NgModule } from '@angular/core'; import { RouterModule, Routes } from '@angular/router'; import { HomeComponent } from './home/home.component'; const routes: Routes = [ {path:'', loadChildren: ()=>import('./account/account.module').then(l=>l.AccountModule)}, {path:'home', component:HomeComponent}, {path:'**',redirectTo:'',pathMatch:'full'} ]; @NgModule({ imports: [RouterModule.forRoot(routes)], exports: [RouterModule] }) export class AppRoutingModule { }
In Ng Module import the modules
path:/ app/ app.module.ts
import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { AppRoutingModule } from './app-routing.module'; import { AppComponent } from './app.component'; import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; import { HttpClientModule } from '@angular/common/http'; import { HomeComponent } from './home/home.component'; @NgModule({ declarations: [ AppComponent, HomeComponent, ], imports: [ BrowserModule, AppRoutingModule, BrowserAnimationsModule, HttpClientModule ], providers: [], bootstrap: [AppComponent] }) export class AppModule { }
and in the app-component.html file update router-outlet tag
path:/ app/app-component.html
<router-outlet></router-outlet>
Create a Shared folder
Inside the shared folder create another folder module in that folder create the interface
Path:/ app/shared/module/Users.ts
export interface Users{ displayName : string, Email : string }
Now in the account routing module update the routing
Path:/ app/account/ account-routing.module.ts
import { Component, NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; import { RouterModule, Routes } from '@angular/router'; import { LoginComponent } from './login/login.component'; const routes : Routes=[ {path:'', component:LoginComponent} ] @NgModule({ declarations: [], imports: [ RouterModule.forChild(routes) ], exports:[ RouterModule ] })
in Ng module import the modules AccountRoutingModule, ReactiveFormsModule
path:/ app/account/ account.module.ts
import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; import { AccountRoutingModule } from './account-routing.module'; import { LoginComponent } from './login/login.component'; import { ReactiveFormsModule } from '@angular/forms'; @NgModule({ declarations: [ LoginComponent ], imports: [ CommonModule, AccountRoutingModule, ReactiveFormsModule ] }) export class AccountModule { }
Create services for server communication.
path:/ app/account/ account.service.ts
import { Injectable } from '@angular/core'; import { Router } from '@angular/router'; import { HttpClient } from '@angular/common/http'; import { Users } from '../shared/module/users'; import { map } from 'rxjs'; @Injectable({ providedIn: 'root' }) export class accountService { baseUrl = "https://localhost:7228/api/"; constructor(private http : HttpClient, private route : Router) { } login(values:any){ return this.http.post<Users>(this.baseUrl + 'account/login', values).pipe( map(users => { localStorage.setItem('username',users.displayName); }) ) } logout(){ localStorage.removeItem('username'); this.route.navigateByUrl('/'); } }
Now open the login component then update
Path:/ app/account/login/ login.component.ts
import { Component } from '@angular/core'; import { FormControl, FormGroup, Validators } from '@angular/forms'; import { Router } from '@angular/router'; import { accountService } from '../account.service'; @Component({ selector: 'app-login', templateUrl: './login.component.html', styleUrls: ['./login.component.css'] }) export class LoginComponent { title : string ='Login From'; loginForm = new FormGroup({ email : new FormControl('',Validators.required), password: new FormControl('',Validators.required) }) constructor(private accountService: accountService, private router: Router){} onSubmit(){ this.accountService.login(this.loginForm.value).subscribe({ next:()=> this.router.navigateByUrl('/home'), error:()=> alert("Please check Credential...!") }) } }
Next, open the login.component.html and update
Path:/ app/account/login/ login.component.html
<div class="d-flex justify-content-center mt-5"> <div class="col-3"> <form [formGroup]="loginForm" (ngSubmit)="onSubmit()"> <div class="text-center mb-4"> <h1 class="mb-3"> Login </h1> </div> <div class="form-floating mb-3"> <input type="email" formControlName="email" class="form-control" id="floatingInput" placeholder="Email"> <label for="floatingInput">Email address</label> </div> <div class="form-floating"> <input type="password" formControlName="password" class="form-control" id="floatingPassword" placeholder="Password"> <label for="floatingPassword">Password</label> </div> <div class="d-grid"> <button class="btn btn-lg btn-primary mt-3" type="submit"> Sign in </button> </div> </form> </div> </div>
Then Run Application
More Articles – How to Implement JWT Authentication in Asp.Net Core Web API