Thursday, August 7, 2025

Building a Real-Time Chat Application with ASP.NET Core SignalR and JavaScript Client

Building a Real-Time Chat Application with ASP.NET Core SignalR and JavaScript

Introduction

Real-time communication is essential for modern web applications. In this article, we’ll walk through building a simple chat application using ASP.NET Core SignalR for the backend and a JavaScript/HTML client for the frontend. You’ll learn how to set up the server, configure CORS, and create a web client that enables users to exchange messages instantly.

Prerequisites

  • .NET SDK
  • Basic knowledge of C#
  • A code editor (e.g., Visual Studio Code)
  • Python (for running a local web server for the HTML client)

Step 1: Create the ASP.NET Core SignalR Project

Open a terminal and run:

dotnet new webapi -n SignalRApiDemo --no-https

Navigate to the project folder:

cd SignalRApiDemo

Step 2: Add SignalR Support

Add the SignalR NuGet package (if not already included):

dotnet add package Microsoft.AspNetCore.SignalR

Step 3: Implement the ChatHub

Create a new file ChatHub.cs:

using Microsoft.AspNetCore.SignalR;

namespace SignalRApiDemo
{
    public class ChatHub : Hub
    {
        public async Task SendMessage(string user, string message)
        {
            await Clients.All.SendAsync("ReceiveMessage", user, message);
        }
    }
}

Step 4: Configure SignalR and CORS in Program.cs

Update Program.cs to register SignalR and configure CORS for your local web client:

using SignalRApiDemo;
var builder = WebApplication.CreateBuilder(args);

builder.Services.AddSignalR();
//builder.Services.AddSignalR().AddAzureSignalR("<connection_string>");
//builder.Services.AddSignalR().
AddAzureSignalR(builder.Configuration["AzureSignalR:ConnectionString"]);
builder.Services.AddCors(options => { options.AddDefaultPolicy(policy => { policy.WithOrigins("http://localhost:8080") .AllowAnyHeader() .AllowAnyMethod() .AllowCredentials(); }); }); var app = builder.Build(); app.MapHub<ChatHub>("/chathub"); app.UseCors(); app.Run();

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*",
  "SignalR": {
    "ConnectionString":
    "Endpoint=https://rg2signalrr.service.signalr.net;AccessKey=;Version=1.0;"
  }
}

Step 5: Build and Run the Server

Build and start your server:

dotnet build
dotnet run

By default, the server runs on http://localhost:5000.

Step 6: Create the HTML/JavaScript Client

Create a file named test.html:

<!DOCTYPE html>
<html>
<head>
    <title>SignalR Chat Test</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/microsoft-signalr/7.0.5/signalr.min.js"></script>
</head>
<body>
    <h2>SignalR Chat Test</h2>
    <input id="userInput" type="text" placeholder="User" />
    <input id="messageInput" type="text" placeholder="Message" />
    <button onclick="sendMessage()">Send</button>
    <ul id="messagesList"></ul>

    <script>
        const connection = new signalR.HubConnectionBuilder()
            .withUrl("http://localhost:5000/chathub", { withCredentials: false })
            .build();

        connection.on("ReceiveMessage", (user, message) => {
            const li = document.createElement("li");
            li.textContent = `${user}: ${message}`;
            document.getElementById("messagesList").appendChild(li);
        });

        async function start() {
            try {
                await connection.start();
                console.log("Connected to SignalR hub");
            } catch (err) {
                console.error(err);
                setTimeout(start, 2000);
            }
        }

        start();

        function sendMessage() {
            const user = document.getElementById("userInput").value;
            const message = document.getElementById("messageInput").value;
            connection.invoke("SendMessage", user, message).catch(err => console.error(err));
        }
    </script>
</body>
</html>

Step 7: Serve the HTML Client

To avoid CORS issues, serve your HTML file using a local web server. In the folder containing test.html, run:

python -m http.server 8080

Open your browser and go to:

http://localhost:8080/test.html

Step 8: Test the Chat Application

  • Open the chat page in multiple browser windows or tabs.
  • Enter a username and message, then click "Send".
  • Messages should appear instantly in all open clients.


Conclusion

You now have a working real-time chat application using ASP.NET Core SignalR and a JavaScript client. This setup can be extended for more advanced features like private messaging, user lists, or notifications.


Let me know if you want to add code snippets, diagrams, or deployment instructions!


-----------------------------------------------------------------------------------------------------------------------
Building a Real-Time Chat Application with ASP.NET Core SignalR and JavaScript Client

using SignalRApiDemo; //dotnet add package Microsoft.AspNetCore.SignalR

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
// Learn more about configuring OpenAPI at https://aka.ms/aspnet/openapi
builder.Services.AddOpenApi();
builder.Services.AddSignalR();
builder.Services.AddCors(options =>
{
    options.AddDefaultPolicy(policy =>
    {
        policy.WithOrigins("http://localhost:8080")
              .AllowAnyHeader()
              .AllowAnyMethod()
              .AllowAnyOrigin();
    });
});

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.MapOpenApi();
}

// Map SignalR hub endpoint
app.MapHub<ChatHub>("/chathub");

app.UseCors();
app.Run();


using Microsoft.AspNetCore.SignalR;

namespace SignalRApiDemo
{
    public class ChatHub : Hub
    {
        // Example method: send message to all clients
        public async Task SendMessage(string user, string message)
        {
            await Clients.All.SendAsync("ReceiveMessage", user, message);
        }
    }
}


{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*",
  "SignalR": {
    "ConnectionString":
    "Endpoint=https://rg2signalrr.service.signalr.net;AccessKey=;Version=1.0;"
  }
}


build: dotnet build
run: dotnet run

Save this file as Test.html in folder.
Open that folder in cmd, and run 'python -m http.server 8080'
Open two browser windows and access 'http://localhost:8080/test.html'

<!DOCTYPE html>
<html>
<head>
    <title>SignalR Chat Test</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/microsoft-signalr/7.0.5
/signalr.min.js"></script>
</head>
<body>
    <h2>SignalR Chat Test</h2>
    <input id="userInput" type="text" placeholder="User" />
    <input id="messageInput" type="text" placeholder="Message" />
    <button onclick="sendMessage()">Send</button>
    <ul id="messagesList"></ul>

    <script>            
        const connection = new signalR.HubConnectionBuilder()
        .withUrl("http://localhost:5000/chathub", { withCredentials: false })
        .build();

        connection.on("ReceiveMessage", (user, message) => {
            const li = document.createElement("li");
            li.textContent = `${user}: ${message}`;
            document.getElementById("messagesList").appendChild(li);
        });

        async function start() {
            try {
                await connection.start();
                console.log("Connected to SignalR hub");
            } catch (err) {
                console.error(err);
                setTimeout(start, 2000);
            }
        }

        start();

        function sendMessage() {
            const user = document.getElementById("userInput").value;
            const message = document.getElementById("messageInput").value;
            connection.invoke("SendMessage", user, message).catch(
                 err => console.error(err));
        }
    </script>
</body>
</html>

OutPut:



No comments:

Post a Comment

Featured Post

Automating Azure DevOps Task Tracking: A Complete PowerShell Solution

Automating Azure DevOps Task Tracking: A Complete PowerShell Solution param (     [ Parameter ( Mandatory = $false )]     [ Alias ( 'F...

Popular posts