[Route("api/[controller]")]
[ApiController]
public class QuizzController : ControllerBase
{
private readonly ApplicationDbContext _context;
public QuizzController(ApplicationDbContext context)
{
_context = context;
}
// ===============================
// CLAIM HELPERS (FAST)
// ===============================
private string CurrentUserName =>
User.Identity?.Name ?? "System";
private int CurrentDepartmentId =>
int.TryParse(
User.FindFirstValue("DepartmentId"),
out var id)
? id
: 0;
// List all available tests
public async Task Index()
{
var tests = await _context.Tests.ToListAsync();
return Ok(tests);
} //Maybe this action result needs @model IEnumerable
//public IActionResult QuizList()
//{
// var quiz = _context.Questions.Include(x => x.Answers)
// .Select(q => new
// {
// QuestionText = q.Text,
// Answers = q.Answers.Select(a => new SelectListItem(a.Text, a.Id.ToString())).ToList()
// }).ToList();
// return View(quiz);
//}
// Show quiz by TestId
public async Task Take(int id)
{
var test = await _context.Tests
.Include(x => x.Questions)
.ThenInclude(x => x.Answers)
.FirstOrDefaultAsync(x => x.Id == id);
if (test == null)
return NotFound();
return Ok(test);
}
// Handle quiz submission and store attempt
[HttpPost]
public async Task Submit(int testId, int[] selectedOptions)
{
var questions = await _context.Question
.Include(q => q.Answers)
.Where(q => q.TestId == testId)
.ToListAsync();
int score = 0;
var attempt = new TestAttempt
{
UserId = CurrentUserName,
TestId = testId,
AttemptDate = DateTime.UtcNow
};
foreach (var question in questions)
{
var correctOption = question.Answers.FirstOrDefault(o => o.IsCorrect);
var selectedOptionId = selectedOptions.FirstOrDefault(o => question.Answers.Any(opt => opt.Id == o));
bool isCorrect = correctOption != null && selectedOptionId == correctOption.Id;
if (isCorrect) score++;
attempt.Answers.Add(new UserAnswer
{
QuestionId = question.Id,
AnswerId = selectedOptionId,
IsCorrect = isCorrect
});
}
attempt.Score = score;
attempt.IsPassed = score >= questions.Count / 2; // replace with your real pass threshold
_context.TestsAttempt.Add(attempt);
await _context.SaveChangesAsync();
return RedirectToAction("History", new { userId = CurrentUserName });
}
// Show attempt history for a user
public async Task History()
{
var attempts = await _context.TestsAttempt
.Include(a => a.Test)
.Where(a => a.UserId == CurrentUserName)
.OrderByDescending(a => a.AttemptDate)
.ToListAsync();
return Ok(attempts);
}
public async Task Details(int id)
{
var attempt = await _context.TestsAttempt
.Include(a => a.Test)
.Include(a => a.Answers)
.ThenInclude(ua => ua.Question)
.ThenInclude(q => q.Answers)
.Include(a => a.Answers)
.ThenInclude(ua => ua.Answer)
.FirstOrDefaultAsync(a => a.Id == id);
if (attempt == null)
return NotFound();
return Ok(attempt);
}
} I want populate test in angular where users can take, submit tests, and see their scoresLoading
Niharika GuptaPosted Sep 28, 2026, 8:30 AM
Yes, you can handle the complete flow with Angular + ASP.NET Core Web API. The API should return JSON rather than MVC redirects/views.
A simple approach is:
Tests API → Angular test list → Take test → Submit answers → Return score → Show history
A few changes are needed in your controller. For example, use
ActionResult/IActionResult:For submission, I'd recommend sending a request model from Angular instead of using
int[] selectedOptions:Then your API can return the result directly:
In Angular, you can then have:
The Angular screens could be kept simple:
Test List – display available tests with a Take Test button.
Take Test – display questions and answer options using radio buttons.
Submit Test – send the selected answers to the API.
Result – show score, total questions, and pass/fail status.
My History – show previous attempts and scores.
One important point: don't send
IsCorrectto Angular or trust the submitted score. The correct answers should remain on the server, and the API should calculate the score during submission. This prevents users from manipulating the result.