我正在构建一个网络应用程序,它是为我认识的老师提供的测试/问题/答案应用程序。要求之一是测试必须一次性完成……即……不能保存并继续。我选择使用 jQuery UI 通过模式弹出窗口来实现这一点。我有一个用于进行测试的搜索页面,以及在开始测试之前的模式确认对话框。我遇到的问题是,在用户选择继续测试后,它需要重定向到一个新页面,其中将显示模式弹出窗口和第一个问题(之后的每个问题将通过 AJAX 加载到相同的模式弹出窗口中)。我可以进行搜索,并弹出确认窗口,但我不知道如何重定向到问题页面。我的 TestController 中的 Question 操作被调用并且参数是正确的,但是一旦返回 View,ASP.NET 就会抛出一个异常,告诉我第一个参数为 null。以下是控制此行为的代码片段:
来自 Search.cshtml(此 div 是模式确认弹出窗口):
<div id="dialog" title="Confirm Test">
<p>
<span class="ui-icon ui-icon-alert" style="float:left; margin:0 7px 20px 0;"></span>Are you sure you want to take the selected test?
</p>
</div>
@section scripts
{
<script type="text/javascript">
$(document).ready(function () {
$(".takeTest").click(function (e) {
e.preventDefault();
var testId = $(this).data("test-id");
$("#selectedTestId").val(testId);
$("#dialog").dialog("open");
});
$("#dialog").dialog({
dialogClass: "no-close",
autoOpen: false,
modal: true,
resizable: false,
height: 180,
buttons: {
'Confirm': function () {
var appId = $("#applicantId").val();
var id = $("#selectedTestId").val();
$.ajax({
url: "/Testing/TakeTest/",
data: { applicantId: appId, testId: id },
type: "POST",
success: function (results) {
window.location.href = "/Testing/Question/";
}
});
},
'Cancel': function () {
$(this).dialog('close');
}
}
});
});
</script>
}
来自测试 Controller :
[HttpPost]
public ActionResult TakeTest(int applicantId, int testId)
{
try
{
ApplicantTest test = TestingRepository.GetInstance().TakeTest(applicantId, testId);
return RedirectToAction("Question", "Testing", new { applicantId = applicantId, testId = testId });
}
catch
{
return RedirectToAction("Search", "Testing");
}
}
[HttpGet]
public ActionResult Question(int applicantId, int testId)
{
Question nextQuestion = TestingRepository.GetInstance().GetNextQuestion(applicantId, testId);
NextQuestionViewModel model = AutoMapper.Mapper.Map<NextQuestionViewModel>(nextQuestion);
model.ApplicantId = applicantId;
model.QuestionNumber = (nextQuestion.ApplicantTestAnswers.Count + 1);
return View(model);
}
来自 Question.cshtml:
@Html.HiddenFor(x => x.ApplicantId, new { id = "applicantId" })
@Html.HiddenFor(x => x.TestId, new { id = "testId" })
<div id="dialog" title="Question: @Model.QuestionNumber">
@Html.Partial("_NextQuestionPartial", Model)
</div>
@section scripts
{
<script type="text/javascript">
$(document).ready(function () {
$("#dialog").dialog({
dialogClass: "no-close",
autoOpen: true,
modal: true,
resizable: false,
height: 400,
buttons: {
'Next': function () {
}
}
});
});
</script>
}
来自_NextQuestionPartial.cshtml:
@Ajax.BeginForm("Question", "Testing", new AjaxOptions { HttpMethod = "POST", InsertionMode = InsertionMode.Replace, UpdateTargetId = "nextQuestionContainer" })
{
<fieldset>
<legend>Question # @Model.QuestionNumber</legend>
<div id="nextQuestionContainer">
<p>Q: @Model.QuestionText</p>
<ul>
@foreach (var answer in Model.QuestionAnswers)
{
<li>
@answer.Answer
</li>
}
</ul>
</div>
</fieldset>
}
Search.cshtml 中的模式确认弹出正常,确认按钮调用 TestController 中的 Question 操作(使用 VS 中的断点进行验证)。 applicationId 和 testId 均填充了正确的值。 NextQuestionViewModel 已正确创建,并且返回 View(model) 被调用,但这就是我对正在发生的事情感到迷失的地方。我收到异常:参数字典包含方法“System.Web.Mvc.ActionResult Question(Int32, Int32)”的不可空类型“System.Int32”的参数“applicantId”的空条目。
但是,如果我直接从 URL 将这些参数添加到查询字符串,则页面将加载,并且问题的模式弹出窗口将正确显示。这似乎是一个路由问题,但我是 MVC 的新手,并且当我可以在操作方法问题中看到它的值时,我无法理解为什么 TestController::TakeTest 中的 RedirectToAction 会抛出有关申请人Id 的异常。
最佳答案
最快的解决方法是更改线路:
window.location.href = "/Testing/Question/";
以下内容:
window.location.href = "/Testing/Question?applicantId=" + appId + "&testId=" + id;
编辑:
用户用户确认想要参加测试后,您可以:
- 重定向页面并替换其全部内容。
- 用测试的第一个问题替换页面的一部分。
根据你的问题,我假设你会选择#1。这样,在用户确认后,浏览器将被重定向到类似于 http://YourSite.com/Testing/Question?applicantId=123&testId=456 "的 URL,而不是停留在 "http://YourSite.com/TestPage "。
我认为实现此目的的最佳方法是使用简单的 HTML 表单,完全绕过 $.ajax
调用。看起来您有两个使用 jQuery 引用的元素,分别为 ids 'applicantId' 和 'selectedTestId'。我不确定您如何为这些元素分配值,但您可以将它们包装在如下形式中:
<form id="testForm" action="/Testing/TakeTest" method="post">
<!-- Put your two elements here -->
<!-- For example: -->
<input id="applicantId" name="applicantId" type="hidden" />
<input id="selectedTestId" name="testId" type="hidden" />
</form>
注意:请注意上述输入的 name
属性如何与 Question
操作方法中的参数名称相对应。
然后您可以将整个 $.ajax
调用替换为以下内容:
$('#testForm').submit();
默认情况下,这会将您的数据提交到 TestPage
POST 操作,该操作又会将您的浏览器重定向到“/Testing/Question...”并呈现新页面。
摘要:由于您不想简单地替换页面的一部分,因此请避免 ajax 调用,而只需使用表单来提交数据。
关于jquery - 从 ASP.NET MVC 中成功的 AJAX 调用重定向,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20231599/