Introduction
CRUD stands for Create, Read, Update, and Delete, which are the four basic operations commonly performed on application data.
In this tutorial, we will build an Employee Management application using ASP.NET Core, Entity Framework Core, SQL Server, Web API, and ASP.NET Core MVC.
The application is divided into two projects:
Employee Web Application
|
v
ASP.NET Core MVC
|
| HTTP Requests
v
ASP.NET Core Web API
|
v
Entity Framework Core
|
v
SQL Server
The Web API is responsible for database operations, while the MVC application consumes the API and provides the user interface.
The application will support:
Creating employees
Viewing employees
Updating employees
Deleting employees
Validating employee information
Persisting employee data in SQL Server
Technologies Used
The implementation uses the following technologies:
ASP.NET Core Web API
ASP.NET Core MVC
Entity Framework Core
SQL Server
C#
Razor Views
HttpClientDependency Injection
Step 1: Create the Employee Model
Create an Employee class in the API project.
using System.ComponentModel.DataAnnotations;
public class Employee
{
[Key]
public int Id { get; set; }
[Required]
[Display(Name = "Employee Name")]
public string Name { get; set; } = string.Empty;
public string Designation { get; set; } = string.Empty;
[DataType(DataType.MultilineText)]
public string Address { get; set; } = string.Empty;
public DateTime? RecordCreatedOn { get; set; }
}
The properties represent the employee information stored in the database.
Idis the primary key.Namestores the employee's name.Designationstores the employee's job designation.Addressstores the employee's address.RecordCreatedOnstores the record creation date.
The [Required] attribute ensures that the employee name is required.
Step 2: Install Entity Framework Core Packages
Install the required Entity Framework Core packages in the API project.
For the original .NET 6 implementation, the package references are:
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="6.0.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="6.0.1" />
These packages provide the core EF functionality, SQL Server provider, and migration tooling.
For a new application, use package versions compatible with the .NET version targeted by the project rather than copying an old package version unchanged.
Step 3: Create the Data Folder
Create a folder named:
Data
Inside the folder, create:
ApplicationDbContext.cs
The ApplicationDbContext class connects the application model to Entity Framework Core.
using EmployeeCRUD.Models;
using Microsoft.EntityFrameworkCore;
namespace EmployeeCRUD.Data
{
public class ApplicationDbContext : DbContext
{
public ApplicationDbContext(
DbContextOptions<ApplicationDbContext> options)
: base(options)
{
}
public DbSet<Employee> Employees { get; set; }
}
}
The important correction here is that ApplicationDbContext must inherit from DbContext.
The DbSet<Employee> property represents the Employees table managed by Entity Framework Core.
Step 4: Configure the SQL Server Connection
Open appsettings.json and add a connection string.
{
"ConnectionStrings": {
"DefaultConnection": "Server=EnterServerName;Database=EmployeeDatabase;User Id=sa;Password=EnterPassword;TrustServerCertificate=True;"
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}
Replace the placeholder server and authentication values with the appropriate configuration for your development environment.
For production applications, avoid storing database passwords directly in source-controlled configuration files. Use an appropriate secrets-management mechanism.
Step 5: Register Entity Framework Core
Open Program.cs and register ApplicationDbContext.
using EmployeeCRUD.Data;
using Microsoft.EntityFrameworkCore;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDbContext<ApplicationDbContext>(
options =>
options.UseSqlServer(
builder.Configuration
.GetConnectionString("DefaultConnection")));
builder.Services.AddControllers();
var app = builder.Build();
app.MapControllers();
app.Run();
AddDbContext registers the database context with ASP.NET Core's built-in Dependency Injection container.
The connection string is retrieved from appsettings.json.
Step 6: Create the Database Using EF Core Migrations
After configuring the DbContext, create the initial migration.
Using the Package Manager Console:
Add-Migration Initial
Update-Database
Alternatively, the .NET CLI can be used:
dotnet ef migrations add Initial
dotnet ef database update
The migration creates the database schema based on the Employee model.
After the database update, the Employees table will contain columns corresponding to the model properties.
Step 7: Create DTOs for POST and PUT
Instead of using the database entity directly for every API request, create DTOs for create and update operations.
EmployeeCreateDto
This DTO is used when creating an employee.
using System.ComponentModel.DataAnnotations;
public class EmployeeCreateDto
{
[Required]
public string Name { get; set; } = string.Empty;
public string Designation { get; set; } = string.Empty;
public string Address { get; set; } = string.Empty;
}
EmployeeUpdateDto
This DTO is used when updating an employee.
using System.ComponentModel.DataAnnotations;
public class EmployeeUpdateDto
{
[Required]
public string Name { get; set; } = string.Empty;
public string Designation { get; set; } = string.Empty;
public string Address { get; set; } = string.Empty;
}
The DTOs intentionally do not contain Id or RecordCreatedOn.
These values are controlled by the application rather than being supplied by the client.
Step 8: Create the Employee API Controller
Create EmployeeController.cs in the API project.
The original code contained spelling inconsistencies such as EmployeeControler and ApplicaitonDbContext. They should be corrected to EmployeeController and ApplicationDbContext.
using EmployeeCRUD.Data;
using EmployeeCRUD.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
namespace EmployeeCRUD.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class EmployeeController : ControllerBase
{
private readonly ApplicationDbContext _context;
public EmployeeController(ApplicationDbContext context)
{
_context = context;
}
// GET: api/Employee
[HttpGet]
public async Task<ActionResult<IEnumerable<Employee>>> GetAllEmployees()
{
return await _context.Employees.ToListAsync();
}
// GET: api/Employee/5
[HttpGet("{id}")]
public async Task<ActionResult<Employee>> GetEmployeeById(int id)
{
var employee = await _context.Employees.FindAsync(id);
if (employee == null)
{
return NotFound(new
{
message = $"Employee with ID {id} not found."
});
}
return Ok(employee);
}
// POST: api/Employee
[HttpPost]
public async Task<ActionResult<Employee>> CreateEmployee(
EmployeeCreateDto employeeDto)
{
var employee = new Employee
{
Name = employeeDto.Name,
Designation = employeeDto.Designation,
Address = employeeDto.Address,
RecordCreatedOn = DateTime.UtcNow
};
_context.Employees.Add(employee);
await _context.SaveChangesAsync();
return CreatedAtAction(
nameof(GetEmployeeById),
new { id = employee.Id },
employee);
}
// PUT: api/Employee/5
[HttpPut("{id}")]
public async Task<IActionResult> UpdateEmployee(
int id,
EmployeeUpdateDto employeeDto)
{
var existingEmployee =
await _context.Employees.FindAsync(id);
if (existingEmployee == null)
{
return NotFound(new
{
message = $"Employee with ID {id} does not exist."
});
}
existingEmployee.Name = employeeDto.Name;
existingEmployee.Designation = employeeDto.Designation;
existingEmployee.Address = employeeDto.Address;
try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!EmployeeExists(id))
{
return NotFound();
}
throw;
}
return NoContent();
}
// DELETE: api/Employee/5
[HttpDelete("{id}")]
public async Task<IActionResult> DeleteEmployee(int id)
{
var employee =
await _context.Employees.FindAsync(id);
if (employee == null)
{
return NotFound(new
{
message = $"Employee with ID {id} not found."
});
}
_context.Employees.Remove(employee);
await _context.SaveChangesAsync();
return NoContent();
}
private bool EmployeeExists(int id)
{
return _context.Employees.Any(e => e.Id == id);
}
}
}
Step 9: Understand the API Endpoints
The controller exposes the following endpoints:
HTTP Method | Endpoint | Purpose |
|---|---|---|
GET |
| Get all employees |
GET |
| Get one employee |
POST |
| Create an employee |
PUT |
| Update an employee |
DELETE |
| Delete an employee |
GET All Employees
GET /api/Employee
The API queries the database:
await _context.Employees.ToListAsync();
and returns the employee collection.
GET Employee by ID
GET /api/Employee/5
The API searches for the employee with ID 5.
If the employee does not exist, the API returns:
404 Not Found
Create Employee
POST /api/Employee
Example request:
{
"name": "John",
"designation": "Software Developer",
"address": "Kolkata"
}
The API creates the entity and assigns RecordCreatedOn automatically.
A successful creation returns:
201 Created
Update Employee
PUT /api/Employee/5
Example request:
{
"name": "John Smith",
"designation": "Senior Developer",
"address": "Kolkata"
}
The existing entity is loaded first, and only the editable properties are changed.
Id and RecordCreatedOn remain unchanged.
The API returns:
204 No Content
Delete Employee
DELETE /api/Employee/5
The employee is removed from the database.
A successful deletion returns:
204 No Content
Step 10: Test the Web API
Before connecting the MVC application, test the API independently.
Swagger, Postman, or another HTTP client can be used to test the endpoints.
A typical CRUD sequence is:
POST
|
v
Create Employee
|
v
GET
|
v
Verify Employee
|
v
PUT
|
v
Update Employee
|
v
DELETE
|
v
Remove Employee
Testing the API separately makes it easier to determine whether a problem belongs to the API or the MVC application.
Step 11: Connect the MVC Web Project
Now create or open the ASP.NET Core MVC project that will consume the Web API.
The architecture is:
+-----------------------+
| ASP.NET Core MVC |
| Employee Web Project |
+-----------+-----------+
|
| HttpClient
v
+-----------------------+
| ASP.NET Core Web API |
+-----------+-----------+
|
| EF Core
v
+-----------------------+
| SQL Server |
+-----------------------+
The MVC application does not directly access the employee database. It communicates with the Web API through HTTP.

Join the conversation! Your thoughts help the community grow.