Introduction
In the first article, we covered the Admin and Employee (Attendance) modules of the HRM project. Now, in this second article, we’ll continue with the Leave Requests module — enabling employees to apply for leave, and HR/Managers to approve or reject requests. This workflow is critical for any HRMS as it directly impacts payroll, attendance, and employee satisfaction.
Leave Request Model
Define the entity to store leave applications:
csharp
public class LeaveRequest
{
public int Id { get; set; }
public int EmployeeId { get; set; }
public Employee Employee { get; set; }
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
public string Reason { get; set; }
public string Status { get; set; } = "Pending"; // Pending, Approved, Rejected
}
Leave Request Controller
Create an MVC controller to handle leave applications:
csharp
public class LeaveRequestsController : Controller
{
private readonly ApplicationDbContext _context;
public LeaveRequestsController(ApplicationDbContext context) => _context = context;
// List all leave requests
public async Task<IActionResult> Index()
{
var requests = await _context.LeaveRequests
.Include(l => l.Employee)
.ToListAsync();
return View(requests);
}
// Apply for leave
public IActionResult Create()
{
ViewBag.Employees = new SelectList(_context.Employees, "Id", "FullName");
return View();
}
[HttpPost]
public async Task<IActionResult> Create(LeaveRequest request)
{
if (ModelState.IsValid)
{
_context.Add(request);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
return View(request);
}
// Approve leave
public async Task<IActionResult> Approve(int id)
{
var request = await _context.LeaveRequests.FindAsync(id);
if (request == null) return NotFound();
request.Status = "Approved";
_context.Update(request);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
// Reject leave
public async Task<IActionResult> Reject(int id)
{
var request = await _context.LeaveRequests.FindAsync(id);
if (request == null) return NotFound();
request.Status = "Rejected";
_context.Update(request);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
}
Leave Request Views
Index.cshtml
html
@model IEnumerable<LeaveRequest>
<h2>Leave Requests</h2>
<a asp-action="Create" class="btn btn-primary">Apply for Leave</a>
<table class="table">
<tr><th>Employee</th><th>Start</th><th>End</th><th>Reason</th><th>Status</th><th>Actions</th></tr>
@foreach (var l in Model)
{
<tr>
<td>@l.Employee.FullName</td>
<td>@l.StartDate.ToShortDateString()</td>
<td>@l.EndDate.ToShortDateString()</td>
<td>@l.Reason</td>
<td>@l.Status</td>
<td>
@if (l.Status == "Pending")
{
<a asp-action="Approve" asp-route-id="@l.Id">Approve</a> |
<a asp-action="Reject" asp-route-id="@l.Id">Reject</a>
}
</td>
</tr>
}
</table>
Create.cshtml
html
@model LeaveRequest
<h2>Apply for Leave</h2>
<form asp-action="Create">
<div class="form-group">
<label>Employee</label>
<select asp-for="EmployeeId" asp-items="ViewBag.Employees" class="form-control"></select>
</div>
<div class="form-group">
<label>Start Date</label>
<input asp-for="StartDate" type="date" class="form-control" />
</div>
<div class="form-group">
<label>End Date</label>
<input asp-for="EndDate" type="date" class="form-control" />
</div>
<div class="form-group">
<label>Reason</label>
<textarea asp-for="Reason" class="form-control"></textarea>
</div>
<button type="submit" class="btn btn-success">Submit</button>
</form>
📸 Screenshot



Join the conversation! Your thoughts help the community grow.