AlexGH AlexGH - 4 months ago 16
jQuery Question

Can't access to action method from JQuery if [AntiForgeryToken] is enabled

I have a JQuery function that works ok but if I enable

[AntiForgerToken]
on the Action Method the JQuery function can't access the Action Method, on the view I have other snippet where I enabled AntiForgeryToken:

@using (Html.BeginForm("InsertStudent","Students",FormMethod.Post, new { @id="myform"}))
{
@Html.AntiForgeryToken()


It doesn't matter if the
@Html.AntiForgeryToken()
inside the view is enabled or not, the JQuery function works good, the one with the problem is at the Action Method...

Why is happening that? What I'm missing?? I've read is very important for security to have
[AntiForgeryToken]
enabled on the Post Action Methods so I think that the application should work with it enabled in both places the Action Method and the View.

JQuery function:

function InsertShowStudents() {
var counter = 0;
$.ajax({
type:"post",
url: "/Students/InsertStudent/",
data: { Name: $("#Name").val(), LastName: $("#LastName").val(), Age: $("#Age").val() }
}).done(function (result) {
if (counter==0) {
GetStudents();
CounterStudents();
counter = 1;
}
else {
$("#tableJQuery").append("<tr>"+"<td>"+result.Name+"</td>"+"<td>"+result.LastName+"</td>"+"<td>"+result.Age+"</td>"+"</tr>")
}
//clear the form
$("#myform")[0].reset();
}).error(function () {
$("#divGetStudents").html("An error occurred")
})
}


Action method:

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult InsertStudent(Student student)
{
if (ModelState.IsValid)
{
db.Students.Add(student);
db.SaveChanges();
//ModelState.Clear();
return RedirectToAction("InsertStudent");
}
return View(student);
}


columns of the table:

@foreach (var item in Model) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.Name)
</td>
<td>
@Html.DisplayFor(modelItem => item.LastName)
</td>
<td>
@Html.DisplayFor(modelItem => item.Age)
</td>
@* <td style="display:none" class="tdStudentID">@Html.DisplayFor(modelItem => item.StudentID)</td> *@
<td>
<img src="~/images/deleteIcon.png" width="20" height="20" class="imgJQuery" data-id="@item.StudentID" />
</td>
<td>
@Html.ActionLink("Details","Details", new { id=item.StudentID})
</td>
</tr>
}

Answer

You not passing the value of the token in your ajax call so an exception is thrown. You can get the value of the token using

var token = $('[name=__RequestVerificationToken]').val();

and modify your ajax call to include it using

data: { __RequestVerificationToken: token, Name: $("#Name").val(), LastName: $("#LastName").val(), Age: $("#Age").val() }

however, it is easier to just serialize your form which will include the token

$.ajax({        
    type:"post",
    url: '@Url.Action("InsertStudent", "Students")', // don't hardcode your url's
    data: $('#myform').serialize(),
}).done(function (result) {

Side note: Ajax calls never redirect (the whole point of ajax is to stay on the same page) so having return RedirectToAction("InsertStudent"); in your InsertStudent() will not work. In addition, your returning html, so the $("#tableJQuery").append() code in the .done() callback will fail.

It appears you have a form to add a new Student so your method simply need to return a JsonResult indicating success or otherwise, and if successful, then you can add a new row to your table based on the values in the form, for example

}).done(function (result) {
    if (result) {
        var row = $('<tr></tr>');
        row.append($('<td></td>').text($("#Name").val()));
        ... // add other cells
        $("#tableJQuery").append(row);
        //clear the form
        $("#myform")[0].reset();
    } else {
        // Oops something went wrong
    }
})
Comments