ASP.NET problem with saving quizzes to a SQL database

Bartek Kowalczyk 0 Reputation points
2023-11-06T22:20:17.3766667+00:00

I have a problem with my application namely I want to create the possibility to create dynamic quizzes. Currently I have a problem related to saving the created quiz with questions to the database.

No matter if I want to create a new one or edit the one default one it is not sent to the database. According to me the problem must lie in the controller or in the js code in the Upsert file, but I can't tell where.Please help

My models - Quiz:

public class Quiz
{
    [Key]
    public int Id { get; set; }
    [DisplayName("Tytuł")]
    [Required]
    public string Title { get; set; }
    
    [DisplayName("Dział")]
    public int SectionId { get; set; }
    [ForeignKey("SectionId")]
    [ValidateNever]
    public Section Section { get; set; }

    public List<Question> Questions { get; set; }
}

Question:

public class Question
{
    [Key]
    public int Id {  get; set; }
    [Required]
    [DisplayName("Pytanie")]
    public string QuestionText { get; set; }
    [Required]
    [DisplayName("Odpowiedź 1")]
    public string Answer1 { get; set; }
    [Required]
    [DisplayName("Odpowiedź 2")]
    public string Answer2 { get; set; }
    [Required]
    [DisplayName("Odpowiedź 3")]
    public string Answer3 { get; set; }
    [Required]
    [DisplayName("Odpowiedź 4")]
    public string Answer4 { get; set; }
    public int IsCorrect { get; set; }

    [DisplayName("Quiz")]
    public int QuizId { get; set; }
    [ForeignKey("QuizId")]
    [ValidateNever]
    public Quiz Quiz { get; set; }
}

QuizVM:

public class QuizVM
{ 
    public Quiz Quiz { get; set; }

    [ValidateNever]
    public IEnumerable<SelectListItem> SectionList { get; set; }

    public List<Question> Questions { get; set; }
}

My index view:

@model List<Quiz>

<div class="card shadow border-0 mt-4">
    <div class="card-header bg-secondary bg-gradient ml-0 py-3">
        <div class="row">
            <div class="col-12 text-center">
                <h2 class="text-white py-2">List Quizów</h2>
            </div>
        </div>
    </div>
    <div class="card-body p-4">
        <div class="row pb-3">
            <div class="col-6">
            </div>
            <div class="col-6 text-end">
                <a asp-controller="Quiz" asp-action="Upsert" class="btn btn-primary">
                    <i class="bi bi-plus-circle"></i> Add new Quiz
                </a>
            </div>
        </div>

        <table id="tblData" class="table table-bordered table-striped" style="width:100%">
            <thead>
                <tr>
                    <th>Title</th>
                    <th>Section</th>
                    <th></th>
                </tr>
            </thead>
        </table>
    </div>
</div>

@section Scripts {
    <script src="~/js/QuizCreate.js"></script>
}

Upsert:

@model QuizVM
<h2>Create Quiz</h2>

<form asp-action="Upsert" method="post">
    <div class="form-group">
        <label asp-for="Quiz.Title" class="control-label"></label>
        <input asp-for="Quiz.Title" class="form-control" />
        <span asp-validation-for="Quiz.Title" class="text-danger"></span>
    </div>

    <div class="form-floating py-2 col-12">
        <select asp-for="Quiz.SectionId" asp-items="@Model.SectionList" class="form-select border-0 shadow">
            <option disabled selected>---Wybierz Dział---</option>
        </select>
        <label asp-for="Quiz.SectionId" class="ms-2"></label>
        <span asp-validation-for="Quiz.SectionId" class="text-danger"></span>
    </div>

    <div id="questionsContainer">
        @for (var questionCounter = 0; questionCounter < Model.Questions.Count; questionCounter++)
        {
            <div class="question-container">
                <h4>Pytanie @questionCounter</h4>

                <div class="form-group">
                    <label asp-for="Questions[questionCounter].QuestionText" class="control-label">Question Text</label>
                    <input asp-for="Questions[questionCounter].QuestionText" class="form-control" />
                </div>

                <div class="form-group">
                    <label>Odpowiedzi</label>
                    <input asp-for="Questions[questionCounter].Answer1" class="form-control" />
                    <input asp-for="Questions[questionCounter].Answer2" class="form-control" />
                    <input asp-for="Questions[questionCounter].Answer3" class="form-control" />
                    <input asp-for="Questions[questionCounter].Answer4" class="form-control" />
                </div>

                <div class="form-group">
                    <label asp-for="Questions[questionCounter].IsCorrect" class="control-label">Correct Answer</label>
                    <select asp-for="Questions[questionCounter].IsCorrect" class="form-select">
                        <option value="1">Answer 1</option>
                        <option value="2">Answer 2</option>
                        <option value="3">Answer 3</option>
                        <option value="4">Answer 4</option>
                    </select>
                </div>
            </div>
        }
    </div>

    <button type="button" id="addQuestionBtn" class="btn btn-success">Add Question</button>

    <div class="row pt-2">
        <div class="row pt-2">
            <div class="col-6 col-md-3">
                @if (Model.Quiz.Id != 0)
                {
                    <button type="submit" class="btn btn-primary form-control">Update</button>
                }
                else
                {
                    <button type="submit" class="btn btn-primary form-control">Create</button>
                }
            </div>
        <div class="col-6 col-md-3">
            <a asp-controller="Quiz" asp-action="Index" class="btn btn-secondary border form-control">Back to List</a>
        </div>
    </div>
</form>

@section Scripts {
    <script>
        var questionCounter = @Model.Questions.Count;

        $("#addQuestionBtn").click(function () {
            var questionHtml = '<div class="question-container">';
            questionHtml += '<h4>Question ' + (questionCounter + 1) + '</h4>';
            questionHtml += '<div class="form-group">';
            questionHtml += '<label>Question Text</label>';
            questionHtml += '<input type="text" name="Questions[' + questionCounter + '].QuestionText" class="form-control" />';
            questionHtml += '</div';

            questionHtml += '<div class="form-group">';
            questionHtml += '<label>Answer</label>';
            questionHtml += '<input type="text" name="Questions[' + questionCounter + '].Answer1" class="form-control" />';
            questionHtml += '<input type="text" name="Questions[' + questionCounter + '].Answer2" class="form-control" />';
            questionHtml += '<input type="text" name="Questions[' + questionCounter + '].Answer3" class="form-control" />';
            questionHtml += '<input type="text" name="Questions[' + questionCounter + '].Answer4" class="form-control" />';
            questionHtml += '</div>';

            questionHtml += '<div class="form-group">';
            questionHtml += '<label>Correct Answer</label>';
            questionHtml += '<select name="Questions[' + questionCounter + '].IsCorrect" class="form-control">';
            questionHtml += '<option value="1">Answer 1</option>';
            questionHtml += '<option value="2">Answer 2</option>';
            questionHtml += '<option value="3">Answer 3</option>';
            questionHtml += '<option value="4">Answer 4</option>';
            questionHtml += '</select>';
            questionHtml += '</div>';

            questionHtml += '</div>';

            $("#questionsContainer").append(questionHtml);
            questionCounter++;
        });

            function GetAnswerOptions() {
                var options = [];
                for (var i = 1; i <= 4; i++) {
                    options.push({ text: i.toString(), value: i.toString() });
                }
                return options;
            }
    
    </script>
}

And QuizController:

[Area("Admin")]
[Authorize(Roles = SD.Role_Admin)]
public class QuizController : Controller
{
    private readonly IUnitOfWork _unitOfWork;
    private readonly ILogger<QuizController> _logger;

    public QuizController(IUnitOfWork unitOfWork, ILogger<QuizController> logger)
    {
        _unitOfWork = unitOfWork;
        _logger = logger;
    }

    public IActionResult Index()
    {
        List<Quiz> objQuizlsList = _unitOfWork.Quiz.GetAll(includeProperties: "Section").ToList();

        return View(objQuizlsList);
    }

    public IActionResult Upsert(int? id)
    {
        QuizVM quizVM = new()
        {
            SectionList = _unitOfWork.Section.GetAll().Select(u => new SelectListItem
            {
                Text = u.Title,
                Value = u.Id.ToString()
            }),
            Quiz = new Quiz(),
            Questions = new List<Question>()
        };

        if (id == null || id == 0)
        {
            return View(quizVM);
        }
        else
        {
            // Edit quiz
            quizVM.Quiz = _unitOfWork.Quiz.Get(u => u.Id == id);
            // Get question from quiz
            quizVM.Questions = _unitOfWork.Question.GetAll().Where(q => q.QuizId == id).ToList();
            return View(quizVM);
        }
    }

    [HttpPost]
    public IActionResult Upsert(QuizVM quizVM)
    {
        if (ModelState.IsValid)
        {
            if (quizVM.Quiz.Id == 0)
            {
                // add new quiz
                _unitOfWork.Quiz.Add(quizVM.Quiz);
                _unitOfWork.Save(); // save changes to generate the id for the quiz

                //add question
                foreach (var question in quizVM.Questions)
                {
                    question.QuizId = quizVM.Quiz.Id;
                    _unitOfWork.Question.Add(question);
                }

                _unitOfWork.Save();
            }
            else
            {
                // Update quiz
                _unitOfWork.Quiz.Update(quizVM.Quiz);

                // Update question
                var existingQuestions = _unitOfWork.Question.GetAll().Where(q => q.QuizId == quizVM.Quiz.Id).ToList();

                foreach (var question in existingQuestions)
                {
                    _unitOfWork.Question.Remove(question);
                }

                foreach (var question in quizVM.Questions)
                {
                    question.QuizId = quizVM.Quiz.Id;
                    _unitOfWork.Question.Add(question);
                }
            }

            _unitOfWork.Save();

            TempData["success"] = "Quiz created successfully";

            return RedirectToAction("Index");
        }
        else
        {
            //Back list
            quizVM.SectionList = _unitOfWork.Section.GetAll().Select(u => new SelectListItem
            {
                Text = u.Title,
                Value = u.Id.ToString()
            });

            return View(quizVM);
        }
    }

    #region API CALLS
    [HttpGet]
    public IActionResult GetAll()
    {
        List<Quiz> objQuizList = _unitOfWork.Quiz.GetAll(includeProperties: "Section").ToList();
        return Json(new { data = objQuizList });
    }

    [HttpDelete]
    public IActionResult Delete(int? id)
    {
        var QuizToBeDeleted = _unitOfWork.Quiz.Get(u => u.Id == id);
        if (QuizToBeDeleted == null)
        {
            return Json(new { success = false, message = "Error while deleting" });
        }

        _unitOfWork.Quiz.Remove(QuizToBeDeleted);
        _unitOfWork.Save();

        return Json(new { success = true, message = "Delete Successful" });
    }
    #endregion
}
Entity Framework Core
Entity Framework Core
A lightweight, extensible, open-source, and cross-platform version of the Entity Framework data access technology.
741 questions
ASP.NET Core
ASP.NET Core
A set of technologies in the .NET Framework for building web applications and XML web services.
4,553 questions
SQL Server
SQL Server
A family of Microsoft relational database management and analysis systems for e-commerce, line-of-business, and data warehousing solutions.
13,784 questions
{count} votes

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.