Output of CRUD Operation |
CREATING THE PROJECT :
Step 1:
In VS 2019, Select the ASP.NET Core Web API and click NEXT.
Give your project a meaningful name and then click NEXT.
Uncheck Configure for HTTPS and then CREATE your WEB API project.
- Change the Startup.cs code to add services for DB, CORS and MVC etc.
using EmployeeWebAPI.Domain.Repositories;
using EmployeeWebAPI.Domain.Services;
using EmployeeWebAPI.Persistence.Contexts;
using EmployeeWebAPI.Persistence.Repositories;
using EmployeeWebAPI.Services;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
namespace EmployeeWebAPI
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_3_0);
services.AddDbContext<AppDbContext>(item => item.UseSqlServer(Configuration.GetConnectionString("DatabaseContext")));
services.AddScoped<IEmployeeRepository,EmployeeRepository>();
services.AddScoped<IUnitOfWork, UnitOfWork>();
services.AddScoped<IEmployeeService, EmployeeService>();
services.AddAutoMapper(typeof(Startup));
services.AddCors(options =>
{
options.AddDefaultPolicy(
builder =>
{
builder.WithOrigins("http://localhost:4200")
.AllowAnyHeader()
.AllowAnyMethod();
});
});
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseCors(builder =>
{
builder
.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader();
});
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
}
2. Add the connection String of your database (don't create the table we will use code first approach and it will create a database table for us)
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"ConnectionStrings": {
"DatabaseContext": "Data Source=.;Initial Catalog=SpurSol;Integrated Security=True"
},
"AllowedHosts": "*"
}
3. Alter the Program.cs as follows,
using EmployeeWebAPI.Persistence.Contexts;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
namespace EmployeeWebAPI
{
public class Program
{
public static void Main(string[] args)
{
var host = BuildWebHost(args);
using (var scope = host.Services.CreateScope())
using (var context = scope.ServiceProvider.GetService<AppDbContext>())
{
context.Database.EnsureCreated();
}
host.Run();
}
public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args).UseStartup<Startup>().Build();
}
}
4. Creating the Domain Model named Employee.cs. Create a folder Domain, add a sub-folder Models in Domain folder then create a class employee.
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace EmployeeWebAPI.Domain.Models
{
public class Employee
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[Key, Column(Order = 0)]
public int id { get; set; }
public string name { get; set; }
public string email { get; set; }
public string phone { get; set; }
}
}
5. Create the Employee Controller in the controller folder
using AutoMapper;
using EmployeeWebAPI.Domain.Models;
using EmployeeWebAPI.Domain.Services;
using EmployeeWebAPI.Extensions;
using EmployeeWebAPI.Resources;
using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace EmployeeWebAPI.Controllers
{
[Route("/api/[controller]")]
public class EmployeeController : Controller
{
private readonly IEmployeeService _employeeService;
private readonly IMapper _mapper;
public EmployeeController(IEmployeeService employeeService, IMapper mapper)
{
_employeeService = employeeService;
_mapper = mapper;
}
[HttpGet]
public async Task<IEnumerable<EmployeeResource>> GetAllAsync()
{
var employee= await _employeeService.ListAsync();
var resources = _mapper.Map<IEnumerable<Employee>, IEnumerable<EmployeeResource>>(employee);
return resources;
}
[HttpPost]
public async Task<IActionResult> PostAsync([FromBody] SaveEmployeeResource resource)
{
if (!ModelState.IsValid)
return BadRequest(ModelState.GetErrorMessages());
var employee = _mapper.Map<SaveEmployeeResource, Employee>(resource);
var result = await _employeeService.SaveAsync(employee);
if (!result.Success)
return BadRequest(result.Message);
var employeeResource = _mapper.Map<Employee, EmployeeResource>(result.employee);
return Ok(employeeResource);
}
[HttpPut("{id}")]
[Route("/id")]
public async Task<IActionResult> PutAsync(int id, [FromBody] SaveEmployeeResource resource)
{
if (!ModelState.IsValid)
return BadRequest(ModelState.GetErrorMessages());
var employee = _mapper.Map<SaveEmployeeResource, Employee>(resource);
var result = await _employeeService.UpdateAsync(id, employee);
if (!result.Success)
return BadRequest(result.Message);
var employeeResource = _mapper.Map<Employee, EmployeeResource>(result.employee);
return Ok(employeeResource);
}
[HttpDelete("{id}")]
public async Task<IActionResult> DeleteAsync(int id)
{
var result = await _employeeService.DeleteAsync(id);
if (!result.Success)
return BadRequest(result.Message);
var employeeResource = _mapper.Map<Employee, EmployeeResource>(result.employee);
return Ok(employeeResource);
}
}
}
Install Nuget package for Auto Mapping, (Right click on the project name in solution explorer then select manage NuGet packages then select this package),
NuGet Package |
All Nuget Packages,
All NuGet Packages
6. Create a folder mapping and create class ModelToResourceProfile.cs. Must inherit it with Profile Class and then alter the code as follows,
using AutoMapper;
using EmployeeWebAPI.Domain.Models;
using EmployeeWebAPI.Resources;
namespace EmployeeWebAPI.Mapping
{
public class ModelToResourceProfile:Profile
{
public ModelToResourceProfile()
{
CreateMap<Employee, EmployeeResource>();
}
}
}
7. Create another class ResourceToModelProfile.cs in the same folder and alter code as follows,
using AutoMapper;
using EmployeeWebAPI.Domain.Models;
using EmployeeWebAPI.Resources;
namespace EmployeeWebAPI.Mapping
{
public class ResourceToModelProfile:Profile
{
public ResourceToModelProfile()
{
CreateMap<SaveEmployeeResource, Employee>();
}
}
}
8. Create a new folder Services within the Domain folder. In the Services folder, add an interface IEmployeeService.cs and alter the code as follows,
using EmployeeWebAPI.Domain.Models;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace EmployeeWebAPI.Domain.Services
{
public interface IEmployeeService
{
Task<IEnumerable<Employee>> ListAsync();
Task<EmployeeResponse> SaveAsync(Employee employee);
Task<EmployeeResponse> UpdateAsync(int id,Employee employee);
Task<EmployeeResponse> DeleteAsync(int id);
}
}
9. Create another class Employee Response in the Services folder.
using EmployeeWebAPI.Domain.Models;
using EmployeeWebAPI.Domain.Services.Communication;
namespace EmployeeWebAPI.Domain.Services
{
public class EmployeeResponse : BaseResponse
{
public Employee employee { get; private set; }
private EmployeeResponse(bool success, string message, Employee _employee) : base(success, message)
{
employee = _employee;
}
public EmployeeResponse(Employee employee) : this(true, string.Empty, employee)
{ }
public EmployeeResponse(string message) : this(false, message, null)
{ }
}
}
10. Create a new folder Services in the root folder and add a class EmployeeService.cs
using EmployeeWebAPI.Domain.Models;
using EmployeeWebAPI.Domain.Repositories;
using EmployeeWebAPI.Domain.Services;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace EmployeeWebAPI.Services
{
public class EmployeeService:IEmployeeService
{
private readonly IEmployeeRepository _employeeRepository;
private readonly IUnitOfWork _unitOfWork;
public EmployeeService(IEmployeeRepository employeeRepository, IUnitOfWork unitOfWork)
{
this._employeeRepository = employeeRepository;
_unitOfWork = unitOfWork;
}
public async Task<IEnumerable<Employee>> ListAsync()
{
return await _employeeRepository.ListAsync();
}
public async Task<EmployeeResponse> SaveAsync(Employee employee)
{
try
{
await _employeeRepository.AddAsync(employee);
await _unitOfWork.CompleteAsync();
return new EmployeeResponse(employee);
}
catch (Exception ex)
{
return new EmployeeResponse($"An error occurred when saving the employee: {ex.Message}");
}
}
public async Task<EmployeeResponse> UpdateAsync(int id, Employee employee)
{
var existingEmployee = await _employeeRepository.FindByIdAsync(id);
if (existingEmployee == null)
return new EmployeeResponse("Employee not found.");
existingEmployee.name = employee.name;
existingEmployee.email = employee.email;
existingEmployee.phone = employee.phone;
try
{
_employeeRepository.Update(id,existingEmployee);
await _unitOfWork.CompleteAsync();
return new EmployeeResponse(existingEmployee);
}
catch (Exception ex)
{
return new EmployeeResponse($"An error occurred when updating the employee: {ex.Message}");
}
}
public async Task<EmployeeResponse> DeleteAsync(int id)
{
var existingEmployee = await _employeeRepository.FindByIdAsync(id);
if (existingEmployee == null)
return new EmployeeResponse("Employee not found.");
try
{
_employeeRepository.Remove(existingEmployee);
await _unitOfWork.CompleteAsync();
return new EmployeeResponse(existingEmployee);
}
catch (Exception ex)
{
return new EmployeeResponse($"An error occurred when deleting the employee: {ex.Message}");
}
}
}
}
11. Create a new folder Repositories in the Domain folder and add interfaces IEmployeeRepository.cs and IUnitOfWork.cs
IEmployeeRepository.cs
using EmployeeWebAPI.Domain.Models;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace EmployeeWebAPI.Domain.Repositories
{
public interface IEmployeeRepository
{
Task<IEnumerable<Employee>> ListAsync();
Task AddAsync(Employee employee);
Task<Employee> FindByIdAsync(int id);
void Update(int id,Employee employee);
void Remove(Employee employee);
}
}
IUnitOfWork.cs
using System.Threading.Tasks;
namespace EmployeeWebAPI.Domain.Repositories
{
public interface IUnitOfWork
{
Task CompleteAsync();
}
}
12. Within the Services folder, add a new folder Communication and add class BaseResponse.cs
namespace EmployeeWebAPI.Domain.Services.Communication
{
public class BaseResponse
{
public bool Success { get; protected set; }
public string Message { get; protected set; }
public BaseResponse(bool success, string message)
{
Success = success;
Message = message;
}
}
}
13. Add a new folder Extensions in the root folder of project and add class ModelStateExtensions.cs
using Microsoft.AspNetCore.Mvc.ModelBinding;
using System.Collections.Generic;
using System.Linq;
namespace EmployeeWebAPI.Extensions
{
public static class ModelStateExtensions
{
public static List<string> GetErrorMessages(this ModelStateDictionary dictionary)
{
return dictionary.SelectMany(m => m.Value.Errors).Select(m => m.ErrorMessage).ToList();
}
}
}
14. Add a new folder Persistence in the root folder of project and add sub-folder Contexts. In the Contexts folder create a class AppDbContext.cs and alter the code as follows,
using EmployeeWebAPI.Domain.Models;
using Microsoft.EntityFrameworkCore;
namespace EmployeeWebAPI.Persistence.Contexts
{
public class AppDbContext:DbContext
{
public DbSet<Employee> employee { get; set; }
public AppDbContext(DbContextOptions<AppDbContext> options) : base(options)
{
}
}
}
15. Within the Persistence folder, add a new folder Repositories and add 3 classes in Repositories folder
BaseRepository.cs , EmployeeRepository.cs and UnitOfWork.cs
BaseRepository.cs
using EmployeeWebAPI.Persistence.Contexts;
namespace EmployeeWebAPI.Persistence.Repositories
{
public class BaseRepository
{
protected readonly AppDbContext _context;
public BaseRepository(AppDbContext context)
{
_context = context;
}
}
}
EmployeeRepository.cs
using EmployeeWebAPI.Domain.Models;
using EmployeeWebAPI.Domain.Repositories;
using EmployeeWebAPI.Persistence.Contexts;
using Microsoft.EntityFrameworkCore;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace EmployeeWebAPI.Persistence.Repositories
{
public class EmployeeRepository : BaseRepository, IEmployeeRepository
{
public EmployeeRepository(AppDbContext context) : base(context)
{
}
public async Task<IEnumerable<Employee>> ListAsync()
{
return await _context.employee.ToListAsync();
}
public async Task AddAsync(Employee employee)
{
await _context.employee.AddAsync(employee);
}
public async Task<Employee> FindByIdAsync(int id)
{
return await _context.employee.FindAsync(id);
}
public void Update(int id,Employee employee)
{
_context.employee.Update(employee);
}
public void Remove(Employee employee)
{
_context.employee.Remove(employee);
}
}
}
UnitOfWork.cs
using EmployeeWebAPI.Domain.Repositories;
using EmployeeWebAPI.Persistence.Contexts;
using System.Threading.Tasks;
namespace EmployeeWebAPI.Persistence.Repositories
{
public class UnitOfWork : IUnitOfWork
{
private readonly AppDbContext _context;
public UnitOfWork(AppDbContext context)
{
_context = context;
}
public async Task CompleteAsync()
{
await _context.SaveChangesAsync();
}
}
}
16. Add a new folder Resources in the root folder and add classes EmployeeResource.cs and SaveEmployeeResource.cs
EmployeeResource.cs
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace EmployeeWebAPI.Resources
{
public class EmployeeResource
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[Key, Column(Order = 0)]
public int id { get; set; }
public string name { get; set; }
public string email { get; set; }
public string phone { get; set; }
}
}
SaveEmployeeResource.cs
using System.ComponentModel.DataAnnotations;
namespace EmployeeWebAPI.Resources
{
public class SaveEmployeeResource
{
public int id { get; set; }
public string name { get; set; }
public string email { get; set; }
public string phone { get; set; }
}
}
Now you have done with crud operation of core web api. Run the application so it can generate a database table for you.
Database table demo |
Then Check the API's in postman.
GET:
Get Postman |
POST:
PUT :
1. Create a component employee in the project folder by using the command :
ng g c employee
2. Alter the employee.component.html file as follows,
<div class=center>
<div class="container">
<mat-card>
<mat-toolbar color="accent">
<div text-align="center" style="color:black;text-align: right;">
CRUD operation in Angular 9 using core Web API
</div>
</mat-toolbar>
<br><br>
<mat-card-content>
<form [formGroup]="employeeForm" (ngSubmit)="onFormSubmit()">
<table>
<tr>
<td class="tbl1">
<mat-form-field class="demo-full-width">
<input formControlName="name" matTooltip="Enter Employee Name" matInput placeholder="Employee Name">
</mat-form-field>
<mat-error>
<span *ngIf="!employeeForm.get('name').value && employeeForm.get('name').touched"></span>
</mat-error>
</td>
<td class="tbl1">
<mat-form-field class="demo-full-width">
<input formControlName="email" matTooltip="Enter Employee Email" matInput
placeholder="Employee Email">
</mat-form-field>
<mat-error>
<span *ngIf="!employeeForm.get('email').value && employeeForm.get('email').touched"></span>
</mat-error>
</td>
<td class="tbl1">
<mat-form-field class="demo-full-width">
<input formControlName="phone" matTooltip="Enter Employee Contact" matInput
placeholder="Employee Contact">
</mat-form-field>
<mat-error>
<span *ngIf="!employeeForm.get('phone').value && employeeForm.get('phone').touched"></span>
</mat-error>
</td>
</tr>
<tr>
<td></td>
<td class="content-center">
<button type="submit" mat-raised-button color="accent" matTooltip="Click Submit Button">Submit</button>
<button type="reset" mat-raised-button color="accent" matTooltip="Click Reset Button"
(click)="resetForm()">Reset</button>
</td>
<td>
<p *ngIf="dataSaved" style="color:rgb(0, 128, 0);font-size:20px;font-weight:bold" Class="success"
align="left">
{{massage}}
</p>
</td>
</tr>
</table>
<br><br>
<table class="table">
<tr ngclass="btn-primary">
<th class="tbl2">Employee ID</th>
<th class="tbl2">Employee Name</th>
<th class="tbl2">Employee Email</th>
<th class="tbl2">Employee Contact</th>
<th class="tbl2">Edit</th>
<th class="tbl2">Delete</th>
</tr>
<tr *ngFor="let employee of employee | async">
<td class="tbl2">{{employee.id}}</td>
<td class="tbl2">{{employee.name }}</td>
<td class="tbl2">{{employee.email}}</td>
<td class="tbl2">{{employee.phone}}</td>
<td class="tbl2">
<button type="button" class="btn btn-info" matTooltip="Click Edit Button"
(click)="loadEmployeeToEdit(employee)">Edit</button>
</td>
<td class="tbl2">
<button type="button" class="btn btn-danger" matTooltip="Click Delete Button"
(click)="deleteEmployee(employee.id)">Delete</button>
</tr>
</table>
</form>
</mat-card-content>
</mat-card>
</div>
</div>
3. Alter the employee.component.ts file as given,
import { Component, OnInit } from '@angular/core';
import { FormBuilder, Validators } from '@angular/forms';
import { Observable } from 'rxjs';
import { EmployeeService } from '../employee.service';
import { Employee } from '../employee';
@Component({
selector: 'app-employee',
templateUrl: './employee.component.html',
styleUrls: ['./employee.component.css']
})
export class EmployeeComponent implements OnInit {
dataSaved = false;
employeeForm: any;
employee!: Observable<Employee[]>;
employeeIdUpdate: any = null;
massage = '';
massage2!: null;
constructor(private formbulider: FormBuilder, private employeeService: EmployeeService) { }
ngOnInit() {
this.employeeForm = this.formbulider.group({
name: ['', [Validators.required]],
email: ['', [Validators.required]],
phone: ['', [Validators.required]],
});
this.loadAllEmployees();
}
loadAllEmployees() {
this.employee = this.employeeService.getAllEmployee();
}
onFormSubmit() {
this.dataSaved = false;
const employee = this.employeeForm.value;
this.CreateEmployee(employee);
this.employeeForm.reset();
}
loadEmployeeToEdit(employee: Employee) {
this.employeeService.updateEmployee(employee).subscribe(employee => {
this.employeeIdUpdate = employee.id;
this.massage2 = null;
this.dataSaved = false;
this.employeeForm.controls['name'].setValue(employee.name);
this.employeeForm.controls['email'].setValue(employee.email);
this.employeeForm.controls['phone'].setValue(employee.phone);
});
}
CreateEmployee(employee: Employee) {
if (this.employeeIdUpdate == null) {
this.employeeService.addEmployee(employee).subscribe(() => {
this.dataSaved = true;
this.massage = 'Record saved Successfully';
this.loadAllEmployees();
this.employeeIdUpdate = null;
this.employeeForm.reset();
}
);
} else {
employee.id = this.employeeIdUpdate;
this.employeeService.updateEmployee(employee).subscribe(() => {
this.dataSaved = true;
this.massage = 'Record Updated Successfully';
this.loadAllEmployees();
this.employeeIdUpdate = null;
this.employeeForm.reset();
});
}
}
deleteEmployee(employeeId: string) {
if (confirm("Are you sure you want to delete this ?")) {
this.employeeService.deleteEmployee(employeeId).subscribe(() => {
this.dataSaved = true;
this.massage = 'Record Deleted Succefully';
this.loadAllEmployees();
this.employeeIdUpdate = null;
this.employeeForm.reset();
});
}
}
resetForm() {
this.employeeForm.reset();
this.massage2 = null;
this.dataSaved = false;
}
}
4. Import the following modules in app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { EmployeeService } from './employee.service';
import { FormsModule ,ReactiveFormsModule} from '@angular/forms';
import { HttpClientModule} from '@angular/common/http';
import { MatButtonModule} from '@angular/material/button';
import { MatMenuModule} from '@angular/material/menu';
import { MatDatepickerModule} from '@angular/material/datepicker';
import { MatCardModule} from '@angular/material/card';
import { MatIconModule} from '@angular/material/icon';
import {MatRadioModule} from '@angular/material/radio';
import {MatInputModule} from '@angular/material/input';
import {MatToolbarModule} from '@angular/material/toolbar';
import {MatTooltipModule} from '@angular/material/tooltip';
import {BrowserAnimationsModule} from '@angular/platform-browser/animations';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { EmployeeComponent } from './employee/employee.component';
@NgModule({
declarations: [
AppComponent,
EmployeeComponent
],
imports: [
BrowserModule,
FormsModule,
ReactiveFormsModule,
HttpClientModule,
BrowserAnimationsModule,
MatButtonModule,
MatMenuModule,
MatDatepickerModule,
MatIconModule,
MatRadioModule,
MatCardModule,
MatInputModule,
MatTooltipModule,
MatToolbarModule,
AppRoutingModule
],
providers: [HttpClientModule, EmployeeService,MatDatepickerModule],
bootstrap: [AppComponent]
})
export class AppModule { }
5. Create a new service employee.service.ts for creating services for crud operation. Use the following command to create the service
ng g s employee
6. Use the tag in app.component.html for employee,
<app-employee></app-employee>
7. Alter the employee.service.ts to call the APIs from the backend.
import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http'
import { Observable } from 'rxjs'
import { Employee } from './employee'
@Injectable({
providedIn: 'root'
})
export class EmployeeService {
getEmployeeById(employeeId: string): Observable<Employee> {
return this.http.get<Employee>(this.url + employeeId);
}
employee: Employee | undefined;
url = 'http://localhost:53885/api/employee';
constructor(private http: HttpClient) { }
getAllEmployee(): Observable<Employee[]> {
return this.http.get<Employee[]>(this.url);
}
addEmployee(employee: Employee): Observable<Employee> {
const httpOptions = { headers: new HttpHeaders({ 'Content-Type': 'application/json' }) };
return this.http.post<Employee>(this.url, employee);
}
updateEmployee(employee: Employee): Observable<Employee> {
const httpOptions = { headers: new HttpHeaders({ 'Content-Type': 'application/json' }) };
return this.http.put<Employee>(`${this.url}/${employee.id}`, employee);
}
deleteEmployee(id: string): Observable<number> {
const HttpOptions = { headers: new HttpHeaders({ 'Content-Type': 'application/json' }) }
return this.http.delete<number>(`${this.url}/${id}`, HttpOptions);
}
}
Make sure your url matches the same path of your APIs. i.e.
8. Create an employee.ts class for Employee
export class Employee {
id!: string;
name!: string;
email!: string;
phone!: string;
}
9. Add bootstrap and CSS to make it attractive.
employee.component.css :
.center {
display: flex;
justify-content: center;
}
use command npm i bootstrap for installing bootstrap
style.css:
@import '@angular/material/prebuilt-themes/deeppurple-amber.css';
OUTPUT :
CREATE & READ Operations :
Clicking the edit button it will autofills the record to edit
0 Comments