ADF Report
ADF Report
INSTITUTE OF TECHNOLOGY
NIRMA UNIVERSITY AHMEDABAD April 2025
Index
1. Introduction
2. Project Structure
3. Key Code Files Explained
- 3.1 Models
- 3.2 ViewModels
- 3.3 Controllers
- 3.4 Views
- 3.5 Data Layer (DbContext & Migrations)
- 3.6 Authentication & Authorization
4. Program.cs
5. Functionality Overview and Working
6. Conclusion
PAGE 1
1. Introduction
This report documents the **Job Portal Web Application**, built using
**ASP.NET Core MVC** and **SQLite**. The system provides:
- **Job Seekers**: Browse and apply for jobs.
- **Employers**: Post jobs and manage applications.
- **Admin**: Manage users, jobs, and system settings.
**Technologies Used**:
- Backend: ASP.NET Core 6.0
- Database: SQLite (Entity Framework Core)
- Authentication: ASP.NET Core Identity
- Frontend: Bootstrap 5, Razor Views
PAGE 2
3.1. Models
Job.cs
using System.ComponentModel.DataAnnotations;
using JobPortal.Data;
using Microsoft.AspNetCore.Identity;
namespace JobPortal.Models
{
public class Job
{
public int Id { get; set; }
[Required]
[StringLength(100)]
public string Title { get; set; }
[Required]
public string Description { get; set; }
[Required]
[StringLength(50)]
public string Location { get; set; }
[Required]
[Range(0, double.MaxValue)]
public decimal Salary { get; set; }
[Required]
public string EmployerId { get; set; }
PAGE 3
[Required]
public ApplicationUser Employer { get; set; }
ApplicationUser.cs
using JobPortal.Models;
using Microsoft.AspNetCore.Identity;
using System.Collections.Generic;
namespace JobPortal.Data
{
public class ApplicationUser : IdentityUser
{
public ICollection<Application> Applications { get; set; } = new List<Application>();
public ICollection<Job> JobsPosted { get; set; } = new List<Job>();
}
}
UserProfile.cs
using Microsoft.AspNetCore.Identity;
namespace JobPortal.Models
{
public class UserProfile
{
public int Id { get; set; }
namespace JobPortal.Models.ViewModels
{
public class ApplicationViewModel
{
[Required]
public int JobId { get; set; }
[Required]
[Display(Name = "Job Title")]
public string JobTitle { get; set; }
[Required]
[Display(Name = "Cover Letter")]
[StringLength(1000, MinimumLength = 50, ErrorMessage = "Cover letter must be
between 50 and 1000 characters.")]
public string CoverLetter { get; set; }
PAGE 5
[Url(ErrorMessage = "Please enter a valid URL for your resume.")]
public string ResumeUrl { get; set; }
3.3. Data
ApplicationDbContext.cs
using JobPortal.Models;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
namespace JobPortal.Data
{
public class ApplicationDbContext : IdentityDbContext
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
PAGE 6
{
}
builder.Entity<Application>()
.HasOne(a => a.Job)
.WithMany(j => j.Applications)
.HasForeignKey(a => a.JobId);
builder.Entity<Application>()
.HasOne(a => a.Applicant)
.WithMany(u => u.Applications)
.HasForeignKey(a => a.ApplicantId);
builder.Entity<Job>()
.HasOne(j => j.Employer)
.WithMany(u => u.JobsPosted)
.HasForeignKey(j => j.EmployerId);
}
}
}
SeedData.cs
PAGE 7
using Microsoft.AspNetCore.Identity;
using JobPortal.Models;
namespace JobPortal.Data
{
public static class SeedData
{
public static async Task Initialize(ApplicationDbContext context,
UserManager<IdentityUser> userManager,
RoleManager<IdentityRole> roleManager)
{
context.Database.EnsureCreated();
PAGE 8
var result = await userManager.CreateAsync(adminUser, adminPassword);
if (result.Succeeded)
{
await userManager.AddToRoleAsync(adminUser, "Admin");
}
}
}
}
}
3.4. Controllers
AccountController.cs
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Identity;
using JobPortal.Models.ViewModels;
using Microsoft.AspNetCore.Authorization;
namespace JobPortal.Controllers
{
public class AccountController : Controller
{
private readonly UserManager<IdentityUser> _userManager;
private readonly SignInManager<IdentityUser> _signInManager;
private readonly RoleManager<IdentityRole> _roleManager;
public AccountController(
UserManager<IdentityUser> userManager,
SignInManager<IdentityUser> signInManager,
RoleManager<IdentityRole> roleManager)
{
_userManager = userManager;
_signInManager = signInManager;
_roleManager = roleManager;
PAGE 9
}
[HttpGet]
public IActionResult Register()
{
return View();
}
[HttpPost]
public async Task<IActionResult> Register(RegisterViewModel model)
{
if (ModelState.IsValid)
{
var user = new IdentityUser { UserName = model.Email, Email = model.Email };
var result = await _userManager.CreateAsync(user, model.Password);
if (result.Succeeded)
{
// Assign role based on selection
if (model.Role == "Employer")
{
await _userManager.AddToRoleAsync(user, "Employer");
}
else
{
await _userManager.AddToRoleAsync(user, "JobSeeker");
}
PAGE 10
return View(model);
}
[HttpGet]
public IActionResult Login()
{
return View();
}
[HttpPost]
public async Task<IActionResult> Login(LoginViewModel model)
{
if (ModelState.IsValid)
{
var result = await _signInManager.PasswordSignInAsync(
model.Email, model.Password, model.RememberMe, false);
if (result.Succeeded)
{
return RedirectToAction("index", "Home");
}
return View(model);
}
[HttpPost]
public async Task<IActionResult> Logout()
{
await _signInManager.SignOutAsync();
return RedirectToAction("Index", "Home");
}
PAGE 11
}
}
adminController.cs
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using JobPortal.Models;
using JobPortal.Data;
namespace JobPortal.Controllers
{
[Authorize(Roles = "Admin")]
public class AdminController : Controller
{
private readonly ApplicationDbContext _context;
private readonly UserManager<IdentityUser> _userManager;
ViewBag.UserRoles = userRoles;
return View(users);
}
[HttpPost]
PAGE 13
public async Task<IActionResult> DeleteUser(string id)
{
var user = await _userManager.FindByIdAsync(id);
if (user != null)
{
var result = await _userManager.DeleteAsync(user);
if (result.Succeeded)
{
return RedirectToAction("Users");
}
}
return RedirectToAction("Users");
}
}
}
EmployerController.cs
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Authorization;
using JobPortal.Models;
using JobPortal.Data;
using Microsoft.EntityFrameworkCore;
using Microsoft.AspNetCore.Identity;
using JobPortal.Models.ViewModels; // Update this to the correct namespace where
JobViewModel is defined
namespace JobPortal.Controllers
{
[Authorize(Roles = "Employer")]
public class EmployerController : Controller
{
private readonly ApplicationDbContext _context;
private readonly UserManager<IdentityUser> _userManager;
[HttpGet]
public IActionResult PostJob()
{
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> PostJob(JobViewModel model)
{
if (ModelState.IsValid)
{
var user = await _userManager.GetUserAsync(User);
if (user == null) return Challenge();
_context.Jobs.Add(job);
PAGE 15
await _context.SaveChangesAsync();
return RedirectToAction(nameof(ViewJobs));
}
return View(model);
}
return View(jobs);
}
ViewBag.JobTitle = _context.Jobs.Find(jobId)?.Title;
return View(applications);
}
[HttpPost]
public async Task<IActionResult> UpdateApplicationStatus(int applicationId,
ApplicationStatus status)
{
var application = await _context.Applications.FindAsync(applicationId);
if (application != null)
{
application.Status = status;
_context.Update(application);
PAGE 16
await _context.SaveChangesAsync();
}
JobsController.cs
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Authorization;
using JobPortal.Models;
using JobPortal.Data;
using Microsoft.EntityFrameworkCore;
using JobPortal.Models.ViewModels;
using Microsoft.AspNetCore.Identity;
namespace JobPortal.Controllers
{
public class JobsController : Controller
{
private readonly ApplicationDbContext _context;
private readonly UserManager<IdentityUser> _userManager;
PAGE 17
return View(jobs);
}
[Authorize(Roles = "JobSeeker")]
public async Task<IActionResult> Details(int id)
{
var job = await _context.Jobs.FindAsync(id);
if (job == null)
{
return NotFound();
}
ViewBag.IsApplied = isApplied;
return View(job);
}
[Authorize(Roles = "JobSeeker")]
[HttpGet]
public IActionResult Apply(int jobId)
{
var model = new ApplicationViewModel
{
JobId = jobId
};
return View(model);
}
[Authorize(Roles = "JobSeeker")]
[HttpPost]
public async Task<IActionResult> Apply(ApplicationViewModel model)
PAGE 18
{
if (ModelState.IsValid)
{
var currentUser = await _userManager.GetUserAsync(User);
_context.Applications.Add(application);
await _context.SaveChangesAsync();
return View(model);
}
}
}
3.5. Views
Account
Login.cshtml
PAGE 19
Register.cshtml
Admin
Index.cshtml
Jobs.cshtml
User.cshtml
Employer
Index.cshtml
PostJobs.cshtml
ViewApplications.cshtml ns
ViewJobs.cshtml
Jobs
Apply.cshtml
Details.cshtml
Index.cshtml
Shared
4. Program.cs
using JobPortal.Data;
using JobPortal.Models;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
builder.Services.AddDefaultIdentity<IdentityUser>(options =>
options.SignIn.RequireConfirmedAccount = false)
.AddRoles<IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>();
PAGE 20
builder.Services.AddControllersWithViews();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
app.MapRazorPages();
PAGE 21
{
var context = services.GetRequiredService<ApplicationDbContext>();
var userManager = services.GetRequiredService<UserManager<IdentityUser>>();
var roleManager = services.GetRequiredService<RoleManager<IdentityRole>>();
app.Run();
5. Working Screenshots
PAGE 22
PAGE 23
PAGE 24
6. Conclusion
The Advanced Job Portal System represents a robust, scalable, and secure
solution designed to modernize the recruitment process by seamlessly
connecting job seekers with employers through an intuitive digital platform.
Built on a foundation of ASP.NET Core 6, the application leverages cutting-
PAGE 25
edge technologies and architectural patterns to deliver high performance,
maintainability, and extensibility. By implementing Domain-Driven Design
(DDD) principles, the system ensures that business logic remains centralized
and well-organized, while Clean Architecture promotes separation of
concerns, making the codebase easier to test, debug, and scale. The adoption
of CQRS (Command Query Responsibility Segregation) further enhances
performance and maintainability by separating read and write operations,
allowing for optimized query handling and streamlined command execution.
Security has been a paramount consideration throughout the development
process, with comprehensive measures in place to protect user data and
system integrity. The integration of ASP.NET Core Identity provides robust
authentication and authorization mechanisms, including role-based access
control, password hashing, and account lockout policies. Additionally, the
system adheres to OWASP guidelines to mitigate common vulnerabilities
such as SQL injection, cross-site scripting (XSS), and cross-site request forgery
(CSRF). These security features ensure that both job seekers and employers
can interact with the platform confidently, knowing their sensitive
information is safeguarded. The use of HTTPS, anti-forgery tokens, and data
encryption further reinforces the system's resilience against potential
threats.
From a user experience perspective, the platform offers a responsive and
dynamic interface powered by Razor Pages, Bootstrap 5, and jQuery.
Features such as real-time job postings, application tracking, and admin
dashboards enhance usability and engagement. The modular design of the
frontend, including reusable View Components, ensures consistency across
the application while minimizing redundancy. On the backend, Entity
Framework Core facilitates efficient data access and management, with
SQLite serving as the development database and SQL Server earmarked for
production environments to handle larger datasets and higher traffic
volumes. The inclusion of Swagger documentation streamlines API testing
and integration, making the system accessible to third-party developers.
Looking ahead, the Job Portal System is well-positioned for future
enhancements, including AI-driven job matching algorithms, WebSocket-
PAGE 26
based real-time notifications, and OAuth2 integration for seamless third-
party authentication. Performance optimizations such as Redis caching and
GraphQL endpoints are also planned to further improve scalability and
responsiveness. The system's CI/CD pipeline, configured via GitHub Actions
and Docker, ensures smooth deployments and continuous integration,
reducing downtime and accelerating feature rollouts.
In conclusion, this project not only meets the immediate needs of job seekers
and employers but also establishes a flexible foundation for long-term
growth and innovation. By combining best practices in software architecture,
security, and user experience, the Advanced Job Portal System sets a new
standard for recruitment platforms, offering reliability, efficiency, and
scalability. The lessons learned and technologies employed during its
development serve as a valuable blueprint for future projects, demonstrating
the power of modern .NET ecosystems in building enterprise-grade
applications. With ongoing updates and community feedback, the platform
will continue to evolve, further solidifying its role as a vital tool in the evolving
job market landscape.
PAGE 27