Ajax post with C# Handler and XSRF-TOKEN

Joseph Kashishian 85 Reputation points
2025-11-21T15:34:44.2166667+00:00

This question is for Web pages with .NET, C#, and Ajax.

I'm having an issue with a ajax calling working with the XSRF-TOKEN" and it's not calling the handler in the .CS. I think I need to do something with my ajax call to validate the token.

In my startup I have

        var antiforgery = app.ApplicationServices.GetRequiredService<IAntiforgery>();

        app.Use((context, next) =>

        {

            var requestPath = context.Request.Path.Value;

            if (string.Equals(requestPath, "/", StringComparison.OrdinalIgnoreCase)

                || string.Equals(requestPath, "/index.html", StringComparison.OrdinalIgnoreCase))

            {

                var tokenSet = antiforgery.GetAndStoreTokens(context);

                context.Response.Cookies.Append("XSRF-TOKEN", tokenSet.RequestToken!,

                    new CookieOptions { HttpOnly = false });

            }

            return next(context);

        });

index cs

using System.IO;

using System.Data.SqlClient;

using System.Collections.Generic;

using Microsoft.AspNetCore.Http;

using Microsoft.Extensions.Configuration;

using Microsoft.AspNetCore.Mvc.RazorPages;

using Microsoft.AspNetCore.Mvc;

using System;

namespace RecoveryHouse.Pages.ReferralRequest

{

public class IndexModel : PageModel

{

    public void OnGet()

    {

    }

    [HttpPost]

    [ValidateAntiForgeryToken]

    public IActionResult OnPostGetTime(string name)

    {

        PersonModel person = new PersonModel

        {

            Name = name,

            DateTime = DateTime.Now.ToString()

        };

        return new JsonResult(person);

    }

}

}

public class PersonModel

{

/// <summary>

/// Gets or sets Name.

/// </summary>

public string Name { get; set; }

/// <summary>

/// Gets or sets DateTime.

/// </summary>

public string DateTime { get; set; }

}

Index CSHTML

@page

@model RecoveryHouse.Pages.ReferralRequest.IndexModel

@addTagHelper*, Microsoft.AspNetCore.Mvc.TagHelpers

<!DOCTYPE html>

<html>

<head>

<meta name="viewport" content="width=device-width" />

<title>Index</title>

</head>

<body>

@Html.AntiForgeryToken()

<input type="text" id="txtName" />

<input type="button" id="btnGet" value="Get Current Time" />

<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script> 

<script type="text/javascript">

    $(function () {

        $("#btnGet").click(function () {

            $.ajax({

                type: "POST",

                url: "/Index?handler=GetTime",

                beforeSend: function (xhr) {

                    xhr.setRequestHeader("XSRF-TOKEN",

                        $('input:hidden[name="__RequestVerificationToken"]').val());

                },

                data: {"name": $("#txtName").val() },

                success: function (response) {

                    alert("Hello: " + response.Name + ".\nCurrent Date and Time: " + response.DateTime);

                },

                error: function (response) {

                    alert(response.responseText);

                }

            });

        });

    });

</script>

</body>

</html>

Developer technologies | ASP.NET Core | Other

Answer accepted by question author
SurferOnWww 6,106 Reputation points
2025-11-22T01:13:43.0666667+00:00

Please try the followings:

(1) Add form tag to .cshtml.

(2) Create the FormData object form the form tag.

(3) Send the FormData using jQuery ajax or fetch API.

Shown below are the samples:

Model

namespace RazorPages.Models
{
    public class PersonModel
    {
        public string Name { get; set; } = string.Empty;
        public string DateTime { get; set; } = string.Empty;
    }
}

.cshtml.cs

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using RazorPages.Models;

namespace RazorPages.Pages
{
    public class AjaxPostModel : PageModel
    {
        public void OnGet()
        {
        }

        [BindProperty]
        public PersonModel Model { get; set; } = default!;

        public IActionResult OnPost()
        {
            if (Request.Headers.XRequestedWith == "XMLHttpRequest")
            {
                string name = Model.Name;
                string dateTime = Model.DateTime;
                return Content($"Name: {name}, DateTime: {dateTime}");
            }
            else
            {
                return BadRequest();
            }
        }
    }
}

.cshtml

@page

@model RazorPages.Pages.AjaxPostModel
@{
    ViewData["Title"] = "AjaxPost";
}

<h1>AjaxPost</h1>

<hr />

<form method="post">
    <input type="text" name="name" />
    <br />
    <input type="text" name="datetime" />
    <br />
</form>

<input type="button" id="ajaxPost" value="POST" />

<div id="result"></div>

@section Scripts {
    <script type="text/javascript">
        //<![CDATA[
        document.getElementById("ajaxPost")
            .addEventListener('click', async () => {
                const fd = new FormData(document.querySelector("form"));
                const result = document.getElementById("result");                

                const param = {
                    method: "POST",
                    body: fd,
                    // set X-Requested-With in request header
                    headers: { 'X-Requested-With': 'XMLHttpRequest' }
                }

                const response = await fetch("/ajaxpost", param);

                if (response.ok) {
                    const data = await response.text();
                    result.innerText = data;
                } else {
                    result.innerText = "response.ok is false";
                }
            });
        //]]>
    </script>
}

CSRF token in cookie sent to the server:

enter image description here

CSRF token in hidden field sent to the server:

enter image description here

Result

enter image description here

To see if the validation of CSRF-token is working, delete cookie of browser after the browser has received the response of OnGet() method and send the FormData by clicking the [POST] button. The ASP.NET will return 400 Bad request without invoking the OnPost() method.

Was this answer helpful?

0 comments No comments

6 additional answers

Sort by: Oldest
  1. Joseph Kashishian 85 Reputation points
    2026-01-02T17:37:53.03+00:00

    the issue is with my startup and Program file. I have some conflicts with the run commands.

    I was able to get it to run if I take out the webBuilder.UseStartup<Startup>(); and put everything in program file but unfortunately, I have a lot of important things going on. There is an issue with I have the app.run and the CreateHostBuilder(args).Build().Run(); and still trying how to separate. Attached is the code in my startup and program.

    Was this answer helpful?


  2. Joseph Kashishian 85 Reputation points
    2026-01-06T15:29:11.7733333+00:00

    I added this to the Startup.CS and it worked!!!!

    services.AddRazorPages()

     .AddJsonOptions(options => options.JsonSerializerOptions.PropertyNamingPolicy = null);
    

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

    Was this answer helpful?

    1 person found this answer helpful.

Your answer

Answers can be marked as 'Accepted' by the question author and 'Recommended' by moderators, which helps users know the answer solved the author's problem.