我正在尝试创建一个用于创建/编辑测验的 Web 应用程序管理工具,该工具可以完全调整(使用 ASP.NET Core MVC)。
我所说的完全可调:
问题是,在
QuizViewModel
类中,我有一个 Questions
的集合,每个 Question
都有一个 Answers
的集合。
我已经通过使用 EditorTemplates 并对我的控制器方法执行 Ajax 调用,创建了 2 个用于添加和删除
Questions
的按钮,该方法在 Questions
集合中添加/删除对象。所有绑定都运行良好。
但是当我尝试为每个
Answer
添加/删除Question
创建相同的逻辑时,就会出现问题。我试图通过分配每个答案的部分 div 来执行与 Questions
相同的操作,它是唯一的 id,即
string answersContainerId = $"answers-container-{Model.QuestionNumber}";
对“添加/删除答案”按钮执行相同的操作。
这是我的课程的简化结构:
public class QuizViewModel
{
public string QuizName { get; set; }
public List<QuizQuestion> Questions { get; set; }
public QuizViewModel()
{
this.Questions = new List<QuizQuestion>
{
new QuizQuestion() // First must-have question
{
QuestionNumber = 1
}
};
}
}
public class QuizQuestion
{
public string QuestionName { get; set; }
public int Duration { get; set; } // Question duration (sec)
public int QuestionNumber { get; set; }
public List<QuizAnswer> Answers { get; set; } // List of answers per 1 question
public QuizQuestion()
{
Duration = 30; // default
Answers = new List<QuizAnswer>() // When creating a new empty question, by default we create 3 answers for it
{
new QuizAnswer{ AnswerNumber = 1 },
new QuizAnswer{ AnswerNumber = 2 },
new QuizAnswer{ AnswerNumber = 3}
};
}
}
public class QuizAnswer
{
public string AnswerName { get; set; }
public bool IsCorrect { get; set; }
public int AnswerNumber { get; set; }
}
这是
Views>Quiz>CreateQuiz.cshtml
视图(简化):
@model QuizViewModel
@using (Html.BeginForm("CreateQuiz", "Quiz", FormMethod.Post, new { id = "form-create-new-quiz" }))
{
@Html.AntiForgeryToken()
<h3>Quiz Name:</h3>
<div class="form-group">
@Html.LabelFor(model => model.QuizName,"Quiz Name:", htmlAttributes: new { @class = "control-label" })
@Html.TextBoxFor(model => model.QuizName, new { @class = "form-control"})
@Html.ValidationMessageFor(model => model.QuizName, "", new { @class = "text-danger" })
</div>
<div>
<h1>Quiz Questions:</h1>
<div id="questions-container">
@Html.EditorFor(model => model.Questions)
</div>
</div>
<div>
<button id="btn-add-new-question" type="button" class="btn btn-success">Add new question</button>
<button id="btn-remove-quiz-question" type="button" class="btn btn-danger">Remove Question</button>
<input type="submit" value="Submit Quiz" class="btn btn-primary" />
</div>
}
@section Scripts
{
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
<script type="text/javascript">
$("#btn-add-new-question").on('click', function () {
$.ajax({
async: true,
data: $('#form-create-new-quiz').serialize(),
type: "POST",
url: "/Quiz/AddQuizQuestion",
success: function (partialView) {
console.log("partialView: " + partialView);
$('#questions-container').html(partialView);
}
});
});
</script>
<script type="text/javascript">
$("#btn-remove-quiz-question").on('click', function () {
$.ajax({
async: true,
data: $('#form-create-new-quiz').serialize(),
type: "POST",
url: "/Quiz/RemoveQuizQuestion",
success: function (partialView) {
console.log("partialView: " + partialView);
$('#questions-container').html(partialView);
}
});
});
</script>
}
我有一个编辑器模板
.cshtml
文件,用于 Question
文件夹中的 Answer
和 EditorTemplates
类:
Views>Shared>EditorTemplates>QuizQuestion.cshtml
文件:@model QuizQuestion
@{
string currentQuestionAddAnswerButtonId = $"btn-add-new-answer-to-question-{Model.QuestionNumber}";
string currentQuestionRemoveAnswerButtonId = $"btn-remove-answer-from-question-{Model.QuestionNumber}";
string answersContainerId = $"answers-container-{Model.QuestionNumber}";
}
<div class="form-group">
<div>
@Html.LabelFor(question => question.QuestionName,"Question Name:", htmlAttributes: new { @class = "control-label" })
@Html.TextBoxFor(question => question.QuestionName, new { @class = "form-control"})
@Html.ValidationMessageFor(question => question.QuestionName, "", new { @class = "text-danger" })
</div>
<div id="@{@answersContainerId}">
@Html.EditorFor(question => question.Answers)
</div>
<button id="@{@currentQuestionAddAnswerButtonId}" type="button" class="btn btn-success">Add New Answer</button>
<button id="@{@currentQuestionRemoveAnswerButtonId}" type="button" class="btn btn-danger">Remove Answer</button>
</div>
@section Scripts
{
<script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<script type="text/javascript">
$("#@{@currentQuestionAddAnswerButtonId}").on('click', function () {
$.ajax({
async: true,
data: $('#form-create-new-quiz').serialize(),
type: "POST",
url: "/Quiz/AddNewAnswerToQuestion",
success: function (partialView) {
console.log("partialView: " + partialView);
$('#@{@answersContainerId}').html(partialView);
}
});
});
</script>
<script type="text/javascript">
$("#@{@currentQuestionRemoveAnswerButtonId}").on('click', function () {
$.ajax({
async: true,
data: $('#form-create-new-quiz').serialize(),
type: "POST",
url: "/Quiz/RemoveAnswerFromQuestion",
success: function (partialView) {
console.log("partialView: " + partialView);
$('#@{@answersContainerId}').html(partialView);
}
});
});
</script>
}
Views>Shared>EditorTemplates>QuizAnswer.cshtml
文件:@model QuizAnswer
<div>
<h2><strong>Answer @Html.DisplayFor(answer => answer.AnswerNumber)</strong></h2>
@Html.HiddenFor(answer => answer.AnswerNumber)
<div class="form-group">
<div>
@Html.LabelFor(answer => answer.AnswerName,"Answer:", htmlAttributes: new { @class = "control-label" })
@Html.TextBoxFor(answer => answer.AnswerName, new { @class = "form-control"})
@Html.ValidationMessageFor(answer => answer.AnswerName, "", new { @class = "text-danger" })
</div>
<div class="form-check">
@Html.CheckBoxFor(answer => answer.IsCorrect, new { @class = "form-check-input"})
@Html.LabelFor(answer => answer.IsCorrect, "Is Correct", new { @class = "form-check-label"})
</div>
</div>
</div>
我确实有 2 个编辑器模板的部分视图:
Views>Quiz>QuizQuestions.cshtml
:@model QuizViewModel
@Html.EditorFor(model => model.Questions)
Views>Quiz>QuizAnswers.cshtml
:@model QuizQuestion
@Html.EditorFor(model => model.Answers)
最后,这是我的
QuizController
课程:
public class QuizController : Controller
{
public IActionResult CreateQuiz()
{
return View(new QuizViewModel());
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> AddQuizQuestion([Bind("Questions")] QuizViewModel quizViewModel)
{
QuizQuestion newQuizQuestion = new QuizQuestion
{
QuestionNumber = quizViewModel.Questions.Count + 1
};
quizViewModel.Questions.Add(newQuizQuestion);
return PartialView("QuizQuestions", quizViewModel);
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> RemoveQuizQuestion([Bind("Questions")] QuizViewModel quizViewModel)
{
if (quizViewModel.Questions.Count is not 1)
{
quizViewModel.Questions.RemoveAt(quizViewModel.Questions.Count - 1);
}
return PartialView("QuizQuestions", quizViewModel);
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> AddNewAnswerToQuestion([Bind("Questions")] QuizViewModel quizViewModel)
{
// Define to which question to add answer
var quizQuestion = quizViewModel.Questions.FirstOrDefault();
return PartialView("QuizAnswers", quizQuestion);
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> RemoveAnswerFromQuestion([Bind("Questions")] QuizViewModel quizViewModel)
{
// Define from which question to remove answer
var quizQuestion = quizViewModel.Questions.FirstOrDefault();
return PartialView("QuizAnswers", quizQuestion);
}
}
所以最后,当我按下独特的“添加/删除答案”按钮时,我的控制器方法
AddNewAnswerToQuestion()
和 RemoveAnswerFromQuestion()
不会被调用。
但是,相同的逻辑适用于添加/删除问题。
所以我认为问题出在嵌套类中。
真的希望有人能提供帮助,我一直在坚持这个问题。 如果您需要提供更多信息,请告诉我。
这是我在 Stack Overflow 上提出的第一个问题,所以如果有问题没有得到很好的解释,我深表歉意。