提问人:Vasily Pascal 提问时间:10/10/2023 最后编辑:Vasily Pascal 更新时间:10/11/2023 访问量:67
Ajax 调用不在 MVC 的嵌套编辑器模板中执行
Ajax call is not performed inside a nested editor templates in MVC
问:
我正在尝试创建一个用于创建/编辑测验的 Web 应用程序管理工具,该工具可以完全调整(使用 ASP.NET Core MVC)。
我所说的完全可调是什么意思:
- 管理员用户可以为每个测验添加/删除任意数量的问题。
- 管理员用户可以在每个问题的答案上添加/删除任何数字。
问题是,在类中,我有一个集合,每个集合都有一个集合。QuizViewModel
Questions
Question
Answers
我已经创建了 2 个用于添加和删除的按钮,通过使用 EditorTemplates 和对我的控制器方法执行 Ajax 调用,该方法正在从集合中添加/删除对象。所有绑定都运行良好。Questions
Questions
但是,当我尝试为每个添加/删除创建相同的逻辑时,就会出现问题。我正在尝试执行与我相同的操作,方法是为每个答案的部分分配 div 它是唯一的 id,即Answer
Question
Questions
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 上的第一个问题,所以如果有什么没有得到很好的解释,我深表歉意。
答:
评论
my Controller methods AddNewAnswerToQuestion() and RemoveAnswerFromQuestion() are not called