ASP.NET Core  

Building AI-Powered Personalized Learning Dashboards with Angular and ASP.NET Core

In the modern e-learning ecosystem, personalized dashboards have become a necessity. Students, trainers, and administrators want tailored insights—like progress tracking, suggested courses, and learning analytics. By integrating AI models, these dashboards can recommend courses, identify weak areas, and even predict student performance.

This article will guide you step by step to build a production-ready AI-powered personalized learning dashboard using:

  • Angular for frontend

  • ASP.NET Core Web API for backend

  • ML/AI services for recommendations and analytics

We will focus on dynamic dashboards, personalization, data persistence, and scalability.

1. Understanding the System Architecture

A modern AI-powered learning dashboard has three main layers:

1. Frontend (Angular)

  • Displays widgets like Course Progress, Recommended Lessons, Performance Graphs

  • Sends user actions and feedback to the backend

  • Supports dynamic widgets and drag-drop layouts

2. Backend (ASP.NET Core)

  • Serves API endpoints for user data, courses, and analytics

  • Integrates AI/ML models to generate recommendations

  • Stores user preferences and dashboard layout

3. AI Service / Machine Learning

  • Recommends courses or content using collaborative filtering or content-based models

  • Predicts student performance based on historical activity

  • Suggests skill gaps and next learning steps

High-Level Flow

User -> Angular Frontend -> ASP.NET Core API -> AI/ML Service
         <- Response <-                 <- Predictions/Recommendations

2. Project Setup

Step 1: Create Backend Project

dotnet new webapi -n LearningDashboardAPI
cd LearningDashboardAPI

Step 2: Install Required Packages

For ML.NET recommendations or predictive models:

dotnet add package Microsoft.ML
dotnet add package Microsoft.ML.Recommender

For AI/ML API integration:

dotnet add package System.Net.Http.Json

Step 3: Create Models

Models/UserDashboard.cs

public class UserDashboard
{
    public string UserId { get; set; } = string.Empty;
    public List<WidgetConfig> Widgets { get; set; } = new List<WidgetConfig>();
}

Models/WidgetConfig.cs

public class WidgetConfig
{
    public string Id { get; set; } = Guid.NewGuid().ToString();
    public string Type { get; set; } = string.Empty; // progress, recommendations, charts
    public string Title { get; set; } = string.Empty;
    public int PositionX { get; set; }
    public int PositionY { get; set; }
    public int Width { get; set; } = 300;
    public int Height { get; set; } = 250;
}

Models/CourseRecommendation.cs

public class CourseRecommendation
{
    public string CourseId { get; set; } = string.Empty;
    public string CourseName { get; set; } = string.Empty;
    public double Score { get; set; }
}

3. AI-Based Recommendation Service

Step 1: Using ML.NET Collaborative Filtering

using Microsoft.ML;
using Microsoft.ML.Trainers;

public class RecommendationService
{
    private MLContext _mlContext;
    private ITransformer? _model;

    public RecommendationService()
    {
        _mlContext = new MLContext();
        TrainModel();
    }

    private void TrainModel()
    {
        // Sample: user-course interactions
        var data = _mlContext.Data.LoadFromTextFile<UserCourseData>("Data/UserCourses.csv", hasHeader: true, separatorChar: ',');
        var pipeline = _mlContext.Recommendation().Trainers.MatrixFactorization(
            new MatrixFactorizationTrainer.Options
            {
                MatrixColumnIndexColumnName = nameof(UserCourseData.UserId),
                MatrixRowIndexColumnName = nameof(UserCourseData.CourseId),
                LabelColumnName = nameof(UserCourseData.Rating),
                NumberOfIterations = 20,
                ApproximationRank = 100
            });

        _model = pipeline.Fit(data);
    }

    public float PredictRating(int userId, int courseId)
    {
        if (_model == null) return 0;

        var predictionEngine = _mlContext.Model.CreatePredictionEngine<UserCourseData, CourseRatingPrediction>(_model);
        return predictionEngine.Predict(new UserCourseData { UserId = userId, CourseId = courseId }).Score;
    }
}

Models/UserCourseData.cs

public class UserCourseData
{
    public int UserId { get; set; }
    public int CourseId { get; set; }
    public float Rating { get; set; }
}

public class CourseRatingPrediction
{
    public float Score { get; set; }
}

Step 2: Expose Recommendations via API

[ApiController]
[Route("api/[controller]")]
public class RecommendationsController : ControllerBase
{
    private readonly RecommendationService _recommendationService;

    public RecommendationsController(RecommendationService recommendationService)
    {
        _recommendationService = recommendationService;
    }

    [HttpGet("{userId}")]
    public IActionResult GetRecommendations(int userId)
    {
        var recommendedCourses = new List<CourseRecommendation>();
        for (int courseId = 1; courseId <= 10; courseId++)
        {
            recommendedCourses.Add(new CourseRecommendation
            {
                CourseId = courseId.ToString(),
                CourseName = $"Course {courseId}",
                Score = _recommendationService.PredictRating(userId, courseId)
            });
        }

        var sorted = recommendedCourses.OrderByDescending(c => c.Score).ToList();
        return Ok(sorted);
    }
}

4. Backend: Dashboard Persistence

Services/DashboardService.cs

public class DashboardService
{
    private readonly Dictionary<string, UserDashboard> _store = new();

    public UserDashboard GetDashboard(string userId)
    {
        if (!_store.ContainsKey(userId))
            _store[userId] = new UserDashboard { UserId = userId };

        return _store[userId];
    }

    public void SaveDashboard(UserDashboard dashboard)
    {
        _store[dashboard.UserId] = dashboard;
    }
}

In production, replace this with database persistence (SQL Server, MongoDB, etc.)

5. Angular Frontend

Step 1: Generate Angular Project

ng new learning-dashboard --routing --style=scss
cd learning-dashboard
ng serve

Step 2: Create Models

src/app/models/widget.model.ts

export interface WidgetConfig {
  id: string;
  type: string;
  title: string;
  positionX: number;
  positionY: number;
  width: number;
  height: number;
}

src/app/models/course-recommendation.model.ts

export interface CourseRecommendation {
  courseId: string;
  courseName: string;
  score: number;
}

Step 3: Services

src/app/services/dashboard.service.ts

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
import { WidgetConfig } from '../models/widget.model';
import { CourseRecommendation } from '../models/course-recommendation.model';

@Injectable({ providedIn: 'root' })
export class DashboardService {
  private apiUrl = 'https://localhost:5001/api';

  constructor(private http: HttpClient) {}

  getUserDashboard(userId: string): Observable<WidgetConfig[]> {
    return this.http.get<WidgetConfig[]>(`${this.apiUrl}/dashboard/${userId}`);
  }

  saveUserDashboard(dashboard: WidgetConfig[]): Observable<any> {
    return this.http.post(`${this.apiUrl}/dashboard/save`, dashboard);
  }

  getRecommendations(userId: string): Observable<CourseRecommendation[]> {
    return this.http.get<CourseRecommendation[]>(`${this.apiUrl}/recommendations/${userId}`);
  }
}

Step 4: Dashboard Component

src/app/components/dashboard/dashboard.component.ts

import { Component, OnInit } from '@angular/core';
import { DashboardService } from '../../services/dashboard.service';
import { WidgetConfig } from '../../models/widget.model';
import { CourseRecommendation } from '../../models/course-recommendation.model';

@Component({
  selector: 'app-dashboard',
  templateUrl: './dashboard.component.html',
  styleUrls: ['./dashboard.component.scss']
})
export class DashboardComponent implements OnInit {
  widgets: WidgetConfig[] = [];
  recommendations: CourseRecommendation[] = [];
  userId = '123';

  constructor(private dashboardService: DashboardService) {}

  ngOnInit(): void {
    this.loadDashboard();
    this.loadRecommendations();
  }

  loadDashboard(): void {
    this.dashboardService.getUserDashboard(this.userId).subscribe(w => this.widgets = w);
  }

  loadRecommendations(): void {
    this.dashboardService.getRecommendations(this.userId).subscribe(r => this.recommendations = r);
  }

  saveDashboard(): void {
    this.dashboardService.saveUserDashboard(this.widgets).subscribe();
  }
}

Step 5: Dashboard Template

dashboard.component.html

<div class="dashboard-container">
  <div class="widgets">
    <div *ngFor="let widget of widgets" class="widget-box" [style.width.px]="widget.width" [style.height.px]="widget.height">
      <h3>{{ widget.title }}</h3>
      <ng-container [ngSwitch]="widget.type">
        <div *ngSwitchCase="'recommendations'">
          <ul>
            <li *ngFor="let rec of recommendations">{{ rec.courseName }} (Score: {{ rec.score | number:'1.1-2' }})</li>
          </ul>
        </div>
        <div *ngSwitchDefault>Widget content here</div>
      </ng-container>
    </div>
  </div>
  <button (click)="saveDashboard()">Save Dashboard</button>
</div>

6. AI-Powered Personalization Logic

  1. Course Recommendation Widget

    • Uses collaborative filtering ML.NET model

    • Fetches recommended courses based on user interaction

  2. Progress Widget

    • Tracks course completion percentage

    • Shows personalized progress graph

  3. Skill Gap Widget

    • Uses ML prediction to identify weak topics

    • Suggests courses to fill gaps

  4. Dynamic Widget Management

    • Angular can support drag-drop layout

    • Persist widget positions and types in backend

7. Best Practices

  1. Backend AI Service Separation: Keep AI/ML logic separate from API controllers.

  2. Caching: Cache recommendations for frequent queries.

  3. Security: Authenticate API endpoints; prevent unauthorized access to personalized dashboards.

  4. Persistence: Use databases for dashboard layout and user interaction history.

  5. Scalability: Use async processing or queue-based systems for heavy AI tasks.

  6. Observability: Log dashboard metrics, recommendation usage, and AI model latency.

  7. Front-end UX: Use loading indicators when recommendations are being fetched.

8. Folder Structure

LearningDashboardAPI/
  Controllers/
    DashboardController.cs
    RecommendationsController.cs
  Models/
    UserDashboard.cs
    WidgetConfig.cs
    CourseRecommendation.cs
    UserCourseData.cs
  Services/
    RecommendationService.cs
    DashboardService.cs
  Data/
    UserCourses.csv
AngularApp/
  src/app/
    components/
      dashboard/
        dashboard.component.ts
        dashboard.component.html
        dashboard.component.scss
    services/
      dashboard.service.ts
    models/
      widget.model.ts
      course-recommendation.model.ts

9. Conclusion

By combining Angular and ASP.NET Core with AI-powered ML models, you can build dynamic personalized learning dashboards that adapt to each user. Key benefits include:

  • Personalized course recommendations

  • Progress tracking and analytics

  • Skill gap identification

  • Dynamic widgets with drag-drop and persistence

This architecture is scalable, maintainable, and production-ready, making it suitable for:

  • Online learning platforms

  • Corporate training systems

  • EdTech SaaS applications

  • Student performance analytics portals

This sets up a full-stack personalized AI dashboard with clear separation between frontend, backend, and AI services.