在MVC5中使用AJAX调用

Jac*_*ack 2 javascript asp.net ajax asp.net-mvc jquery

我试图在MVC5项目中使用AJAX调用,就像在网上有很多类似的例子,但每次都有错误,例如antiforgerytoken,500等等.我正在寻找一个适当的AJAX调用方法,其控制器操作方法具有所有必要的属性和从View到Controller Action发送模型数据.以下是我使用的方法:

视图:

@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>
Run Code Online (Sandbox Code Playgroud)

控制器:由于反伪造或类似问题,代码无法访问此Action方法.

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

我只需要一个适当的AJAX和Action方法,可以用于MVC5中的CRUD操作.任何帮助,将不胜感激.

更新:以下是我需要澄清的一些要点:

1)我们没有使用"__RequestVerificationToken",我不确定我们是否正确地将它发送到Controller(它似乎是Firebug的Request Headers中的cookie,但我不确定它是否正常).任何的想法?

2)我应该使用var formdata = new FormData($('#frmRegister').get(0)); 当我上传文件?

3)为什么我必须避免在这种情况下使用processData和contentType?

4)AJAX方法的Controller方法和错误部分是否正常?或者那里有任何缺失或额外的部分?

小智 5

如果视图中的模型是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);
        }
    });
});
Run Code Online (Sandbox Code Playgroud)

或者更简单

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

如果您要上传文件,那么您需要使用FormData并且代码需要(请参阅此答案

$('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);
        }
    });
});
Run Code Online (Sandbox Code Playgroud)

请注意,在使用jQuery时必须将both processDatacontentTypefalse 设置为false FormData.

如果你得到一个500(Internal Server Error),它几乎总是意味着你的控制器方法抛出异常.在您的情况下,我怀疑这是因为您的方法返回部分视图(如回调中$('#result').html(data);的代码行所示success),但您已指定返回类型应该是json(您使用该datatype: "json",选项).请注意,没有必要指定dataType选项(.ajax()如果未指定,该方法将解决)

如果这不是原因500(Internal Server Error),那么您需要调试代码以确定导致预期的原因.您可以使用浏览器开发人员工具来协助该过程.打开网络选项卡,运行该功能,(将突出显示该功能的名称),单击它,然后检查响应.它将包括投掷的详细信息.