2016-08-17 28 views
2

我試圖在MVC5項目中使用AJAX調用,因爲網上有很多類似的例子,但每次出現錯誤時,即antiforgerytoken,500等等,我正在查看適當的AJAX調用方法與控制器行動方法,具有所有必要的屬性和發送模型數據從視圖到控制器行動。下面是我使用的方法:在MVC5中使用AJAX調用

查看:

@using (Html.BeginForm("Insert", "Account", FormMethod.Post, new { id = "frmRegister" })) 
{ 
    @Html.AntiForgeryToken() 
    //code omitted for brevity 
} 



<script> 

    AddAntiForgeryToken = function (data) { 
    data.__RequestVerificationToken = $('#__AjaxAntiForgeryForm input[name=__RequestVerificationToken]').val(); 
    return data; 
    }; 

$('form').submit(function (event) { 
     event.preventDefault(); 

     //var formdata = JSON.stringify(@Model); //NOT WORKING??? 
     var formdata = new FormData($('#frmRegister').get(0)); 
     //var token = $('[name=__RequestVerificationToken]').val(); //I also tried to use this instead of "AddAntiForgeryToken" method but I encounter another error 

     $.ajax({ 
      type: "POST", 
      url: "/Account/Insert", 
      data: AddAntiForgeryToken({ model: formdata }), 
      //data: { data: formdata, __RequestVerificationToken: token }, 
      //contentType: "application/json", 
      processData: false, 
      contentType: false, 

      datatype: "json", 
      success: function (data) { 
       $('#result').html(data); 
      } 
     }); 

    }); 
</script> 

控制器:代碼不能打到由於antiforgerytoken或類似的問題,這種操作方法。

[HttpPost] 
[AllowAnonymous] 
[ValidateAntiForgeryToken] 
public JsonResult Insert(RegisterViewModel model) 
{ 
    try 
    { 
     //... 
     //code omitted for brevity 
    } 
} 

我只需要一個適當的AJAX和Action方法,可以用於MVC5中的CRUD操作。任何幫助,將不勝感激。

UPDATE:下面是一些點,對此,我需要澄清:

1)我們沒有使用「__RequestVerificationToken」,我不知道,如果我們把它發送到控制器正確(這似乎在Firebug的請求頭中作爲cookie,但我不確定是否可以)。任何想法? 2)我應該使用var formdata = new FormData($('#frmRegister')。get(0));當我上傳文件?

3)爲什麼我必須避免在這種情況下使用processData和contentType?

4)AJAX方法的Controller方法和錯誤部分是否正常?或者那裏有缺失或多餘的部分?

+0

使用var formdata = new FormData($('#frmRegister')。get(0));'將包含防僞標記。所有你需要的是'data:formdata',儘管它不清楚爲什麼你使用FormData(你也在上傳文件嗎?) –

回答

3

如果您的視圖模型是RegisterViewModel和您正確使用強類型HtmlHelper方法生成的表單控件,然後使用無論是new FormData($('#frmRegister').get(0))$('#frmRegister').serialize()將正確發送<form>標記中的所有表單控件的值(包括該標記),並且不需要再次添加該標記。

如果你的表格不包括文件輸入,則代碼應該是

$('form').submit(function (event) { 
    event.preventDefault(); 
    var formData = $('#frmRegister').serialize(); 
    $.ajax({ 
     type: "POST", 
     url: '@Url.Action("Insert", "Account")', // do not hard code your url's 
     data: formData, 
     datatype: "json", // refer notes below 
     success: function (data) { 
      $('#result').html(data); 
     } 
    }); 
}); 

或者更簡單地說

$.post('@Url.Action("Insert", "Account")', $('#frmRegister').serialize(), function(data) { 
    $('#result').html(data); 
}); 

如果您要上傳的文件,那麼你需要,你需要使用FormData和代碼需要(也可參考this answer

$('form').submit(function (event) { 
    event.preventDefault(); 
    var formData = new FormData($('#frmRegister').get(0)); 
    $.ajax({ 
     type: "POST", 
     url: '@Url.Action("Insert", "Account")', 
     data: formData, 
     processData: false, 
     contentType: false, 
     datatype: "json", // refer notes below 
     success: function (data) { 
      $('#result').html(data); 
     } 
    }); 
}); 

請注意,在使用jQuery和FormData時,您必須將processDatacontentType設置爲false。

如果你得到一個500(Internal Server Error),它幾乎總是意味着你的控制器方法拋出一個異常。在你的情況,我懷疑這是因爲你的方法返回一個部分視圖($('#result').html(data);代碼行success回調),但你已經指定返回類型應該是json(你使用datatype: "json",選項)。請注意,這是沒有必要指定dataType選項(.ajax()方法做出來,如果沒有指定其)

如果不是500(Internal Server Error)的原因,那麼你需要調試你的代碼,以確定是什麼原因造成期待。您可以使用瀏覽器開發人員工具來協助該過程。打開網絡選項卡,運行該功能(該功能的名稱將突出顯示),點擊它,然後檢查響應。它將包括拋出的預期細節。

+0

非常感謝你的精彩解釋。我認爲這個話題應該分爲兩個部分,就像你「上傳文件和不上傳文件」一樣,現在我已經在你的答案的幫助下完全澄清了。另一方面,我相信這些答案將幫助許多人厭倦了尋找關於AJAX調用的適當解決方案:)關注... –

+0

由於我已經不堪重負有關在MVC中使用AJAX的問題,我將繼續用AJAX調用我的MVC項目中的所有動作。你是否推薦這麼做,或者有什麼要注意的地方? –

+0

使用ajax的唯一原因是保持在同一頁面上。在許多情況下,您可能只想進行正常提交併重定向到POST方法中的另一個視圖(如果'ModelState'無效,則返回視圖)。在你的情況下,你似乎想保存一些東西,然後用一些額外的數據更新當前頁面,在這種情況下,使用Ajax是適當的。它是一個初學者使用ajax常見的錯誤,然後在成功回調中做一個'location.href ='....''來重定向(這是毫無意義的) –

1

的contentType應該application/x-www-form-urlencoded

試試這個代碼

<script> 
$('form').submit(function (event) { 
     event.preventDefault(); 

    $.ajax({ 
     method: "POST", 
     url: "/Account/Insert", 
     data: $(this).serialize(), 
     contentType:"application/x-www-form-urlencoded", 
     success: function (data) { 
     $('#result').html(data); 
     }, 
     error: function (jqXHR, textStatus, errorThrown) { 
      console.log(errorThrown); 
     } 
    }); 
}); 
    </script> 
+0

「TypeError:FormData.constructor的參數1沒有實現接口HTMLFormElement。 >>> var formData = new FormData($('#frmRegister')); –

+0

我修改了代碼試試這個,讓我知道會發生什麼。 –

+1

錯誤。爲了使FormData工作,'contentType'需要設置爲'false'(就像OP所做的那樣) –