2013-11-27 41 views
2

我有一個web應用程序,我正在構建一個測試/問題/答案應用程序,我認識一位老師。其中一個要求是測試必須在一次會議中完成......即......不保存並繼續。我選擇通過使用jQuery UI的模式彈出窗口來實現這一點。在測試開始前,我有一個測試搜索頁面和一個模態確認對話框。我遇到的問題是在用戶選擇繼續測試之後,它需要重定向到一個新頁面,其中第一個問題將顯示模式彈出窗口(之後的每個問題將通過AJAX加載到相同的模式彈出窗口中)。我有搜索工作,以及確認彈出窗口,但我無法弄清楚如何重定向到問題頁面。我的TestingController中的Question操作被調用並且參數是正確的,但是一旦返回View,ASP.NET將引發一個異常,告訴我第一個參數爲null。以下是控制此行爲的片段:從ASP.NET MVC中成功的AJAX調用重定向

從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> 
} 

從TestingController:

 [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模態確認彈出罰款和確認按鈕調用TestingController問題的行動(與斷點VS驗證)。 applicantId和testId都填充了正確的值。 NextQuestionViewModel被正確創建並且返回View(模型)被調用,但是這正是我所迷失的事情發生的地方。我得到了這個異常:參數字典包含一個空方法'System.Web.Mvc.ActionResult Question(Int32,Int32)'的非空類型'System.Int32'的參數'applicantId'的空項。

但是,如果我直接從URL中將這些參數添加到querystring中,頁面將加載並且問題的模式彈出窗口會正確顯示。看起來這是一個路由問題,但我是MVC的新手,我無法理解爲什麼TestingController :: TakeTest中的RedirectToAction正在拋出有關applicantId的此異常,因爲我可以在操作方法Question中看到它的值。

+0

等待。當你從頭到尾地執行這個過程時,是否會發生異常*只是在用戶在第**行確認測試後返回RedirectToAction(「Question」,「Testing」,...'**或者第一個問題成功顯示並*然後*拋出異常? – William

+0

它發生在第一個問題顯示之前。使用Fiddler,我已經確定有2個調用操作方法。第一個來自我的TakeTest操作方法,然後是第二個(從ajax成功函數中的window.location.href行猜測)。第一個參數是querystring,第二個參數不是......因此錯誤。我不確定最好的方法來做這個重定向,所以也許它 – user1011627

+0

如果我刪除了window.location.href,那麼對話框並沒有關閉,但是隻有第一個請求被執行(帶有查詢字符串參數),但是對話框保持不變打開重定向不會發生。如果我將$(this).dialog('close')添加到成功函數中,我得到一個javascript錯誤:「JavaScript運行時錯誤:無法在初始化之前調用對話框上的方法;試圖調用方法'關閉'」 確定如何關閉模式對話框,然後將其重定向到問題頁面。 – user1011627

回答

3

最快的解決將是改變你的線路:

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一個網址「而不是停留在」 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操作,這反過來將瀏覽器重定向到/測試/問題......「並呈現新的頁面。

摘要:由於您不想簡單地替換頁面的一部分,請避免使用ajax調用並僅使用表單提交數據。

+0

感謝威廉。這確實起作用,如果我從TakeTest中刪除RedirectToAction,則只會調用一次,這也很好。無論如何,我都會接受你的回答,但我確實對你的回覆有疑問。當我看到「最快......」時,這讓我相信有可能有更好的方法來實現這一點。在我的情況下,最好是從服務器重定向,並以某種方式處理成功函數中的問題,或者按照您的答案構建重定向?只是想確保我正在學習最好的方式來做到這一點,因爲我沒有時間緊迫...感謝你的時間。 – user1011627

+0

你打賭!它確實取決於您點擊「確認」後用戶同意參加測試時想要發生的事情。我會編輯我的答案來涵蓋這一點。 – William

+0

謝謝......我認爲完成要求的最佳方式是使用模態對話框。我有另一個要求,測試可以採取多次,但只有在一個3個月內一次。因此,確認用於確保他們想要開始測試。我試圖做的是當選擇一個測試(即......測試?鏈接)時從Search.csthml中彈出對話框。我認爲最好重定向到另一個頁面(Question.cshtml),然後顯示一個包含問題的新模態對話框。當問題得到解答時,對話框會通過另一個AJAX調用來獲得一個新問題 – user1011627