(ASP.NET Core AJAX) Ajax based POST of a Razor Page

How to POST an ASP.NET Core Razor FORM through an Ajax Request. We discuss a practical approach that is to-the-point and easy to understand. The given code is ready to copy-paste!
(Rev. 06-Nov-2022)

Categories | About |     |  

Parveen,

Linking an Ajax Request to an "OnPost" handler

Javascript has fetch API that can be used to POST/GET a FORM to an ASP.NET Core application on the server side.

The following snippet shows how a single line of javascript fetch function can be used to send an AJAX request to OnPostAsync function on the server side. The same function handles any exceptions and also processes the server response.


<script type="text/javascript">


  (function () {

// ---------- form submit handler --------------// 

    // aysnchronous fetch ajax 
    fetch(
      "/Index", // <---- sent to OnPostAsync 
        {
          method: "POST",

          body: new FormData(form)
        }
      )
        // if any exceptions - log them 
        .catch(err => console.log("network error: " + err))

        .then(response => {

          // read json from the response stream 
          // and display the data 
          response.json().then(data => { pw.innerHTML = data });

        })
    })();

</script>

Video Explanation

Please watch the following youtube video:

Receiver on the Server Side

The ONLY requirement on the server side handler is that it should return a JsonResult - which is a string in json format. JsonResult is a type of IActionResult. We have seen earlier that FileResult is also an IActionResult, and that a FileResult is used for serving a file download to the browser.

NOTE: if an instance of JsonResult is not returned, the function will not respond to any AJAX call from the javascript side.

Following is a skeleton -

public async Task<IActionResult> OnPostAsync()
{

  if (!ModelState.IsValid)
  {

    return new JsonResult("JSONResponse: Error occurred. Please retry.");

  }

  // some processing occurs 
  // that causes some delay 
  await Task.Delay(500);

  String jsonResponse = "JSONResponse: some string in json format ";

  // THIS IS IMPORTANT: return JsonResult 
  // this function sends the correct Http response 
  // and, if required, also formats a string 
  // into a json type 
  return new JsonResult (jsonResponse);

}

Walkthrough on a simple AJAX Post

This is a three step walkthrough that creates a razor FORM of a one textbox. When the submit button is clicked, a please wait is shown and the form data in the textbox is sent to the server.

The server echoes back the same data - which is ultimately displayed to the user.

Step 1 of 3: Configure the Startup.cs File

First create an ASP.NET Core project using the empty template. An empty template will add just the required files. So it will be easier to work with and easier to understand also.

Configure the Startup.cs file to add support for razor pages.

using Microsoft.AspNetCore.Builder;

using Microsoft.AspNetCore.Hosting;

using Microsoft.Extensions.DependencyInjection;

using Microsoft.Extensions.Hosting;

namespace AjaxForm
{

  public class Startup
  {

    public void ConfigureServices(IServiceCollection services)
    {

      // add support for razor pages 
      services.AddRazorPages();

    }

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {

      if (env.IsDevelopment())
      {

        app.UseDeveloperExceptionPage();

      }

      app.UseRouting();

      // set razor pages as the 
      // terminal middleware 
      app.UseEndpoints(endpoints =>
      {

        endpoints.MapRazorPages();

      });

    }

  }

}

Step 2 of 3: Add a razor page called Index

Next add a folder called "Pages" to the project and right click it to add a new razor page called Index. For details and the images please refer the linked video below.

Write this markup in the index.cshtml razor page -

@page

@model AjaxForm.Pages.IndexModel

@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

<h1>Ajax Form</h1>

<span id="pw" style="color:red"></span>

<form method="post">

  <table>

    <tr>
      <td>
        <label asp-for="Name"></label>
      </td>
      <td>
        <input asp-for="Name" />
      </td>
    </tr>

    <tr>
      <td colspan="2" style="text-align:right">

        <input type="submit" />

      </td>
    </tr>

  </table>

</form>

<script type="text/javascript">

  (function () {

    // only one form - select it! 
    const form = document.forms[0];

    // attach onsubmit 
    form.addEventListener("submit", async function (event)
    {

      event.preventDefault();

      // show please wait, a gif can be used instead 
      pw.innerHTML = "please wait...";

      // aysnchronous fetch ajax 
      fetch(form.action,
        {
          method: form.method,

          body: new FormData(form)
        }
      )
        // if any exceptions - log them 
        .catch(err => console.log("network error: " + err))

        .then(response => {

          // read json from the response stream 
          // and display the data 
          response.json().then(data => { pw.innerHTML = data });

        })
    });

  })();

</script>

The above markup creates a simple form with just one html5 input text bound to a property called Name. We have used asp.net tag helpers for creating this form.

Ajax communication is executed with the help of the fetch method of javascript. This is the easiest and simplest way. But do check browser compatibility for critical use cases.

Step 3 of 3: The Index.cshtml.cs backing class

Open the file index.cshtml.cs and write this code in the IndexModel backing class:

IMPORTANT NOTE: The return type of the OnPost method MUST be a JsonResult, otherwise it will NOT receive the Ajax call!
using Microsoft.AspNetCore.Mvc;

using Microsoft.AspNetCore.Mvc.RazorPages;

using System.ComponentModel.DataAnnotations;

using System.Threading.Tasks;

namespace AjaxForm.Pages
{

  public class IndexModel : PageModel
  {

    [BindProperty]
    [Required]
    public string Name { get; set; }

    // OnPost return type is JsonResult 
    public async Task<IActionResult> OnPostAsync()
    {

      // artifical delay 
      await Task.Delay(500);

      if (!ModelState.IsValid)
      {

        return new JsonResult("JSONResponse: Error occurred. Please retry.");

      }

      return new JsonResult("JSONResponse: (OK) " + Name);

    }

  }

}

Run the project to see that the form gets posted as an Ajax call. It shows a "please wait" message and echoes back the data that was posted.


This Blog Post/Article "(ASP.NET Core AJAX) Ajax based POST of a Razor Page" by Parveen is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.