1

I was using antiforgerytoken within my razor view, and it was working fine. Then I moved the same code to AJAX, and it has started giving weird problems.

The AJAX POST request works fine, but the action SendData() which is called from the AJAX has a redirect to a different View (return View("Close");), which does not work anymore. It worked perfectly fine when the SendData() was called from the form directly.

Working code:

@using(Html.BeginForm("SendData", "Controller", FormMethod.Post)) {
    @Html.AntiForgeryToken():
}

Not working code:

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

JS File:

var form = $('#__AjaxAntiForgeryForm');
var token = $('input[name="__RequestVerificationToken"]', form).val();
$.ajax({
    type: 'POST',
    url: '/Controller/SendData',
    data: {
        __RequestVerificationToken: token
    },
    cache: false,
    success: function(result) {}
});

The Action SendData() executes fine, but the redirect within this action doesn't work anymore.

rickvdbosch
  • 14,105
  • 2
  • 40
  • 53
  • 4
    What do you mean _the redirect within this action don't work any more_? - its an ajax call - the whole point of ajax is to stay on the **SAME** page. Ajax calls cannot redirect. (and this has nothing at all to do with the `AntiForgeryToken`) –  Jun 15 '18 at 09:17
  • Can you show us your `SendData` action ? I'm not sure I understand what you mean by "redirect to a different [...]". The `View()` function has nothing to do with a redirect. – Mathieu VIALES Jun 15 '18 at 09:47

2 Answers2

0

I advise you use .serialize() instead of the following line.

var token = $('input[name="__RequestVerificationToken"]', form).val();

It is generic and thus will automatically adapt to any model changes.

For a working example of Antiforgery used alongside Ajax check this answer. The question was asked for MVC3 but it should work perfectly well as long as you're using an MVC version above 3.

The result param in the success: function (result) part of the ajax call will receive whatever was returned by your SendData action. If the SendData action uses a return View([...]); then you will probably get some html code in your result var. You could also return json data as follow return Json([...]).

If you actually want to have a redirect be made by the result of your Ajax call you should return the URL that you want to use as the redirection's target as follow return Content("http://target.url.for.redirect.com"); and then in your success callback, using the location.replace method, do this:

success: function(result)
{
    document.location.replace(result);
}

This way the URL returned by the Ajax controller will be used to execute a redirection.

NOTE if you wish to ALWAYS redirect the user after the form is sent you should not use ajax at all ! A regular POST form would be far better suited for the job.

Mathieu VIALES
  • 4,526
  • 3
  • 31
  • 48
  • _Ajax.BeginForm instead of Html.BeginForm_ - what poor advice (its no longer supported, not recommended by the mvc team, and has been dropped from core-mvc). And to make an ajax call and then redirect in the callback is pointless –  Jun 16 '18 at 05:33
  • Thank you for your comment, you are right. Old habits led me to writing this but your comment had me do some research and reading threads such as [this one](https://github.com/aspnet/Mvc/issues/2015) made me realise my advice wasn't good. I removed it from the answer. – Mathieu VIALES Jun 16 '18 at 07:31
0

I figured out the problem, as per the comment from Stephen Muecke. The AJAX calls don't allow redirects, as the whole point behind AJAX is to stay on the same page and make a background JS call.