I want to create a Quiz, add questions to the quiz, and add answers to the question. I bound all items with asp-for, serialize my form, and send it to the controller, but they don't bind.
My classes:
public class Answer
{
[Key]
public Guid Id { get; } = Guid.NewGuid();
public string Content { get; set; }
public Guid QuestionId { get; set; }
}
public class Question
{
[Key]
public Guid Id { get; } = Guid.NewGuid();
public string Content { get; set; }
public Guid QuizId { get; set; }
public ICollection<Answer> Answers { get; set; } = new List<Answer>() {
new Answer() { Content = "Answeeeer" },
new Answer() { Content = "Answeeeer2" },
new Answer() { Content = "Answeeeer3" }
};
}
public class Quiz
{
[Key]
public Guid Id { get; } = Guid.NewGuid();
public string Name { get; set; }
public ICollection<Question> Questions { get; set; } = new List<Question>() { };
}
Quiz view:
@model QuizIt_Tests.Entities.Quiz
@{
ViewData\["Title"\] = "Create";
}
\<h1\>Create\</h1\>
\<h4\>Quiz\</h4\>
\<hr /\>
\<div \>
\<div \>
\<form id="myform" asp-action="Create" method="post" \>
<div >
<label asp-for="Name" >Quiz Name</label>
<input asp-for="Name" />
<span asp-validation-for="Name" ></span>
</div>
<div id="questionRows" >
@Html.EditorFor(model => model.Questions)
<button type="button" id="AddQuestion" >Add Question</button>
</div>
<div >
input id="submitbutton" type="submit" value="Create" />
</div>
</form>
</div>
\</div\>
\<div\>
\<a asp-action="Index"\>Back to List\</a\>
\</div\>
@section Scripts {
@{
await Html.RenderPartialAsync("\_ValidationScriptsPartial");
}
<script>
$("#submitbutton").click(function (e) {
e.preventDefault();
console.log("Serialized Data: ");
console.log($('#myform').serialize())
$.ajax({
async: true,
data: $('#myform').serialize(),
method: 'post',
url: "Quizes/AddQuestion",
success: function () {
}
});
});
$("#AddQuestion").click(function () {
console.log("Serialized Data: ");
console.log($('#myform').serialize())
console.log($('#questionRows').serialize())
$.ajax({
url: '@Url.Action("AddBlankQuestion", "Quizes")',
cache: false,
success: function (html) { $("#questionRows").append(html); },
error: function (xhr, status, error) {
console.log(xhr.responseText);
}
});
return false;
});
$("a.deleteRow").on("click", function () {
$(this).parents("div.editorRow:first").remove();
return false;
});
</script>
}
Question partial view:
@model QuizIt_Tests.Entities.Question
\<hr style="height: 4px; color: black;" /\>
\<div \>
<div >
<label asp-for="Content" >Question</label>
<input asp-for="Content" value="@Model.Content" />
<span asp-validation-for="Content" ></span>
</div>
<input type="hidden" asp-for="Id" value="@Model.Id" />
@{
var answerrowid = "answerRows" @Model.Id;
var addanswerbtnid = "addAnswer" @Model.Id;
}
<div id="@answerrowid" >
@Html.EditorFor(model => model.Answers)
</div>
<button type="button" id="@addanswerbtnid">Add Answer</button>
\</div\>
<script>
console.log("#@addanswerbtnid");
$("#@addanswerbtnid").click(function () {
console.log("Add Answer clicked");
$.ajax({
url: '@Url.Action("AddBlankAnswer", "Quizes")',
cache: false,
success: function (html) {
$("#@answerrowid").append(html);
},
error: function (xhr, status, error) {
console.log(xhr.responseText);
}
});
return false;
});
</script>
Answer partial view:
@model QuizIt_Tests.Entities.Answer
\<div style="margin: 20px;"\>
<div asp-validation-summary="ModelOnly" ></div>
<div >
<label asp-for="Content" >Answer Content</label>
<input asp-for="Content" value="@Model.Content" />
<span asp-validation-for="Content" ></span>
</div>
<input type="hidden" asp-for="Id" value="@Model.Id" />
\</div\>
This is my controller:
public class QuizesController : Controller
{
private readonly ApplicationDBContext _context;
public QuizesController(ApplicationDBContext context)
{
_context = context;
}
public async Task<IActionResult> Index()
{
return View(await _context.Quizzes.ToListAsync());
}
public IActionResult Create()
{
var newquiz = new Quiz();
return View(newquiz);
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create(Quiz quiz)
{
if (ModelState.IsValid)
{
_context.Add(quiz);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
return View(quiz);
}
public IActionResult AddBlankQuestion(Quiz model)
{
Question question = new Question();
//question.Answers.Add(new Answer() { QuestionId = question.Id, Content = "Salaaam Necesem" });
return PartialView("EditorTemplates/Question", question);
}
public IActionResult AddBlankAnswer(Question model)
{
var newanswer = new Answer() { QuestionId = model.Id, Content = String.Empty };
return PartialView("EditorTemplates/Answer", newanswer);
}
}
I want to create a Quiz, add questions to the quiz, and add answers to the question. I bound all items with asp-for, serialize my form, and send it to the controller, but they don't bind.
CodePudding user response:
public ICollection Questions { get; set; }
You don't bind Content
to your list ICollection<Question> Questions
, so the Questions list is null.
You need to set name like name="Questions[0].Content"
and name="Questions[1].Content"
.