ASP.NET Core  

AI-Powered Job Portal with Resume Matching

A Complete End-to-End Guide for Building Intelligent Recruitment Applications using Angular, ASP.NET Core, SQL Server, and AI Models

Introduction

Recruitment is one of the biggest challenges for companies today. HR teams receive thousands of job applications for each position. Manually reading, filtering, and scoring resumes is slow, expensive, and often inconsistent. Most traditional job portals only allow keyword search or basic filtering, which does not help in identifying the right candidates.

This is where AI-powered resume matching comes in. Modern machine learning (ML) models can:

  • Extract skills, experience, and job roles from resumes

  • Match candidate profiles with job descriptions

  • Score and rank applicants

  • Highlight skill gaps

  • Recommend other suitable roles

  • Reduce manual screening time

This article is a complete guide on building a production-ready AI-powered job portal using:

  • SQL Server (data storage and optional ML)

  • ASP.NET Core (backend APIs)

  • Angular (frontend UI)

  • Python ML Models / Azure AI / OpenAI Embeddings (resume matching)

It is written for beginner to senior-level developers who want to implement intelligent job-matching features in real-world applications.

1. Understanding AI-Powered Resume Matching

Resume matching uses artificial intelligence to match candidates with jobs. It involves three core steps:

1. Parsing

Extracting structured information from resumes:

  • Name

  • Education

  • Skills

  • Experience

  • Certifications

2. Embedding

Converting text into numeric vectors using:

  • OpenAI Text Embeddings

  • BERT / Sentence-BERT

  • Azure Cognitive Search Embeddings

  • HuggingFace models

3. Matching

Computing similarity between:

  • Candidate resume vector

  • Job description vector

The most common method is cosine similarity, which gives a score between 0 and 1.

2. High-Level Architecture

A scalable AI job portal looks like this:

Angular UI
    ↓
ASP.NET Core API
    ↓
SQL Server (Candidates, Jobs, Embeddings)
    ↓
Python ML Service or AI Embedding API
    ↓
Matching Engine (Similarity Scoring)

Angular handles UI, search, dashboards, and recommendations.
ASP.NET Core manages the APIs.
SQL Server stores job listings, resume content, and embedding vectors.
AI service performs feature extraction and matching.

3. Data Model for Resume Matching

You need at least three tables:

3.1 Candidate Table

CREATE TABLE Candidates (
    CandidateId INT IDENTITY PRIMARY KEY,
    FullName NVARCHAR(200),
    Email NVARCHAR(200),
    ResumeText NVARCHAR(MAX),
    Skills NVARCHAR(MAX),
    ExperienceYears INT,
    Embedding VARBINARY(MAX)
);

3.2 Job Table

CREATE TABLE Jobs (
    JobId INT IDENTITY PRIMARY KEY,
    JobTitle NVARCHAR(200),
    Description NVARCHAR(MAX),
    RequiredSkills NVARCHAR(MAX),
    MinExperience INT,
    Embedding VARBINARY(MAX)
);

3.3 Match Results Table

CREATE TABLE MatchResults (
    ResultId INT IDENTITY PRIMARY KEY,
    CandidateId INT,
    JobId INT,
    Score FLOAT,
    MatchedOn DATETIME DEFAULT GETDATE()
);

4. Resume Parsing

Resumes may come as:

  • PDF

  • Word

  • Text

  • JSON

You need a parser to extract text. You can integrate:

  • Tika Server

  • Python PyPDF2

  • Azure Form Recognizer

Example API workflow:

Upload Resume → Parse Text → Extract Skills → Save in DB → Generate Embedding → Store Vector

Simple Python-based text extraction example:

import PyPDF2

def extract_text_from_pdf(file_path):
    reader = PyPDF2.PdfReader(file_path)
    text = ""
    for page in reader.pages:
        text += page.extract_text()
    return text

Extract skills using regex or NLP:

skills = extract_skills(text)

Save data into the SQL Server using ASP.NET Core.

5. Generating Embeddings for Jobs and Resumes

You can use:

Option A: OpenAI Embeddings (Recommended)

Models like text-embedding-3-large.

Option B: Sentence-BERT (Local Model)

Option C: Azure OpenAI

Example C# API call to generate embeddings:

public async Task<float[]> GenerateEmbedding(string text)
{
    var client = new OpenAIClient(apiKey);

    var response = await client.Embeddings.CreateAsync(new EmbeddingsCreateRequest
    {
        Model = "text-embedding-3-large",
        Input = text
    });

    return response.Data[0].Embedding.ToArray();
}

Store vectors as VARBINARY:

byte[] binaryVector = MemoryMarshal.AsBytes<float>(embedding.AsSpan()).ToArray();

Save into SQL:

UPDATE Candidates SET Embedding = @Embedding WHERE CandidateId = @Id;

6. Matching Engine (Cosine Similarity)

Matching involves comparing vectors:

from numpy import dot
from numpy.linalg import norm

def cosine_similarity(a, b):
    return dot(a, b)/(norm(a)*norm(b))

Score ranges:

  • Above 0.75 → Strong match

  • 0.60–0.75 → Medium match

  • Below 0.60 → Weak match

7. ASP.NET Core API for Resume Matching

7.1 API: Match a Candidate to Jobs

[HttpGet("match-candidate/{id}")]
public async Task<IActionResult> MatchCandidate(int id)
{
    var candidate = await _context.Candidates.FindAsync(id);
    var jobs = await _context.Jobs.ToListAsync();

    var candidateEmbedding = ByteArrayToFloat(candidate.Embedding);

    var results = new List<JobMatchResult>();

    foreach(var job in jobs)
    {
        var jobEmbedding = ByteArrayToFloat(job.Embedding);
        var score = CosineSimilarity(candidateEmbedding, jobEmbedding);

        results.Add(new JobMatchResult
        {
            JobId = job.JobId,
            JobTitle = job.JobTitle,
            Score = score
        });
    }

    return Ok(results.OrderByDescending(r => r.Score));
}

Utility converters:

private float[] ByteArrayToFloat(byte[] bytes)
{
    return MemoryMarshal.Cast<byte, float>(bytes).ToArray();
}

private double CosineSimilarity(float[] a, float[] b)
{
    double dot = 0, normA = 0, normB = 0;

    for(int i=0;i<a.Length;i++)
    {
        dot += a[i] * b[i];
        normA += a[i] * a[i];
        normB += b[i] * b[i];
    }

    return dot / (Math.Sqrt(normA) * Math.Sqrt(normB));
}

8. Angular Integration

8.1 Angular Service

job-matching.service.ts

@Injectable({ providedIn: 'root' })
export class JobMatchingService {

  constructor(private http: HttpClient) {}

  getMatchesForCandidate(id: number): Observable<JobMatchResult[]> {
    return this.http.get<JobMatchResult[]>(`/api/matching/match-candidate/${id}`);
  }
}

export interface JobMatchResult {
  jobId: number;
  jobTitle: string;
  score: number;
}

8.2 Angular Component

candidate-matches.component.ts

@Component({
  selector: 'app-candidate-matches',
  templateUrl: './candidate-matches.component.html'
})
export class CandidateMatchesComponent implements OnInit {

  displayedColumns = ['jobTitle', 'score'];
  dataSource = new MatTableDataSource<JobMatchResult>();

  constructor(private service: JobMatchingService) {}

  ngOnInit() {
    this.service.getMatchesForCandidate(1).subscribe(res => {
      this.dataSource.data = res;
    });
  }
}

HTML template:

<mat-card>
  <h2>Top Job Matches</h2>

  <table mat-table [dataSource]="dataSource">
    <ng-container matColumnDef="jobTitle">
      <th mat-header-cell *matHeaderCellDef> Job Title </th>
      <td mat-cell *matCellDef="let row">{{ row.jobTitle }}</td>
    </ng-container>

    <ng-container matColumnDef="score">
      <th mat-header-cell *matHeaderCellDef> Score </th>
      <td mat-cell *matCellDef="let row">{{ row.score | number:'1.0-3' }}</td>
    </ng-container>

    <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
    <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
  </table>
</mat-card>

9. Recommended AI Enhancements

9.1 Skill Gap Analysis

Identify missing skills compared to job requirements.

9.2 Job Recommendations

Recommend alternative jobs if match score is low.

9.3 Candidate Ranking

Rank candidates for each job.

9.4 Resume Summarization

Use LLMs to generate:

  • Profile summary

  • Skill summary

  • Experience summary

9.5 Interview Question Generation

Automatically prepare questions based on job skills.

10. Candidate Dashboard (Angular)

A modern candidate dashboard includes:

  • Upload resume

  • View parsed resume data

  • View skill extraction

  • See top job matches

  • Track application status

You can build this with:

  • Angular Material

  • MatTable

  • MatStepper

  • MatCard

  • NgCharts

11. HR Dashboard (Angular)

HR dashboard shows:

  • Candidate ranking

  • Resume comparison

  • Job posting management

  • AI insights

  • Matching scores

  • Skill gap distribution charts

Use Angular Material and charts for this.

12. Performance Considerations

  1. Do not compute embeddings repeatedly. Store vectors.

  2. Vector size is large. Use VARBINARY(MAX) and store compressed.

  3. Use batch matching.

  4. Cache results.

  5. Use async operations for prediction APIs.

  6. Offload ML computation to background workers.

13. Security and Compliance

  • Encrypt resumes in storage

  • Remove personal data before embedding

  • Use secure HTTPS connections

  • Restrict access to HR-only APIs

  • Log AI decisions for transparency

14. Scaling the System

To scale an AI job portal:

Option A: Microservices

Separate:

  • Resume parsing

  • Embedding generation

  • Matching service

  • Notification service

Option B: Vector Databases

Use:

  • Pinecone

  • Qdrant

  • Azure Cognitive Search Vector Store

Option C: Distributed Processing

Use workers for handling bulk resumes.

15. Deployment Strategy

Deployment Sequence

  1. SQL Server on Azure or on-prem

  2. ASP.NET Core on Azure App Service

  3. Angular app on Static Web App or App Service

  4. ML microservice on Azure Container Apps

  5. Background jobs on Azure Functions

Conclusion

Building an AI-powered job portal with resume matching is not only achievable but highly practical for modern businesses. With the right integration of SQL Server, ASP.NET Core, Angular, and AI models, you can deliver a system that:

  • Reads and understands resumes

  • Extracts important skills

  • Generates embeddings for powerful text matching

  • Compares candidates and jobs using cosine similarity

  • Ranks applicants based on fit

  • Provides dashboards for HR teams and candidates

  • Automates a major part of recruitment

This guide walked through:

  • Data modeling

  • Resume parsing

  • Embedding generation

  • Matching logic

  • ASP.NET Core APIs

  • Angular UI implementation

  • System architecture

  • AI enhancements

  • Performance and security best practices

With these building blocks, you can deliver a real, production-grade job matching solution.