15

AJAX POST in ASP.NET Core Razor page will not work. It always returns a 400 Bad Request.

I have the following page method code :

[ValidateAntiForgeryToken]
public async Task<IActionResult> OnPostProcessCCPaymentAsync(CheckInPaymentModel checkInPaymentModel)
    {
        return new JsonResult(checkInPaymentModel.AmountExtra);
    }

The following is set in the page :

@Html.AntiForgeryToken()

And the following JS AJAX call :

$.ajax({
    type: "POST",
    url: "/CheckIn/Payment?handler=ProcessCCPayment",
    contentType: "application/json",
    beforeSend: function (xhr) {
        xhr.setRequestHeader("XSRF-TOKEN",
            $('input:hidden[name="__RequestVerificationToken"]').val());
    },
    data: JSON.stringify({
        // Those property names must match the property names of your PromotionDecision  view model
        Donate: true
    }), 
    success: function (response) {
        $(".paymentDetails .loading").addClass("loader").removeClass("loading");
    },
    failure: function (response) {
        $(".paymentDetails .loading").addClass("loader").removeClass("loading");
    }
});

If the Ajax Type is changed to GET & the method changed to OnGetProcessCCPaymentAsync then it correctly sends to the server.

However the AJAX POST in Core Razor always fails with a 400 Bad Request.

I am debugging directly from Visual Studio so the URL is http://localhost:62632/CheckIn/Payment so I don't know how to locate the logs to see what error is occuring when the debug instance is receiving the request.

Any ideas or advice would be greatly appreciated.

Bhargav Rao
  • 50,140
  • 28
  • 121
  • 140
nrr
  • 163
  • 2
  • 8
  • When doing a POST have you tried decorating the MVC Action with [HttpPost]? –  Apr 27 '18 at 14:25
  • 3
    Your request header has the wrong name, it should be RequestVerificationToken and also note that AntiForgeryToken isn't used for GET. It would be a good idea to add razor-pages tag to your question. – Mark G Apr 27 '18 at 14:28
  • 4
    @MarkG that did the trick. The header should have been "RequestVerificationToken" and not "XSRF-TOKEN" https://www.learnrazorpages.com/security/request-verification – nrr Apr 27 '18 at 23:37
  • I fixed my issue by just adding @Html.AntiForgeryToken() into the form. (I serialize form data and then use jquery's .post method to send all form fields.) Even if I just targetted an iframe for the form's post it would cause the "bad request" message, so it's not only an ajax issue. – pcalkins Jul 09 '20 at 23:32

1 Answers1

4

Just so there's no confusion in reading the revisions above and comment (which left me scratching my head for a minute), the solution is to change:

xhr.setRequestHeader("XSRF-TOKEN",

To:

xhr.setRequestHeader("RequestVerificationToken",

The answer is in the revision and the someone edited it out. It's also mentioned briefly in the comments. I'm certainly not taking any credit, just trying to minimize confusion for anyone else that encounters this insanity making error in the future.

Sum None
  • 2,164
  • 3
  • 27
  • 32
  • A lot of articles on ASP.NET Core Razor Pages suggest putting `services.AddAntiforgery(o => o.HeaderName = "XSRF-TOKEN");` in the Startup.cs routine, so whatever name you put in your request header must match how it's set up in Startup.cs. – furman87 Jan 22 '22 at 19:13