2014-01-05 59 views
1

我正在處理用戶單擊註冊按鈕的表單,然後打開一個彈出窗口,以便用戶輸入註冊的詳細信息....用戶名應該這是唯一的,所以當用戶點擊提交按鈕即時檢查數據庫是否該用戶名已存在或沒有,如果它已經存在的IM顯示錯誤消息在'用戶名已存在'相同的彈出窗口.. 。在'保存'按鈕上打一個Ajax調用點擊彈出菜單

這是我爲它獲取的保存按鈕發射碼點擊

$.ajax({ 
    url: '@Url.Content("~/Registration/CheckUNameExists")', 
    type: 'GET', 
    data: { UName: $('#UserName').val() }, 
    success: function (data) { 
     if (data == 'True') { 
      $('#UserAddError').html('User Name already exists!'); 
     } else { 
      $("#update-message").html(''); 
      $("#addUserForm").submit(); 
      $(this).dialog("close"); 
     } 
    } 
}); 


public JsonResult CheckUNameExists(string UName) 
{ 

} 


[HttpPost] 
public ActionResult RegisterUser(Regitration Reg) 
{ 


} 

這是工作正常,但在極少數情況下THI這是一個問題。在用戶點擊保存按鈕幾次後,在彈出的詳細信息中填入詳細信息後,需要3-4秒的時間才能保存,在這種情況下,用戶點擊保存按鈕2-3次。在這種情況下,保存按鈕點擊是第一次檢查方法CheckUNameExists,然後RegisterUser被多次調用,基於用戶點擊保存按鈕的次數nd相同的記錄被多次保存到db中。

For測試的目的,我把一個斷點,讓我可以點擊'保存'按鈕n次,然後點擊保存按鈕4次,CheckUNameExists只被第一次擊中,但之後RegisterUser被稱爲4次,記錄被插入4倍。

不明白這裏的問題以及如何擺脫它?

回答

0

您正在發送一個GET ajax請求來檢查用戶是否存在,所以響應可能會被瀏覽器緩存。 jQuery提供的,您可以使用啓用/禁用緩存的AJAX功能,默認情況下啓用的設置,see the cache setting here

嘗試爲Ajax調用禁用緩存,加入選項cache:false到AJAX設置:

$.ajax({ 
    url: '@Url.Content("~/Registration/CheckUNameExists")', 
    type: 'GET', 
    data: { UName: $('#UserName').val() }, 
    cache: false, 
    success: function (data) { 
    ... 

這應該解決CheckUNameExists未被調用的問題。

但是你仍然可以有多個Ajax調用的競爭條件。一個更好的解決方案是發送一個單獨的ajax POST,它同時執行唯一名稱和用戶註冊的檢查。這應該可以防止由於Ajax調用的異步性質而導致的錯誤,當您在GETFileFin用戶時發生在第一次點擊按鈕之前完成提交表單。

這將需要一些重構:

$(".actionSubmit").click(function() { 
    $(".actionSubmit").attr('disabled', 'disabled'); 
    $.ajax({ 
     url: '@Url.Content("~/Account/RegisterUser")', 
     type: 'POST', 
     data: $("#addUserForm").serializeArray(), 
     success: function (data) { 
      if (!data.success) { 
       $('#UserAddError').html(data.errorMessage); 
       $(".actionSubmit").removeAttr('disabled'); 
      } else { 
       $(this).dialog("close"); 
       //Possibly redirect here, same logic you had in RegisterUser method 

      } 
     } 
    }); 
    return false; 
}); 

[HttpPost] 
public ActionResult RegisterUser(Regitration Reg) 
{ 
    //Check if user exists, whatever you were doing in CheckUNameExists 
    bool userAlreadyExists = ...; 
    if (userAlreadyExists) 
    { 
     return Json(new { success = false, errorMessage = "User Name already exists!" }); 
    } 

    //Register user 
    ... 

    return Json(new { success = true }); 
} 

您可能需要使用JavaScript禁用它的單擊事件的按鈕並再次不使它,直到你完成該解決方案結合在一起(或者是因爲名稱已經存在或由於POST完成)。我已經在上面的代碼中顯示了這一點,我正在禁用/啓用提交按鈕。

以上更改應防止與來自同一客戶端的請求相關的問題。但是,仍然可以讓來自不同機器的用戶嘗試使用相同的用戶名同時註冊。爲了避免這些,你將需要包裝的C#代碼在交易範圍內的誤差,所以無論用戶驗證和登記發生在一個事務中:

[HttpPost] 
public ActionResult RegisterUser(LoginModel model) 
{ 
    using (var tran = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions { IsolationLevel = IsolationLevel.ReadCommitted })) 
    { 
     //Check if user exists, whatever you were doing in CheckUNameExists 
     bool userAlreadyExists = ...; 
     if (userAlreadyExists) 
     { 
      return Json(new { success = false, errorMessage = "User Name already exists!" }); 
     } 

     //Register user 
     ... 

     tran.Complete(); 
    } 
    return Json(new { success = true }); 
} 

希望這有助於!

+0

我使用的緩存:假的,並點擊保存按鈕4倍,令人驚訝的「CheckUNameExists」被稱爲4倍,第二我一直在其他條件的警報味精ND該警報味精也解僱4次,但「CheckUNameExists」連續叫4倍nd警報味精也連續4次,而不是一個接一個....笏是其他選項你提到,我沒有得到他們? – sebastian

+0

@sebastian Ajax調用是異步的,所以你可能仍然有競爭條件,因爲任何形式的提交的已註冊的用戶,並在數據庫中插入記錄之前的GET Ajax調用將完成。最安全的是不要信任發佈的數據,只有一個POST方法可以驗證用戶是否唯一併註冊他。爲了確保不存在競爭條件,您需要在交易中包裝用戶驗證和註冊。我編輯了我的答案。 –

+0

Thnku,截至目前即時通訊禁用按鈕上的按鈕點擊並再次啓用它在成功功能....其工作正常..肯定會嘗試你提到的其他方式 – sebastian

相關問題