Wednesday, June 24, 2026

ASP.NET Core Razor Page App Basic Setup for fetch API

Razor Page App Setup

STEP 1: Setup the configuration for Razor Page App in Program file

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
var app = builder.Build();
app.UseDeveloperExceptionPage();
app.UseStaticFiles();
app.UseRouting();
app.UseEndpoints(options =>
{
    options.MapRazorPages();
});
app.Run();
        
STEP 2: Create UI design for list of anchor tags

@page
@model Razor_Page_App_With_JS.Pages.IndexModel
@{
}

<ul>
    <li id="1"> <a data-item="i1" href="#">This is item number 1</a></li>
    <li id="2"> <a data-item="i2" href="#">This is item number 2</a></li>
    <li id="3"> <a data-item="i3" href="#">This is item number 3</a></li>
    <li id="4"> <a data-item="i4" href="#">This is item number 4</a></li>
    <li id="5"> <a data-item="i5" href="#">This is item number 5</a></li>
</ul>
<div id="displayHere">
    <h2>@Model.Message</h2>
</div>

        
STEP 3: Prepare Client side JavaScript Code for click events

The event listener is attached to all list items when the page is loaded. Then, if a user clicks any anchor, its associated event handler is executed and fetch API runs.

This in turn invokes the server-side handler method. This is given in STEP 4.


<script>
    // add event listener to all list items
    (function(){
        var items = document.querySelectorAll("a");
        items.forEach(anchr=>{
            console.log(anchr);
            anchr.addEventListener('click', async function(event){
                event.preventDefault();
                // fetch API
                fetch("/?handler=PrepareJsonData&id="+ anchr.getAttribute('data-item'),{
                    method:'GET'
                }).catch(err=> console.log("Error during reporting: " + err))
                .then(response=>{
                    if (!response.ok) {
                        throw new Error(`HTTP error! status: ${response.status}`);
                    }
                    return response.json(); // Parse the response as JSON
                })
                .then(data=> {
                    // display the data in UI
                    // Access the 'message' property from the returned JSON object
                    document.getElementById("displayHere").innerHTML = "<h2>RESULT: " + data.message + "</h2>";
                })
                .catch(err => console.log("Error during processing response: " + err));
            });
        });
    })();
</script>

        
STEP 4: Server side handler method

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using System.Text.Json; // for JsonSerializer

namespace Razor_Page_App_With_JS.Pages
{
    public class IndexModel : PageModel
    {
        [BindProperty]
        public string? Message { get; set; } = "";

        // return type IActionResult for returning JSON
        public IActionResult OnGetPrepareJsonData(string? id)
        {
            switch (id)
            {
                
                case "i1":
                    Message = "You have clicked list item number: " + id;
                    break;
                case "i2":
                    Message = "You have clicked list item number: " + id;
                    break;
                case "i3":
                    Message = "You have clicked list item number: " + id;
                    break;
                case "i4":
                    Message = "You have clicked list item number: " + id;
                    break;
                case "i5":
                    Message = "You have clicked list item number: " + id;
                    break;
                default:
                    Message = "Some Error !!!";
                    break;
            }

            // Return the Message as a JSON object
            // You can return a simple string, but it's generally good practice to return a JSON object
            // especially if you might return more data in the future.
            return new JsonResult(new { message = Message });
        }
    }
}

ASP.NET Core Razor Pages Radio Button Selection Change

Step1. Set configuration for ASP.NET Core Razor Page in Program file

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();

var app = builder.Build();

app.UseDeveloperExceptionPage();

app.UseRouting();

app.MapRazorPages();

app.Run();
Step2. HTML form with Input controls and Button with Script
@page
@model RazorPageWithRadioButtonsChange.Pages.IndexModel
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

<div align="center">
    <h1>ASP.NET Core Razor Pages Radio Button Selection Change</h1>
    <h4>Select a singer of your choice to get his or her Song Title</h4>
</div>
<div style="border-color:red;padding:10px;border-style:dashed;width:40%;margin-left:30%">
    <form id="singerForm" method="post">

        @Html.AntiForgeryToken()

        <label>Select your most favorite singer </label><br />
        <input type="radio" id="kishore" name="singer" value="kishore" />
        <label for="kishore">Kishore</label><br />

        <input type="radio" id="rafi" name="singer" value="rafi" />
        <label for="rafi">Rafi</label><br />

        <input type="radio" id="lata" name="singer" value="lata" />
        <label for="lata">Lata</label><br />

        <input type="radio" id="asha" name="singer" value="asha" />
        <label for="asha">Asha</label><br />

    </form>

    <h3 id="songTitleDisplay"></h3>
</div>


<script>
    const radios = document.querySelectorAll('input[type="radio"][name="singer"]');
    const songTitleDisplay = document.getElementById('songTitleDisplay'); // Get the display element

    // Get the anti-forgery token from the hidden input field
    const antiForgeryToken = document.querySelector('input[name="__RequestVerificationToken"]')?.value;

    // Add event listener to all radio buttons
    radios.forEach(radio => {
        radio.addEventListener('change', function(){
            console.log('Selected radio ID:', radio.id); // Log the ID being sent

            if (!antiForgeryToken) {
                songTitleDisplay.innerText = "Error: Anti-forgery token missing.";
                return; // Stop execution if token is missing
            }

            // fetch api to post selected singer name to server
            // server will process accordingly and will return a song of the singer
            fetch('?handler=Post', { // Use ?handler=Post to target the OnPost handler explicitly
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                    'RequestVerificationToken': antiForgeryToken // Include the token
                },
                body: JSON.stringify({ singer: radio.id })
            })
            .then(res => {
                if (!res.ok) {
                    // Handle HTTP errors (e.g., 400 Bad Request, 500 Internal Server Error)
                    console.error(`HTTP error! Status: ${res.status}`);
                    return res.text().then(text => { // Read response as text for better error messages
                        console.error('Server response:', text);
                        songTitleDisplay.innerText = `Error: ${res.status} - ${text.substring(0, 100)}`; // Display part of the error
                        throw new Error(`Server responded with status ${res.status}`);
                    });
                }
                return res.json(); // Parse the JSON response
            })
            .then(song => {
                // Received song of selected singer
                console.log('Received song:', song);
                songTitleDisplay.innerText = `Song Title: ${song}`; // Display the song title on the page
            })
            .catch(err => {
                console.error('Error occurred during data sending or processing:', err);
                songTitleDisplay.innerText = 'An error occurred while fetching the song.';
            });
        });
    });
</script>
Step3. Backend code with OnPost event handler
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using System.Threading.Tasks;

namespace RazorPageWithRadioButtonsChange.Pages
{
    public class IndexModel : PageModel
    {
        public string? title { get; set; }

        // The OnPost handler that receives the AJAX request
        public async Task<ActionResult> OnPost([FromBody] InputModel model)
        {
            await Task.Delay(1);

            // Check if the model state is valid (e.g., if 'singer' property exists)
            if (ModelState.IsValid)
            {
                // Ensure the 'singer' value from the client (radio.id) matches these cases (e.g., "kishore" vs "Kishore")
                switch (model?.singer)
                {
                    case "kishore":
                        title = "Ek Rasta Hai Zindagi";
                        break;
                    case "rafi":
                        title = "Tujhko Pukare Mera Pyar";
                        break;
                    case "lata":
                        title = "Ram Teri Ganga Maili Ho Gayi";
                        break;
                    case "asha":
                        title = "Raat Baaki Baat Baaki";
                        break;
                    default:
                        title = "Singer not found or invalid selection.";
                        break;
                }

                // Return the 'title' string as a JSON response.
                // The client-side JavaScript will receive this string.
                return new JsonResult(title);
            }
            else
            {
                // If model state is invalid (e.g., 'singer' property was null or not sent correctly)
                // Return a BadRequest with model errors for better debugging on the client side.
                return BadRequest(ModelState);
            }
        }
    }

    // This class defines the structure of the data expected from the client-side JSON.
    public class InputModel
    {
        public string? singer { get; set; } // Must match the key in JSON.stringify({ singer: ... })
    }
}
Next:

Hot Topics