Ajax call to a ViewComponent in .net core 3.1, Razor pages, for loading on demand part of a web page.

Published by Marian Galie-Andriescu on

The technique described in the title of this article is a great way to reuse parts of the functionality build for a web page in different parts of of the website, and at the same time to implement a great user experience because only part of the page is reloading which is faster and reduces the time the user is just looking at a reload which is quite boring.

There are a lot of articles explaining Ajax calls and Razor View Components, but most of them do not exactly explain how to use a Ajax call to reload a Razor view Component, they mostly deal with a Ajax call in the context of a MVC web application. The important thing to realize in Razor pages is the implicit agreement made between the front end and the back end, more precisely the fact that in the back end Razor will expect the method name to start with OnGet for a Get HTTP call.

But let’s go to the code. This code is part of MyDemoPage.cshtml:

@page
@model RazorPagesDemo.Pages.AjaxExamplePages
.MyDemoModel
@{
    ViewData["Title"] = "Details";
}

<script>
    $(document).ready(function () {
        $(".displayReloadLink").click(function () {
            $.ajax({
                url: "?handler=CallMyViewComponent",
                method: "GET",
                data: { id: 4 },
                success: function (data) {
                    $("#partialDiv").html("");
                    $("#partialDiv").html(data);
                }
            });
        });
    });
</script>

<div>
<a>
  <p class="displayReloadLink">Reload part of page</p>
 </a></div>

<div id="partialDiv">
  @await Component.InvokeAsync("MyViewComponent", new { Id = 4 })
</div>

This code is part of the MyDemoPage.cshtml.cs:

using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;

namespace RazorPagesDemo.Pages.AjaxExamplePages
{
    public class MyDemoModel : PageModel
    {
      public ActionResult OnGetCallMyViewComponent(int id)
      {
        return ViewComponent("MyViewComponent", new { Id = id });
       }
    }
}

This code is part of the MyViewComponent.Cs from ViewComponents map in the project:

using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace RazorPagesDemo.ViewComponents
{
   public class MyViewComponent : ViewComponent
   {
     public async Task<IViewComponentResult> InvokeAsync(int Id)
     {
         myViewData = new MyViewModelDTO
         { 
             NumberOfItems = Id 
         }
         return View(myViewData);
     }
   }
}

If the ViewComponent happens to implement chat functionality using SingnalR, please keep in mind that any javascript file used in the ViewComponent will not be reloaded, and as a result all variables used in the java script already have values, and you may need to reinitialize those, especially the connection to the hub. Otherwise you can end up with funny bugs, as for example registering to the same SignalR event multiple times, as many as the user clicked on the “Reload part of page”, with the end result being the same chat text being displayed multiple times in the chat div on the webpage 🙂 To prevent this, use the stop() function as it can be seen in the javascript code below:

"use strict";

if (Connection!=undefined) {
    Connection.stop();
}

var Connection = new signalR.HubConnectionBuilder().withUrl("/chatHub").build();

Special thanks to Meena Vyas, she was the one to actually discover and implement all the details for the successful implementation of all the code in this article:

https://www.linkedin.com/in/meena-vyas-52b1b2151/