jquery - 从 ASP.NET MVC 中成功的 AJAX 调用重定向

标签 jquery asp.net-mvc modal-dialog

我正在构建一个网络应用程序,它是为我认识的老师提供的测试/问题/答案应用程序。要求之一是测试必须一次性完成……即……不能保存并继续。我选择使用 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. 重定向页面并替换其全部内容。
  2. 用测试的第一个问题替换页面的一部分。

根据你的问题,我假设你会选择#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/

相关文章:

asp.net-mvc - 在 mvc3 的 Html.Actionlink() 中显示从数据库获取的值

c# - 依赖注入(inject)

javascript - Rails 4 Bootstrap 模式在显示前短暂闪烁

objective-c - 以模态呈现 UIView 不是全屏

javascript - 如何删除除特定属性之外的所有标签属性?

javascript - 前端性能和css/js文件数量

javascript - 总共得到jquery的.each()

javascript - 使用 jQuery,我如何检测元素是否为 'mouseovered' 以及该元素的任何子元素?

asp.net-mvc - ASPNET MVC DropDownListFor 对两个输入重复使用相同的数据列表会导致意外选择

iFrame 上的 jQuery 模式对话框