MVC 3 AJAX and [ValidateAntiForgeryToken]
Asked Answered
I

1

2

I previously asked a question regarding this, got an interesting answer which got me on my way to, well asking more questions. So here is the next question in my journey to figure out the inner workings of AJAX posts and the rather annoying ValidateAntiForgeryTokenAttribute.

I have a _layout.cshtml, this is where all of the script goodies are located for now. I have a login page that render three partials, one for OpenID logins, which is just a normal @using(Html.BeginForm()) {}, one for local login, and the other is for basic registration. The login partial and register partial both use ViewModels and Ajax.BeginForm

Please note that I am using @using Ajax.BeginForm and grabbing the data-ajax-update attr to update the element on success

Script in _layout.cshtml:

$(document).ready(function () {
    $('input[type=submit]').live("click", function (event) {
        event.preventDefault();
        var _allFormData = $(this).parents().find('form');
        var _currentForm = $(this).closest('form');
        var _updateElement = $(_currentForm).attr("data-ajax-update");

        $.ajax({
            type: "POST",
            url: $(_currentForm).attr('action'),
            data: $(_allFormData).serialize(),
            success: function (data) {
                $(_updateElement).html(data);
            }
        });

        return true;
    });
});

Form Element in _layout.cshtml

<form id="__AjaxAntiForgeryForm" action="#" method="post">
    <@Html.AntiForgeryToken()>
</form>  

Action Method in Controller:

public ActionResult RegisterMember(
    RegisterMemberViewModel registerMemberViewModel)
{
    // Process some stuff
    return PartialView("_Register");
}

Why is this working, magically the AntiForgeryToken is getting included in all my posts. I am not grabbing it and appending it, I am not doing anything with it really it is just there. Can someone please shed some light on why this works. I don't like accidental solutions, they usually break later on.

Inimical answered 1/9, 2011 at 12:37 Comment(2)
@casper, thanks for the related links on my prev posts way cool.Inimical
I love questions that ask "why is this working" because then I don't have to dig through the answers to find working code! Props to you for providing all the codeRecrudesce
T
0

The @Html.AntiForgeryToken() creates an <input type='hidden' name='__RequestVerificationToken'/> or something similar inside your form. And if I understand correctly this: var _allFormData = $(this).parents().find('form'); in combination with this:data: $(_allFormData).serialize() post all your form data to the server, including the inputfield __RequestVerificationToken which MVC probably looks for,

Triturable answered 1/9, 2011 at 12:52 Comment(5)
Hmm, interesting. I wonder if the form data from the login form is being sent as well everytime.Inimical
probably, as $(this).parents().find('form') will return all form elements found in the dom document.Triturable
Yes, every form's values are being sent so now I need to figure out a way to filter the others out and only include the current form and the antiforgery form. However you did answer my question and I am sure I will post another one if I cant figure out the filtering part. Going to give it a whirl though. Thanks much for your answer.Inimical
you can probably apply a other jquery selector in the .find() to identify only those two formsTriturable
I broke my validation but the token works :) I posted another question #7272732Inimical

© 2022 - 2024 — McMap. All rights reserved.