SignalR

SignalR and its needed components are installed with a VS 2022 project, so I'm not covering any of the NuGet packages required here.
The first task is to map SignalR inside your Startup.cs file:

public class Startup
{
	public void Configuration(IAppBuilder app)
	{
		// Any connection or hub wire up and configuration should go here
		app.MapSignalR();
	}
}

With that done, you'll need to create a Hub file. The name isn't important, nor is the Class Name (though they are probably the same). Here, the file is LikeHub.cs
There are 2 functions that can be used, though I only use SendCount() for the Like control at the bottom of pages.
The hubContext.Clients.All.sendCount() function is inside JavaScript, shown next.

using Microsoft.AspNet.SignalR;

namespace BenSawyer
{
	public class LikeHub : Hub
	{
		private static Microsoft.AspNet.SignalR.IHubContext hubContext = GlobalHost.ConnectionManager.GetHubContext();

		//public static void SendMessage(string message)
		//{
		//	hubContext.Clients.All.sendMessage(message);
		//}

		public static void SendCount(string page, int count)
		{
			hubContext.Clients.All.sendCount(page, count);
		}
	}
}

Next you'll need some JavaScript - this is inside Like.js
The UpdateCount() function is inside the Like.ascx user control.

$(document).ready(function () {

	var likeNotifier = $.connection.likeHub;

	// ================
	// client-side send() functions that will be called from the server-side
	// ================

	// we're not sending text for the Likes
	/*
	likeNotifier.client.sendMessage = function (message) {
		UpdateProgress(message);
	};
	*/

	likeNotifier.client.sendCount = function (page, count) {
		UpdateCount(page, count);
	};
});

Before looking at the JavaScript inside the Like user control, let's look at the HTML for the Like & Unlike buttons.
These are (2) distinct sections, since they have associated .svg maps for the 'thumbs up' & 'thumbs down' icons.
The partial HTML is below...

<button runat="server" id="btnLike" type="button" class="btn btn-success" title="Like this">
	<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-hand-thumbs-up" viewBox="0 0 16 16">
		<path d="M8.864.046C7.908-.193 etc."/>
	</svg>
	Like this<span class="ms-2" id="spanLike"></span>
</button>

<button runat="server" id="btnUnlike" type="button" class="btn btn-outline-danger" title="Unlike this">
	<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-hand-thumbs-down" viewBox="0 0 16 16">
		<path d="M8.864 15.674c-.956.24 etc."/>
	</svg>
	Unlike this<span class="ms-2" id="spanUnlike"></span>
</button>


A little more JavaScript called from the code-behind on Page_Load() inserts classes, based upon the calling page's name, into each button - along with the initial count...
For this page, the (2) classes would be: spanLikeSignalR & spanUnlikeSignalR. These classes aren't used for styling, just so we can find the correct <span> elements to update later.

function fnSetLikeCount(page, count) {
	var innerLike   = '<span class="spanLike'   + page + '">' + '(' + count + ')' + '</span>'
	var innerUnlike = '<span class="spanUnlike' + page + '">' + '(' + count + ')' + '</span>'

	var outerLike   = document.getElementById('spanLike');
	var outerUnlike = document.getElementById('spanUnlike');

	outerLike.innerHTML   = innerLike;
	outerUnlike.innerHTML = innerUnlike;
}

And, finally, the UpdateCount() function inside the user control. The first line is in the code behind.

// send the message to the Hub...
BenSawyer.LikeHub.SendCount(Name, count);

// Update the count
function UpdateCount(page, count) {

	// first check for correct page....
	if ($("#<%=hdnName.ClientID%>").val() != page)
		return;

	// get by ClassName here as it depends upon what the parent PageName is...
	var innerLike   = document.getElementsByClassName('spanLike'   + page)[0];
	var innerUnlike = document.getElementsByClassName('spanUnlike' + page)[0];

	innerLike.innerHTML   = '(' + count + ')';
	innerUnlike.innerHTML = '(' + count + ')';
}

Next...


optional below comment
Next...


optional below comment