Back to: ASP.NET Core Tutorials For Beginners and Professionals
Employee Portal Application Development using ASP.NET Core MVC
We will develop one application to manage employee data in an organized and efficient manner, i.e., an Employee Portal Application using ASP.NET Core MVC. This application will provide features such as adding new employees, viewing existing employee details, updating employee information, and removing employees from the system. We will design the application with user-friendly interfaces that allow easy navigation and interaction, ensuring users can manage employee records effectively. Let us first discuss the different pages that we are going to develop as part of this application:
List Page:
The List Page serves as the main dashboard for the application, displaying a comprehensive list of all employees. It includes features such as filtering and pagination, enabling users to find and manage specific employee records easily. The List page will look like the one below:
Features:
- It displays a table with employee information such as Name, Email, Position, Department, Gender, and Employee Type.
- Allows users to filter employees by department, employee type, and name.
- Includes pagination controls to navigate through multiple pages of employee records.
- Users can view details and update and delete employees from this page.
Create Page:
The Create Page allows users to add a new employee to the system. This page provides a form where users can input all necessary details about a new employee. The Create Employee page will look like the one below:
Features:
- Presents a form for entering employee details such as Full Name, Email, Position, Department, Hire Date, Date of Birth, Employee Type, Gender, and Salary.
- Includes validation to ensure all required fields are filled out correctly before submission.
- It also includes the Back button in case the user doesn’t want to create a new employee and wants to return to the List page.
- After submitting the form, the new employee is added to the system, and the user is redirected to the Success Page.
Success Page:
The Success Page confirms that a new employee has been successfully created and added to the system. It provides a summary of the newly added employee’s information. The Success page will look like the one below:
Features:
- Displays a summary of the employee’s details that were entered on the Create Page.
- Offers options to either create another employee or return to the Employee List page.
- This page reassures users that their actions were successful and provides easy navigation for further actions.
Details Page:
The Details Page provides a detailed view of a specific employee’s information. It allows users to review all stored details about an employee. The Details page will look like the one below:
Features:
- Displays all information about the selected employee, such as Full Name, Email, Position, Department, Hire Date, Date of Birth, Employee Type, Gender, and Salary.
- Allows users to navigate to the List Page or update or delete the employee’s information.
- This page is essential for users who need to verify or review detailed employee information before making decisions.
Update Page:
The Update Page allows users to modify the details of an existing employee. It provides a form pre-filled with the current information, which users can edit as needed. The Update page will look like the one below:
Features:
- Presents a form similar to the Create Page but pre-filled with the employee’s existing data.
- Users can update any of the employee’s details, including Full Name, Email, Position, Department, Hire Date, Date of Birth, Employee Type, Gender, and Salary.
- After submitting the form, the updated information is saved, and the user is redirected back to the List Page to confirm the changes.
Delete Page:
The Delete Page allows users to remove an employee from the system. It ensures that users make an informed decision by asking for confirmation before the deletion is executed. The Delete page will look like the one below:
Features:
- Presents a confirmation prompt with details of the employee to be deleted, ensuring users know the action they are about to take.
- Users can confirm the deletion, which permanently removes the employee from the system, or cancel the action to return to the List Page.
- This page is essential for maintaining data integrity and preventing accidental deletions.
Creating ASP.NET Core MVC Project:
Let’s implement this application step by step using ASP.NET Core MVC. First, create a new ASP.NET Core Project using the Model View Controller template and name it EmployeePortal.
Employee Enums:
First, create a class file named EmployeeEnums.cs within the Models folder, and then copy and paste the following code. The following enums define the possible types of employment and departments in the EmployeePortal application. The EmployeeType enum provides a standardized set of employment types (Permanent, Temporary, Contract, Intern). The Department enum offers a predefined set of departments (IT, HR, Sales, Admin).
namespace EmployeePortal.Models { public enum EmployeeType { Permanent, Temporary, Contract, Intern } public enum Department { IT, HR, Sales, Admin } }
Employee Model:
Next, create a class file named Employee.cs within the Models folder and copy and paste the following code. The Employee class represents an employee within the application, encapsulating all relevant data. It includes Id, FullName, Email, Position, Department, HireDate, DateOfBirth, Type, Gender, and Salary. Data annotations are used for validation and display purposes, ensuring that required fields are filled out and follow specific formatting rules. This model serves as the data structure for CRUD operations related to employees in the application.
using System.ComponentModel.DataAnnotations; namespace EmployeePortal.Models { public class Employee { public int Id { get; set; } [Required(ErrorMessage = "Full Name is required")] [StringLength(100, ErrorMessage = "Full Name cannot be longer than 100 characters")] [Display(Name = "Full Name")] public string FullName { get; set; } [Required(ErrorMessage = "Email is required")] [EmailAddress(ErrorMessage = "Invalid Email Address")] [Display(Name = "Email Address")] public string Email { get; set; } [Required(ErrorMessage = "Position is required")] [StringLength(50, ErrorMessage = "Position cannot be longer than 50 characters")] public string Position { get; set; } [Required(ErrorMessage = "Department is required")] public Department? Department { get; set; } [Required(ErrorMessage = "Hire Date is required")] [Display(Name = "Hire Date")] [DataType(DataType.Date, ErrorMessage = "Invalid date format")] public DateTime? HireDate { get; set; } [Required(ErrorMessage = "Date of Birth is required")] [Display(Name = "Date of Birth")] [DataType(DataType.Date, ErrorMessage = "Invalid date format")] public DateTime? DateOfBirth { get; set; } [Required(ErrorMessage = "Employee Type is required")] [Display(Name = "Employee Type")] public EmployeeType? Type { get; set; } [Required(ErrorMessage = "Gender is required")] [StringLength(6, ErrorMessage = "Gender should be Male, Female, or Other")] public string? Gender { get; set; } [Required(ErrorMessage = "Salary is required")] [Range(0, double.MaxValue, ErrorMessage = "Salary must be a positive number")] [DataType(DataType.Currency)] public decimal? Salary { get; set; } } }
Employee List View Model:
Next, create a class file named EmployeeListViewModel.cs within the Models folder and copy and paste the following code. The EmployeeListViewModel class is used to pass data from the controller to the view to display a list of employees. It contains a list of Employee objects and additional properties like TotalPages, SearchTerm, SelectedDepartment, SelectedType, SortBy, SortAscending, PageSize, and PageNumber. This class supports pagination and filtering in the employee listing view, enhancing user interaction and data presentation.
namespace EmployeePortal.Models { public class EmployeeListViewModel { public List<Employee> Employees { get; set; } public int TotalPages { get; set; } public string SearchTerm { get; set; } public string SelectedDepartment { get; set; } public string SelectedType { get; set; } public int PageSize { get; set; } public int PageNumber { get; set; } } }
Employee Service:
Next, create a class file named EmployeeService.cs within the Models folder and copy and paste the following code. The EmployeeService class provides a mock data service for managing employee records within the application. It includes methods for retrieving a list of employees with filtering and pagination (GetEmployees), retrieving a single employee by ID (GetEmployeeById), creating a new employee (CreateEmployee), updating an existing employee (UpdateEmployee), and deleting an employee (DeleteEmployee).
namespace EmployeePortal.Models { public class EmployeeService { private static List<Employee> employees = new List<Employee> { new Employee { Id = 1, FullName = "John Doe", Email = "john@example.com", Position = "Software Developer", Department = Department.IT, HireDate = DateTime.Now.AddYears(-3), DateOfBirth = DateTime.Now.AddYears(-30), Type = EmployeeType.Permanent, Gender = "Male", Salary = 60000 }, new Employee { Id = 2, FullName = "Jane Smith", Email = "jane@example.com", Position = "HR Manager", Department = Department.HR, HireDate = DateTime.Now.AddYears(-5), DateOfBirth = DateTime.Now.AddYears(-35), Type = EmployeeType.Permanent, Gender = "Female", Salary = 80000 }, new Employee { Id = 3, FullName = "Sam Wilson", Email = "sam@example.com", Position = "Sales Executive", Department = Department.Sales, HireDate = DateTime.Now.AddYears(-2), DateOfBirth = DateTime.Now.AddYears(-28), Type = EmployeeType.Contract, Gender ="Male", Salary = 50000 }, new Employee { Id = 4, FullName = "Anna Taylor", Email = "anna@example.com", Position = "Executive Assistant", Department = Department.Admin, HireDate = DateTime.Now.AddYears(-1), DateOfBirth = DateTime.Now.AddYears(-25), Type = EmployeeType.Temporary, Gender = "Female", Salary = 40000 }, new Employee { Id = 5, FullName = "Tom Brown", Email = "tom@example.com", Position = "Network Engineer", Department = Department.IT, HireDate = DateTime.Now.AddYears(-4), DateOfBirth = DateTime.Now.AddYears(-32), Type = EmployeeType.Permanent, Gender = "Male", Salary = 70000 }, new Employee { Id = 6, FullName = "Emma Davis", Email = "emma@example.com", Position = "HR Specialist", Department = Department.HR, HireDate = DateTime.Now.AddYears(-6), DateOfBirth = DateTime.Now.AddYears(-34), Type = EmployeeType.Permanent, Gender = "Female", Salary = 75000 }, new Employee { Id = 7, FullName = "Luke Miller", Email = "luke@example.com", Position = "Sales Manager", Department = Department.Sales, HireDate = DateTime.Now.AddYears(-3), DateOfBirth = DateTime.Now.AddYears(-31), Type = EmployeeType.Contract, Gender = "Male", Salary = 85000 }, new Employee { Id = 8, FullName = "Olivia Johnson", Email = "olivia@example.com", Position = "Office Manager", Department = Department.Admin, HireDate = DateTime.Now.AddYears(-2), DateOfBirth = DateTime.Now.AddYears(-29), Type = EmployeeType.Permanent, Gender = "Female", Salary = 65000 }, new Employee { Id = 9, FullName = "Mia Moore", Email = "mia@example.com", Position = "System Administrator", Department = Department.IT, HireDate = DateTime.Now.AddYears(-1), DateOfBirth = DateTime.Now.AddYears(-26), Type = EmployeeType.Intern, Gender = "Female", Salary = 30000 }, new Employee { Id = 10, FullName = "Chris Evans", Email = "chris@example.com", Position = "Talent Acquisition Coordinator", Department = Department.HR, HireDate = DateTime.Now.AddYears(-5), DateOfBirth = DateTime.Now.AddYears(-33), Type = EmployeeType.Temporary, Gender = "Other", Salary = 55000 }, new Employee { Id = 11, FullName = "Sophia White", Email = "sophia@example.com", Position = "Sales Executive", Department = Department.Sales, HireDate = DateTime.Now.AddYears(-2), DateOfBirth = DateTime.Now.AddYears(-27), Type = EmployeeType.Permanent, Gender = "Female", Salary = 52000 }, new Employee { Id = 12, FullName = "Liam Green", Email = "liam@example.com", Position = "Receptionist", Department = Department.Admin, HireDate = DateTime.Now.AddYears(-1), DateOfBirth = DateTime.Now.AddYears(-24), Type = EmployeeType.Temporary, Gender = "Male", Salary = 38000 }, new Employee { Id = 13, FullName = "Noah Black", Email = "noah@example.com", Position = "System Administrator", Department = Department.IT, HireDate = DateTime.Now.AddYears(-3), DateOfBirth = DateTime.Now.AddYears(-29), Type = EmployeeType.Permanent, Gender = "Male", Salary = 65000 }, new Employee { Id = 14, FullName = "Isabella Blue", Email = "isabella@example.com", Position = "HR Specialist", Department = Department.HR, HireDate = DateTime.Now.AddYears(-4), DateOfBirth = DateTime.Now.AddYears(-30), Type = EmployeeType.Permanent, Gender = "Female", Salary = 76000 }, new Employee { Id = 15, FullName = "James Brown", Email = "james@example.com", Position = "Account Executive", Department = Department.Sales, HireDate = DateTime.Now.AddYears(-2), DateOfBirth = DateTime.Now.AddYears(-28), Type = EmployeeType.Contract, Gender = "Male", Salary = 62000 } }; public async Task<(List<Employee> Employees, int TotalCount)> GetEmployees( string SearchTerm, // The search term used to filter employees by name string SelectedDepartment, // The selected department used to filter employees by department string SelectedType, // The selected employment type used to filter employees by employee type int PageNumber, // The current page number for pagination int PageSize) // The number of employees to display per page { // Convert the list of employees to an IQueryable to enable filtering and pagination // IQueryable allow dynamic querying with filtering and pagination. var filteredEmployees = employees.AsQueryable(); // If a search term is provided, filter the employees by their full name, ignoring case if (!string.IsNullOrEmpty(SearchTerm)) { filteredEmployees = filteredEmployees.Where(p => p.FullName.Contains(SearchTerm, StringComparison.OrdinalIgnoreCase)); } // If a department is selected, attempt to parse the department string to the Department enum if (!string.IsNullOrEmpty(SelectedDepartment)) { if (Enum.TryParse(SelectedDepartment, out Department department)) { // Filter the employees by the selected department filteredEmployees = filteredEmployees.Where(p => p.Department == department); } } // If an employment type is selected, attempt to parse the type string to the EmployeeType enum if (!string.IsNullOrEmpty(SelectedType)) { if (Enum.TryParse(SelectedType, out EmployeeType type)) { // Filter the employees by the selected employment type filteredEmployees = filteredEmployees.Where(p => p.Type == type); } } // Get the total count of employees after filtering, before pagination int totalCount = filteredEmployees.Count(); // Apply pagination by skipping the previous pages and taking the current page's employees filteredEmployees = filteredEmployees.Skip((PageNumber - 1) * PageSize) .Take(PageSize); // Return the filtered and paginated list of employees along with the total count return await Task.FromResult((filteredEmployees.ToList(), totalCount)); } public Employee? GetEmployeeById(int id) { return employees.FirstOrDefault(e => e.Id == id); } public void CreateEmployee(Employee employee) { employee.Id = employees.Max(e => e.Id) + 1; employees.Add(employee); } public void UpdateEmployee(Employee employee) { var existingEmployee = GetEmployeeById(employee.Id); if (existingEmployee != null) { existingEmployee.FullName = employee.FullName; existingEmployee.Email = employee.Email; existingEmployee.Position = employee.Position; existingEmployee.Department = employee.Department; existingEmployee.HireDate = employee.HireDate; existingEmployee.DateOfBirth = employee.DateOfBirth; existingEmployee.Type = employee.Type; existingEmployee.Gender = employee.Gender; existingEmployee.Salary = employee.Salary; } } public void DeleteEmployee(int id) { var employee = GetEmployeeById(id); if (employee != null) { employees.Remove(employee); } } } }
Employee Controller:
Next, create an Empty MVC Controller named EmployeeController within the Controllers folder and copy and paste the following code. The EmployeeController class handles HTTP requests related to employees in our application. It includes actions for listing employees (List), viewing details of a single employee (Details), creating a new employee (Create), updating an existing employee (Update), and deleting an existing employee (Delete).
The controller interacts with the EmployeeService to perform operations on the employee data and uses various view models to pass data to and from the views. Additionally, it provides a method (GetPositions) to return a list of positions based on the selected department, enhancing the user experience.
using EmployeePortal.Models; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Rendering; namespace EmployeePortal.Controllers { public class EmployeeController : Controller { private readonly EmployeeService _employeeService; public EmployeeController() { _employeeService = new EmployeeService(); } [HttpGet] public async Task<IActionResult> List( [FromQuery] string SearchTerm, // Model binding from the query string [FromQuery] string SelectedDepartment, // Model binding from the query string [FromQuery] string SelectedType, // Model binding from the query string [FromQuery] int PageNumber = 1, // Model binding from the query string with a default value [FromQuery] int PageSize = 5) // Model binding from the query string with a default value { // Retrieve the filtered and paginated list of employees var (employees, totalCount) = await _employeeService.GetEmployees(SearchTerm, SelectedDepartment, SelectedType, PageNumber, PageSize); var viewModel = new EmployeeListViewModel { Employees = employees, PageNumber = PageNumber, PageSize = PageSize, TotalPages = (int)Math.Ceiling((double)totalCount / PageSize), SearchTerm = SearchTerm, SelectedDepartment = SelectedDepartment, SelectedType = SelectedType }; // Generate SelectLists for dropdowns GetSelectLists(); // Set page size options in ViewBag for use in the view ViewBag.PageSizeOptions = new SelectList(new List<int> { 3, 5, 10, 15, 20, 25 }, PageSize); return View(viewModel); } [HttpGet] public IActionResult Create() { // Prepare dropdown options before rendering the Create view GetSelectLists(); return View(); } // Model binding from the form data [HttpPost] public IActionResult Create([FromForm] Employee employee) { if (ModelState.IsValid) { // Create a new employee and redirect to the Success page _employeeService.CreateEmployee(employee); return RedirectToAction("Success", new { id = employee.Id }); } // If validation fails, regenerate dropdown options and return the view with validation errors GetSelectLists(); return View(employee); } // Model binding from the route data public IActionResult Success([FromRoute] int id) { // Retrieve the employee by ID and display the Success view var employee = _employeeService.GetEmployeeById(id); if (employee == null) { return NotFound(); } return View(employee); } // Model binding from the route data public IActionResult Details([FromRoute] int id) { // Retrieve the employee details by ID and display the Details view var employee = _employeeService.GetEmployeeById(id); if (employee == null) { return NotFound(); } return View(employee); } // Model binding from the route data [HttpGet] public IActionResult Update([FromRoute] int id) { // Retrieve the employee by ID and prepare the Update view var employee = _employeeService.GetEmployeeById(id); if (employee == null) { return NotFound(); } // Prepare dropdown options before rendering the Update view GetSelectLists(); return View(employee); } // Model binding from the form data [HttpPost] public IActionResult Update([FromForm] Employee employee) { if (ModelState.IsValid) { // Update the employee details and redirect to the List view _employeeService.UpdateEmployee(employee); TempData["Message"] = $"Employee with ID {employee.Id} and Name {employee.FullName} has been updated."; return RedirectToAction("List"); } // If validation fails, regenerate dropdown options and return the view with validation errors GetSelectLists(); return View(employee); } // Model binding from the route data [HttpGet] public IActionResult Delete([FromRoute] int id) { // Retrieve the employee by ID and prepare the Delete confirmation view var employee = _employeeService.GetEmployeeById(id); if (employee == null) { return NotFound(); } return View(employee); } // We use ActionName to map this method to the "Delete" action // Model binding from the route data [HttpPost, ActionName("Delete")] public IActionResult DeleteConfirmed([FromRoute] int id) { // Retrieve the employee by ID and delete the employee var employee = _employeeService.GetEmployeeById(id); if (employee == null) { return NotFound(); } // Perform the deletion and redirect to the List view _employeeService.DeleteEmployee(id); TempData["Message"] = $"Employee with ID {id} and Name {employee.FullName} has been deleted."; return RedirectToAction("List"); } // Model binding from the query string (default binding) [HttpGet] public JsonResult GetPositions(Department department) { // This method returns a list of positions based on the department selected by the user var positions = new Dictionary<Department, List<string>> { { Department.IT, new List<string> { "Software Developer", "System Administrator", "Network Engineer" } }, { Department.HR, new List<string> { "HR Specialist", "HR Manager", "Talent Acquisition Coordinator" } }, { Department.Sales, new List<string> { "Sales Executive", "Sales Manager", "Account Executive" } }, { Department.Admin, new List<string> { "Office Manager", "Executive Assistant", "Receptionist" } } }; // Check if the department exists in the dictionary, and return the corresponding positions var result = positions.ContainsKey(department) ? positions[department] : new List<string>(); // Return the positions as a JSON response to be used in client-side scripts return Json(result); } // Private method to generate SelectLists for dropdowns in the views private void GetSelectLists() { ViewBag.DepartmentOptions = new SelectList(Enum.GetValues(typeof(Department)).Cast<Department>()); ViewBag.EmployeeTypeOptions = new SelectList(Enum.GetValues(typeof(EmployeeType)).Cast<EmployeeType>()); } } }
Model Binding Techniques:
- [FromQuery] binds query string parameters to action method parameters.
- [FromForm] binds form data (POST data) to action method parameters.
- [FromRoute] binds route data (e.g., URL segments) to action method parameters.
ActionName Attribute:
The ActionName(“Delete”) attribute maps the DeleteConfirmed method to the Delete action name. This allows you to differentiate between the HttpGet and HttpPost methods, which are both associated with the same action name: Delete.
GetPositions Method:
This method returns a list of positions based on the department selected by the user. It returns the data in JSON format, making it easy to consume on the client side (e.g., in JavaScript). This can be useful for dynamically populating dropdowns based on user selections.
Creating Views:
Now, let us create the required views:
List View:
Next, create a view named List.cshtml within the Views/Employee folder and then copy and paste the following code. This will create the List view where the user can see the employees and filter them. Also, provide the buttons to create a new employee and update and delete an existing employee. It also has the Details button to view the details of an existing employee.
@model EmployeeListViewModel @{ ViewData["Title"] = "Employee List"; } <div class="container mt-4"> <div class="row"> <div class="col-md-12"> <div class="d-flex justify-content-between align-items-center mb-4 p-3 bg-light rounded shadow-sm"> <h2 class="mb-0 text-primary"><i class="bi bi-people-fill"></i> @ViewData["Title"]</h2> <a class="btn btn-success btn-lg" asp-action="Create"> <i class="bi bi-plus-circle"></i> Create New Employee </a> </div> @if (TempData["Message"] != null) { <div class="alert alert-success alert-dismissible fade show" role="alert"> @TempData["Message"] <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button> </div> } <!-- Filter Section --> <div class="card mb-4 shadow-sm"> <div class="card-header bg-primary text-white d-flex justify-content-between align-items-center"> <h5 class="mb-0">🔍 Filter Employees</h5> <span class="badge bg-light text-dark">Total Employees: @Model.Employees.Count() 📝</span> </div> <div class="card-body"> <form method="get" asp-controller="Employee" asp-action="List" class="row g-3"> <div class="col-md-3"> <label asp-for="SearchTerm" class="form-label">🔍 Search by Name</label> <input asp-for="SearchTerm" class="form-control" placeholder="Type a name..." /> </div> <div class="col-md-3"> <label asp-for="SelectedDepartment" class="form-label">🏢 Department</label> <select asp-for="SelectedDepartment" asp-items="@ViewBag.DepartmentOptions" class="form-control"> <option value="">All Departments</option> </select> </div> <div class="col-md-3"> <label asp-for="SelectedType" class="form-label">👔 Employee Type</label> <select asp-for="SelectedType" asp-items="@ViewBag.EmployeeTypeOptions" class="form-control"> <option value="">All Employee Types</option> </select> </div> <div class="col-md-2"> <label asp-for="PageSize" class="form-label">📄 Items per Page</label> <select asp-for="PageSize" asp-items="@ViewBag.PageSizeOptions" class="form-control" onchange="this.form.submit();"></select> </div> <div class="col-md-1 d-flex align-items-end"> <button type="submit" class="btn btn-success w-100">Filter 🎯</button> </div> </form> </div> </div> <div class="card shadow-sm"> <div class="card-body p-0"> <table class="table table-hover table-striped mb-0"> <thead class="bg-primary text-white"> <tr> <th>📛 Name</th> <th>📧 Email</th> <th>💼 Position</th> <th>🏢 Department</th> <th>⚧ Gender</th> <th>👔 Employee Type</th> <th class="text-center">⚙️ Actions</th> </tr> </thead> <tbody> @foreach (var employee in Model.Employees) { <tr> <td>@employee.FullName</td> <td>@employee.Email</td> <td>@employee.Position</td> <td>@employee.Department</td> <td>@employee.Gender</td> <td>@employee.Type</td> <td class="text-center"> <a class="btn btn-sm btn-info" asp-controller="Employee" asp-action="Details" asp-route-id="@employee.Id"> <i class="bi bi-eye"></i> Details </a> <a class="btn btn-sm btn-warning" asp-controller="Employee" asp-action="Update" asp-route-id="@employee.Id"> <i class="bi bi-pencil"></i> Update </a> <a class="btn btn-sm btn-danger" asp-controller="Employee" asp-action="Delete" asp-route-id="@employee.Id"> <i class="bi bi-trash"></i> Delete </a> </td> </tr> } </tbody> </table> </div> </div> <!-- Pagination --> <nav aria-label="Employee List Pagination" class="mt-4"> <ul class="pagination justify-content-center mb-0"> @if (Model.PageNumber == 1) { <li class="page-item disabled"> <span class="page-link">First ⏮️</span> </li> <li class="page-item disabled"> <span class="page-link">Previous ⬅️</span> </li> } else { <li class="page-item"> <a class="page-link" href="@Url.Action("List", "Employee", GetRouteValuesForPage(1))">First ⏮️</a> </li> <li class="page-item"> <a class="page-link" href="@Url.Action("List", "Employee", GetRouteValuesForPage(Model.PageNumber - 1))">Previous ⬅️</a> </li> } <li class="page-item active"> <span class="page-link">@Model.PageNumber</span> </li> @if (Model.PageNumber == Model.TotalPages) { <li class="page-item disabled"> <span class="page-link">Next ➡️</span> </li> <li class="page-item disabled"> <span class="page-link">Last ⏭️</span> </li> } else { <li class="page-item"> <a class="page-link" href="@Url.Action("List", "Employee", GetRouteValuesForPage(Model.PageNumber + 1))">Next ➡️</a> </li> <li class="page-item"> <a class="page-link" href="@Url.Action("List", "Employee", GetRouteValuesForPage(Model.TotalPages))">Last ⏭️</a> </li> } </ul> </nav> </div> </div> </div> @functions { private object GetRouteValuesForPage(int pageNumber) { return new { SearchTerm = Model.SearchTerm, SelectedDepartment = Model.SelectedDepartment, SelectedType = Model.SelectedType, PageSize = Model.PageSize, PageNumber = pageNumber }; } }
Create View:
Next, create a view named Create.cshtml within the Views/Employee folder and copy and paste the following code. This will create the Create view where the user can create new employees.
@model Employee @{ ViewData["Title"] = "Create New Employee"; } <div class="container mt-5"> <div class="row justify-content-center"> <div class="col-lg-8 col-md-10"> <div class="card border-0 shadow-sm"> <div class="card-body p-4 border rounded"> <h2 class="text-center text-primary mb-4">👤 Create New Employee</h2> <form asp-controller="Employee" asp-action="Create" method="post"> <div class="row mb-3"> <label asp-for="FullName" class="col-sm-3 col-form-label text-end">Full Name:</label> <div class="col-sm-9"> <input asp-for="FullName" class="form-control" placeholder="Enter full name" title="Full Name" /> <span asp-validation-for="FullName" class="text-danger"></span> </div> </div> <div class="row mb-3"> <label asp-for="Email" class="col-sm-3 col-form-label text-end">📧 Email:</label> <div class="col-sm-9"> <input asp-for="Email" class="form-control" placeholder="Enter email address" title="Email Address" /> <span asp-validation-for="Email" class="text-danger"></span> </div> </div> <div class="row mb-3"> <label asp-for="Department" class="col-sm-3 col-form-label text-end">🏢 Department:</label> <div class="col-sm-9"> <div class="input-group"> <select asp-for="Department" class="form-control" asp-items="@ViewBag.DepartmentOptions" title="Select Department" id="DepartmentDropdown"> <option value="">Select Department</option> </select> <span class="input-group-text"><i class="bi bi-caret-down-fill"></i></span> </div> <span asp-validation-for="Department" class="text-danger"></span> </div> </div> <div class="row mb-3"> <label asp-for="Position" class="col-sm-3 col-form-label text-end">💼 Position:</label> <div class="col-sm-9"> <div class="input-group"> <select asp-for="Position" class="form-control" id="PositionDropdown" title="Select Position"> <option value="">Select Position</option> </select> <span class="input-group-text"><i class="bi bi-caret-down-fill"></i></span> </div> <span asp-validation-for="Position" class="text-danger"></span> </div> </div> <div class="row mb-3"> <label asp-for="HireDate" class="col-sm-3 col-form-label text-end">🗓️ Hire Date:</label> <div class="col-sm-9"> <input asp-for="HireDate" class="form-control" type="date" title="Select Hire Date" /> <span asp-validation-for="HireDate" class="text-danger"></span> </div> </div> <div class="row mb-3"> <label asp-for="DateOfBirth" class="col-sm-3 col-form-label text-end">🎂 Date of Birth:</label> <div class="col-sm-9"> <input asp-for="DateOfBirth" class="form-control" type="date" title="Select Date of Birth" /> <span asp-validation-for="DateOfBirth" class="text-danger"></span> </div> </div> <div class="row mb-3"> <label asp-for="Type" class="col-sm-3 col-form-label text-end">👔 Employee Type:</label> <div class="col-sm-9"> <div class="input-group"> <select asp-for="Type" class="form-control" asp-items="@ViewBag.EmployeeTypeOptions" title="Select Employee Type"> <option value="">Select Employee Type</option> </select> <span class="input-group-text"><i class="bi bi-caret-down-fill"></i></span> </div> <span asp-validation-for="Type" class="text-danger"></span> </div> </div> <div class="mb-3 row"> <label asp-for="Gender" class="col-sm-3 col-form-label text-end">⚧ Gender:</label> <div class="col-sm-9"> <div class="form-check form-check-inline"> <input asp-for="Gender" type="radio" class="form-check-input" value="Male" /> <label class="form-check-label" asp-for="Gender">Male</label> </div> <div class="form-check form-check-inline"> <input asp-for="Gender" type="radio" class="form-check-input" value="Female" /> <label class="form-check-label" asp-for="Gender">Female</label> </div> <div class="form-check form-check-inline"> <input asp-for="Gender" type="radio" class="form-check-input" value="Other" /> <label class="form-check-label" asp-for="Gender">Other</label> </div> <span asp-validation-for="Gender" class="text-danger"></span> </div> </div> <div class="row mb-3"> <label asp-for="Salary" class="col-sm-3 col-form-label text-end">💰 Salary:</label> <div class="col-sm-9"> <input asp-for="Salary" class="form-control" placeholder="Enter salary amount" title="Salary" /> <span asp-validation-for="Salary" class="text-danger"></span> </div> </div> <div class="text-center mt-4"> <button type="submit" class="btn btn-success btn-lg me-3"><i class="bi bi-check-circle-fill"></i> Create</button> <a class="btn btn-primary btn-lg" asp-controller="Employee" asp-action="List"><i class="bi bi-arrow-left-circle-fill"></i> Back</a> </div> </form> </div> </div> </div> </div> </div> @section Scripts { <script> $(document).ready(function () { // Function to load positions and set the selected position function loadPositions(department, selectedPosition) { if (department) { $.getJSON('@Url.Action("GetPositions")', { department: department }, function (data) { var $positionDropdown = $('#PositionDropdown'); $positionDropdown.empty(); $positionDropdown.append('<option value="">Select Position</option>'); $.each(data, function (index, value) { var selected = (value === selectedPosition) ? 'selected' : ''; $positionDropdown.append('<option value="' + value + '" ' + selected + '>' + value + '</option>'); }); }); } else { $('#PositionDropdown').empty().append('<option value="">Select Position</option>'); } } // Check the DepartmentDropdown value on page load and populate PositionDropdown var department = $('#DepartmentDropdown').val(); var selectedPosition = '@(Model?.Position ?? "")'; // Safely check if Model or Model.Position is null if (department) { loadPositions(department, selectedPosition); } // When the Department dropdown value changes, load the corresponding positions $('#DepartmentDropdown').change(function () { var department = $(this).val(); loadPositions(department, ''); // Clear selected position when department changes }); }); </script> }
Success View:
Next, create a view named Success.cshtml within the Views/Employee folder, and then copy and paste the following code. This will create the Success view, which will be rendered when the user successfully creates a new employee.
@model Employee @{ ViewData["Title"] = "Success"; } <div class="container mt-5"> <div class="row justify-content-center"> <div class="col-lg-8 col-md-10"> <div class="card border-0 shadow-sm"> <div class="card-body p-4 border rounded"> <div class="text-center mb-4"> <h2 class="text-success mb-3"><i class="bi bi-check-circle-fill"></i> Employee Created Successfully!</h2> <p class="text-muted">Welcome <strong>@Model.FullName</strong>! We are excited to have you join the <strong>@Model.Department</strong> department. Below are the details of the newly created employee:</p> </div> <div class="table-responsive"> <table class="table table-borderless"> <tbody> <tr> <th class="text-muted text-start" style="width: 30%;">📧 Email:</th> <td class="fw-bold text-dark text-start">@Model.Email</td> </tr> <tr> <th class="text-muted text-start">💼 Position:</th> <td class="fw-bold text-dark text-start">@Model.Position</td> </tr> <tr> <th class="text-muted text-start">🏢 Department:</th> <td class="fw-bold text-dark text-start">@Model.Department</td> </tr> <tr> <th class="text-muted text-start">🗓️ Hire Date:</th> <td class="fw-bold text-dark text-start">@Model.HireDate?.ToShortDateString()</td> </tr> <tr> <th class="text-muted text-start">🎂 Date of Birth:</th> <td class="fw-bold text-dark text-start">@Model.DateOfBirth?.ToShortDateString()</td> </tr> <tr> <th class="text-muted text-start">👔 Employee Type:</th> <td class="fw-bold text-dark text-start">@Model.Type</td> </tr> <tr> <th class="text-muted text-start">⚧ Gender:</th> <td class="fw-bold text-dark text-start">@Model.Gender</td> </tr> <tr> <th class="text-muted text-start">💰 Salary:</th> <td class="fw-bold text-dark text-start">$@Model.Salary?.ToString("N2")</td> </tr> </tbody> </table> </div> <div class="text-center mt-4"> <a class="btn btn-success btn-lg me-3" asp-controller="Employee" asp-action="Create"><i class="bi bi-person-plus-fill"></i> Create Another Employee</a> <a class="btn btn-primary btn-lg" asp-controller="Employee" asp-action="List"><i class="bi bi-arrow-left-circle-fill"></i> Back to Employee List</a> </div> </div> </div> </div> </div> </div>
Details View:
Next, create a view named Details.cshtml within the Views/Employee folder and then copy and paste the following code. This will create the Details view where the user can verify the data of an existing employee.
@model Employee @{ ViewData["Title"] = "Employee Details"; } <div class="container mt-5"> <div class="row justify-content-center"> <div class="col-lg-8 col-md-10"> <div class="card border-0 shadow-sm"> <div class="card-body p-4 border rounded"> <div class="text-center mb-4"> <h2 class="text-primary mb-1">👤 @Model.FullName</h2> <p class="text-muted">Employee ID: @Model.Id</p> </div> <div class="table-responsive"> <table class="table table-borderless"> <tbody> <tr> <th class="text-muted text-start ps-3" style="width: 30%;">📧 Email:</th> <td class="fw-bold text-dark text-start ps-3"><a href="mailto:@Model.Email" class="text-decoration-none text-dark">@Model.Email</a></td> </tr> <tr> <th class="text-muted text-start ps-3">💼 Position:</th> <td class="fw-bold text-dark text-start ps-3">@Model.Position</td> </tr> <tr> <th class="text-muted text-start ps-3">🏢 Department:</th> <td class="fw-bold text-dark text-start ps-3">@Model.Department</td> </tr> <tr> <th class="text-muted text-start ps-3">🗓️ Hire Date:</th> <td class="fw-bold text-dark text-start ps-3">@Model.HireDate?.ToString("MMMM dd, yyyy")</td> </tr> <tr> <th class="text-muted text-start ps-3">🎂 Date of Birth:</th> <td class="fw-bold text-dark text-start ps-3">@Model.DateOfBirth?.ToString("MMMM dd, yyyy")</td> </tr> <tr> <th class="text-muted text-start ps-3">👔 Employee Type:</th> <td class="fw-bold text-dark text-start ps-3">@Model.Type</td> </tr> <tr> <th class="text-muted text-start ps-3">⚧ Gender:</th> <td class="fw-bold text-dark text-start ps-3">@Model.Gender</td> </tr> <tr> <th class="text-muted text-start ps-3">💰 Salary:</th> <td class="fw-bold text-dark text-start ps-3">$@Model.Salary?.ToString("N2")</td> </tr> </tbody> </table> </div> <div class="d-flex justify-content-around mt-4"> <a class="btn btn-primary btn-lg px-5 py-2 rounded-pill shadow-sm" asp-controller="Employee" asp-route-id="@Model.Id" asp-action="Update"> <i class="bi bi-pencil-fill"></i> Update </a> <a class="btn btn-danger btn-lg px-5 py-2 rounded-pill shadow-sm" asp-controller="Employee" asp-route-id="@Model.Id" asp-action="Delete"> <i class="bi bi-trash-fill"></i> Delete </a> <a class="btn btn-secondary btn-lg px-5 py-2 rounded-pill shadow-sm" asp-controller="Employee" asp-action="List"> <i class="bi bi-arrow-left-circle-fill"></i> Back to List </a> </div> </div> </div> </div> </div> </div>
Update View:
Next, create a view named Update.cshtml within the Views/Employee folder and copy and paste the following code. This will create the Update view, where the user can update the data of an existing employee.
@model Employee @{ ViewData["Title"] = "Update Employee"; } <div class="container mt-5"> <div class="row justify-content-center"> <div class="col-lg-8 col-md-10"> <div class="card border-0 shadow-sm"> <div class="card-body p-4 border rounded"> <h2 class="text-center text-primary mb-4">✏️ Update Employee Details</h2> <form asp-controller="Employee" asp-action="Update" method="post"> <!-- Hidden field to store the Employee ID --> <input type="hidden" asp-for="Id" /> <div class="row mb-3"> <label asp-for="FullName" class="col-sm-3 col-form-label text-end">Full Name:</label> <div class="col-sm-9"> <input asp-for="FullName" class="form-control" placeholder="Enter full name" title="Full Name" /> <span asp-validation-for="FullName" class="text-danger"></span> </div> </div> <div class="row mb-3"> <label asp-for="Email" class="col-sm-3 col-form-label text-end">📧 Email:</label> <div class="col-sm-9"> <input asp-for="Email" class="form-control" placeholder="Enter email address" title="Email Address" /> <span asp-validation-for="Email" class="text-danger"></span> </div> </div> <div class="row mb-3"> <label asp-for="Department" class="col-sm-3 col-form-label text-end">🏢 Department:</label> <div class="col-sm-9"> <div class="input-group"> <select asp-for="Department" class="form-control" asp-items="@ViewBag.DepartmentOptions" title="Select Department" id="DepartmentDropdown"> <option value="">Select Department</option> </select> <span class="input-group-text"><i class="bi bi-caret-down-fill"></i></span> </div> <span asp-validation-for="Department" class="text-danger"></span> </div> </div> <div class="row mb-3"> <label asp-for="Position" class="col-sm-3 col-form-label text-end">💼 Position:</label> <div class="col-sm-9"> <div class="input-group"> <select asp-for="Position" class="form-control" id="PositionDropdown" title="Select Position"> <option value="">Select Position</option> </select> <span class="input-group-text"><i class="bi bi-caret-down-fill"></i></span> </div> <span asp-validation-for="Position" class="text-danger"></span> </div> </div> <div class="row mb-3"> <label asp-for="HireDate" class="col-sm-3 col-form-label text-end">🗓️ Hire Date:</label> <div class="col-sm-9"> <input asp-for="HireDate" class="form-control" type="date" title="Select Hire Date" /> <span asp-validation-for="HireDate" class="text-danger"></span> </div> </div> <div class="row mb-3"> <label asp-for="DateOfBirth" class="col-sm-3 col-form-label text-end">🎂 Date of Birth:</label> <div class="col-sm-9"> <input asp-for="DateOfBirth" class="form-control" type="date" title="Select Date of Birth" /> <span asp-validation-for="DateOfBirth" class="text-danger"></span> </div> </div> <div class="row mb-3"> <label asp-for="Type" class="col-sm-3 col-form-label text-end">👔 Employee Type:</label> <div class="col-sm-9"> <div class="input-group"> <select asp-for="Type" class="form-control" asp-items="@ViewBag.EmployeeTypeOptions" title="Select Employee Type"> <option value="">Select Employee Type</option> </select> <span class="input-group-text"><i class="bi bi-caret-down-fill"></i></span> </div> <span asp-validation-for="Type" class="text-danger"></span> </div> </div> <div class="mb-3 row"> <label asp-for="Gender" class="col-sm-3 col-form-label text-end">⚧ Gender:</label> <div class="col-sm-9"> <div class="form-check form-check-inline"> <input asp-for="Gender" type="radio" class="form-check-input" value="Male" /> <label class="form-check-label" asp-for="Gender">Male</label> </div> <div class="form-check form-check-inline"> <input asp-for="Gender" type="radio" class="form-check-input" value="Female" /> <label class="form-check-label" asp-for="Gender">Female</label> </div> <div class="form-check form-check-inline"> <input asp-for="Gender" type="radio" class="form-check-input" value="Other" /> <label class="form-check-label" asp-for="Gender">Other</label> </div> <span asp-validation-for="Gender" class="text-danger"></span> </div> </div> <div class="row mb-3"> <label asp-for="Salary" class="col-sm-3 col-form-label text-end">💰 Salary:</label> <div class="col-sm-9"> <input asp-for="Salary" class="form-control" placeholder="Enter salary amount" title="Salary" /> <span asp-validation-for="Salary" class="text-danger"></span> </div> </div> <div class="text-center mt-4"> <button type="submit" class="btn btn-success btn-lg me-3"><i class="bi bi-pencil-square"></i> Update Employee</button> <a class="btn btn-primary btn-lg" asp-controller="Employee" asp-action="List"><i class="bi bi-arrow-left-circle-fill"></i> Back to Employee List</a> </div> </form> </div> </div> </div> </div> </div> @section Scripts { <script> $(document).ready(function () { // Function to load positions and set the selected position function loadPositions(department, selectedPosition) { if (department) { $.getJSON('@Url.Action("GetPositions")', { department: department }, function (data) { var $positionDropdown = $('#PositionDropdown'); $positionDropdown.empty(); $positionDropdown.append('<option value="">Select Position</option>'); $.each(data, function (index, value) { var selected = (value === selectedPosition) ? 'selected' : ''; $positionDropdown.append('<option value="' + value + '" ' + selected + '>' + value + '</option>'); }); }); } else { $('#PositionDropdown').empty().append('<option value="">Select Position</option>'); } } // Check the DepartmentDropdown value on page load and populate PositionDropdown var department = $('#DepartmentDropdown').val(); var selectedPosition = '@(Model?.Position ?? "")'; // Safely check if Model or Model.Position is null if (department) { loadPositions(department, selectedPosition); } // When the Department dropdown value changes, load the corresponding positions $('#DepartmentDropdown').change(function () { var department = $(this).val(); loadPositions(department, ''); // Clear selected position when department changes }); }); </script> }
Delete View:
Next, create a view named Delete.cshtml within the Views/Employee folder and copy and paste the following code. This will create the Delete view where the user can delete an existing employee.
@model Employee @{ ViewData["Title"] = "Delete Employee"; } <div class="container mt-5 d-flex justify-content-center"> <div class="col-lg-8 col-md-10"> <div class="card border-0 shadow-sm"> <div class="card-body p-4 border rounded"> <div class="alert alert-warning text-center mb-4"> <h2 class="text-danger mb-1">⚠️ Are you sure?</h2> <p class="text-dark">You are about to permanently delete this employee's record. This action is irreversible and will remove all data related to <strong>@Model.FullName</strong> from the system. Please confirm your decision.</p> </div> <div class="table-responsive"> <table class="table table-borderless"> <tbody> <tr> <th class="text-muted text-start">👤 Full Name:</th> <td class="fw-bold text-dark text-start ps-2">@Model.FullName</td> </tr> <tr> <th class="text-muted text-start">📧 Email:</th> <td class="fw-bold text-dark text-start ps-2">@Model.Email</td> </tr> <tr> <th class="text-muted text-start">💼 Position:</th> <td class="fw-bold text-dark text-start ps-2">@Model.Position</td> </tr> <tr> <th class="text-muted text-start">🏢 Department:</th> <td class="fw-bold text-dark text-start ps-2">@Model.Department</td> </tr> <tr> <th class="text-muted text-start">🗓️ Hire Date:</th> <td class="fw-bold text-dark text-start ps-2">@Model.HireDate?.ToShortDateString()</td> </tr> <tr> <th class="text-muted text-start">🎂 Date of Birth:</th> <td class="fw-bold text-dark text-start ps-2">@Model.DateOfBirth?.ToShortDateString()</td> </tr> <tr> <th class="text-muted text-start">👔 Employee Type:</th> <td class="fw-bold text-dark text-start ps-2">@Model.Type</td> </tr> <tr> <th class="text-muted text-start">💰 Salary:</th> <td class="fw-bold text-dark text-start ps-2">$@Model.Salary</td> </tr> </tbody> </table> </div> <div class="text-center mt-4"> <form asp-action="Delete" asp-controller="Employee" method="post"> <input type="hidden" asp-for="Id" /> <button type="submit" class="btn btn-danger btn-lg me-3"><i class="bi bi-trash-fill"></i> Yes, Delete</button> <a class="btn btn-outline-success btn-lg" asp-controller="Employee" asp-action="List"><i class="bi bi-arrow-left-circle-fill"></i> Cancel</a> </form> </div> </div> </div> </div> </div>
Modify Program Class:
We need to set the Employee Controller and List action as the default page for our application. So, please change the default Routing Configuration as follows in the Program class:
app.MapControllerRoute( name: "default", pattern: "{controller=Employee}/{action=List}/{id?}");
That’s it. Run the application and test the functionalities; it should work as expected. We have successfully implemented the Employee Portal application using ASP.NET Core MVC, allowing users to perform different operations on Employee data.
In the next article, I will discuss developing a Hospital Management Application using ASP.NET Core MVC and Entity Framework Core. I hope you enjoy this in-depth article on a Real-time Employee Portal Application using ASP.NET Core MVC. Please give your valuable feedback about this Employee Portal Application using the ASP.NET Core MVC article and tell me how we can improve this project.
I have read this article and create the same application in my local system. I have learnt many new concepts in it.