Search code examples
c#ajaxasp.net-corerazor-pages

Ajax Call using Razor Page Handler Returns 400


Using asp.net core 3.1 and I'm trying to make a Post method call using ajax when dropdown is changed, the id value from the selected dropdown will be stored in a session, but upon changing the dropdown I encounter 400

Pages/Index.cshtml.cs

[Authorize]
[AuthorizeForScopes(ScopeKeySection = "DownstreamApi:Scopes")]
public class IndexModel : PageModel
{
    public void OnGet()
    {
    return _studentService.GetStudents();
    }

    public void OnPostUpdateStudent(string id)
    {
         HttpContext.Session.SetString("SelectedStudent", id);
    }
}

Pages/Shared/_Layout.cshtml

@{
    var studentList = HttpContextAccessor.HttpContext.Session.GetObject<List<SelectListItem>>("StudentList");
}
<select onchange="UpdateAll(this)" asp-items="studentList" class="form-control">
<option value="all">All Students</option>
</select>

site.js

function updateAll(element){
    updateStudent(element.value);
}

function updateStudent(id) {
    if (id != null && id != '') {
        $.ajax({
            type: "POST",
            url: "/Index?Handler=UpdateStudent",
            data: { id: id },
            success: function (result) {
            },
            failure: function (response) {
                console.log(response);
            }
        });
    }
}

Response:

Request URL: https://localhost:44383/Index?Handler=UpdateStudent
Request Method: POST
Status Code: 400 
Remote Address: 127.0.0.1:44383
Referrer Policy: strict-origin-when-cross-origin
date: Mon, 10 Oct 2022 08:11:42 GMT
server: Microsoft-IIS/10.0
x-powered-by: ASP.NET
:authority: localhost:44383
:method: POST
:path: /Index?Handler=UpdateStudent
:scheme: https
accept: */*
accept-encoding: gzip, deflate, br
accept-language: en-US,en;q=0.9
content-length: 0

Solution

    1. In cshtml, add

    @Html.AntiForgeryToken()

    2.The Ajax request should send the anti-forgery token in request header to the server. So, the modified Ajax request looks like:

       function updateStudent(id) {
        if (id != null && id != '') {
            $.ajax({
                type: "POST",          
                 url: "/Index?Handler=UpdateStudent",
                beforeSend: function (xhr) {
            xhr.setRequestHeader("XSRF-TOKEN",
                $('input:hidden[name="__RequestVerificationToken"]').val());
        },
                data: { id: id },
       
                success: function (result) {
                },
                failure: function (response) {
                    console.log(response);
                }
            });
        }
    }
    

    3.In startup, since the script sends the token in a header called X-CSRF-TOKEN, configure the antiforgery service to look for the X-CSRF-TOKEN header:

    services.AddAntiforgery(o => o.HeaderName = "XSRF-TOKEN");

    result:

    enter image description here