Saturday, July 15, 2023

ASP.NET Core - How to post a Razor Page form using Fetch API

Objective. To learn about JavaScript fetch API and formData. The fetch method takes two parameters. First parameter is the handler method which is defined in the Razor application and is invoked by the fetch API. The second parameter is all about the action method such as Get or Post and the resource is in the body or header etc.

Project
  • Open the Visual Studio. 
  • Create web project using ASP.NET Core Empty template.
  • Project name: AJAXWithRP
  • Solution name: AJAXWithRP
  • .NET Core version: 5.0
  • Add the AddRazorPages() into the IServiceCollection in Startup class.
  • Use MapRazorPages() as terminal middleware in Startup class.
Look at the below updated code in Startup class.

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

namespace AJAXWithRP
{
    public class Startup
    {
        // This method gets called by the runtime. Use this method to add services to the container.
        // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddRazorPages();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseRouting();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapRazorPages();
            });
        }
    }
}

  • Add a New Folder and rename it Pages.
  • Add a Razor Page in Pages folder and name it Index. Two files are generated which are Index.cshtml and Index.cshtml.cs

Index.cshtml
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
@page
@model AJAXWithRP.Pages.IndexModel
@{
}
Index.cshtml.cs
namespace AJAXWithRP.Pages
{
    public class IndexModel : PageModel
    {
        public void OnGet()
        {
        }
    }
}
Next step. Update the Index.cshtml to create a simple form as given below.
Index.cshtml

@page
@model AJAXWithRP.Pages.IndexModel
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@{
}

<h1>Post Form Data using Fetch API</h1>

<span id="msg" style="color:blue"></span>

<form id="form1" 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 () {
        const form = document.getElementById("form1");

        // attach onsubmit
        form.addEventListener("submit", async function (event) {
            // Event Method: Prevent a link from opening the URL
            // The preventDefault() method cancels the event if it is cancelable,
            // meaning that the default action that belongs to the event will not occur.
            // Clicking on a "Submit" button, prevent it from submitting a form
            event.preventDefault();

            // show some message in the span tag if the event occurs
            msg.innerHTML = "please wait...";

            // aysnchronous fetch ajax
            // fetch(resource url, options)
            // url refers the method which handles the event
            // https://developer.mozilla.org/en-US/docs/Web/API/fetch
            fetch(form.action, // action is handler: OnPostAsync method
                {
                    method: form.method, // GET or POST, here it is POST
                    body: new FormData(form) // form data sent. Here Name input control
                }
            )
                // if any exceptions - log them
                .catch(err => console.log("network error: " + err))
                // promise success then response stream
                .then(response => {
                    // read json from the response stream
                    // and display the data
                    // server returns JsonResult which is handled by JS
                    // using the json() method
                    response.json().then(data => { msg.innerHTML = data });
                })
        });
    })();
</script>
Note that despite the method being named json(), the result is not JSON but is instead the result of taking JSON as input and parsing it to produce a JavaScript object. This is why in server side code we use JsonResult as return type. The json() method of the Response interface takes a Response stream and reads it to completion. It returns a promise which resolves with the result of parsing the body text as JSON.

Index.cshtml.cs: Update its code.

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using System.ComponentModel.DataAnnotations;
using System.Threading.Tasks;

namespace AJAXWithRP.Pages
{
    public class IndexModel : PageModel
    {
        [BindProperty]
        [Required]
        public string Name { get; set; }

        // OnPost return type must be JsonResult 
        // so that JS can handle it using json() method 
        public async Task<IActionResult> OnPostAsync()
        {
            // not required in actual project 
            await Task.Delay(500); // 500 milliseconds

            if (!ModelState.IsValid)
            {
                return new JsonResult("OnPostAsync Error: some error occured.");
            }

            return new JsonResult("The JSON result is : " + Name);

        }
    }
}

Run the Application: Input some text in the textbox and press submit button. We get the following output.


Updated on 15 July 2023

No comments:

Post a Comment

Hot Topics