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:
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.