Let’s create a real-time chatting application(SignalR) with ASP.Net Core and Angular with this post. In my previous post SignalR was implemented using ASP.Net MVC, please have an overview if needed by following the link: https://shashangka.com/2017/12/30/user-specific-notifications-using-asp-net-mvc-signalr/ .
ASP.NET Core SignalR :
According to Microsoft docs, ASP.NET Core SignalR is an open-source library that simplifies adding real-time web functionality to apps. Real-time web functionality enables server-side code to push content to clients instantly.
Server Side:
Let’s get started creating and configure server side application by Visual Studio 2019.
Package Installation:
After successfully creating the application, install latest package from NuGet:
Microsoft.AspNetCore.SignalR.Core
SignalR Hub:
SignalR Hub is basically centre of client server communication. Below is the hub class.
public class ChatHub : Hub
{
private readonly static ConnectionMapping _connections = new ConnectionMapping();
public DataAccess _objData = null;
public async Task SendMessage(vmMessage _message)
{
//Receive Message
List ReceiverConnectionids = _connections.GetConnections(_message.Receiverid).ToList();
if (ReceiverConnectionids.Count() > 0)
{
//Save-Receive-Message
try
{
_objData = new DataAccess();
_message.IsPrivate = true;
_message.Connectionid = String.Join(",", ReceiverConnectionids);
await _objData.saveUserChat(_message);
await Clients.Clients(ReceiverConnectionids).SendAsync("ReceiveMessage", _message);
}
catch (Exception) { }
}
}
public override async Task OnConnectedAsync()
{
var httpContext = Context.GetHttpContext();
if (httpContext != null)
{
try
{
//Add Logged User
var userName = httpContext.Request.Query["user"].ToString();
//var UserAgent = httpContext.Request.Headers["User-Agent"].FirstOrDefault().ToString();
var connId = Context.ConnectionId.ToString();
_connections.Add(userName, connId);
//Update Client
await Clients.All.SendAsync("UpdateUserList", _connections.ToJson());
}
catch (Exception) { }
}
}
public override async Task OnDisconnectedAsync(Exception exception)
{
var httpContext = Context.GetHttpContext();
if (httpContext != null)
{
//Remove Logged User
var username = httpContext.Request.Query["user"];
_connections.Remove(username, Context.ConnectionId);
//Update Client
await Clients.All.SendAsync("UpdateUserList", _connections.ToJson());
}
//return base.OnDisconnectedAsync(exception);
}
}
Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddSignalR();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
endpoints.MapHub("/chathub");
});
}
Client Side:
After completing server side work, let’s configure client side angular application.
Package Installation:
Go to package.json file to add SignalR client package:
/signalr": "1.1.4
Copy library to wwwroot folder by using gulp task below:
gulp.src('./node_modules//signalr/dist/browser/**/*.+(js|js.map)')
.pipe(gulp.dest(root_path.package_lib + 'signalr'));
Open index.html to linkup library.
Chat Component:
import { Component, OnInit, ElementRef, ViewChild, EventEmitter, OnDestroy } from '/core';
import { FormBuilder, FormGroup, FormControl, Validators } from '/forms';
import { Title } from '/platform-browser';
import { DataService } from '../../shared/service';
import { Paging } from '../../shared/paging';
import { Message } from '../../shared/models/message';
declare var signalR: any;
({
selector: 'app-chat',
templateUrl: './app/backoffice/chat/component.html',
providers: [DataService, Paging]
})
export class ChatComponent implements OnInit, OnDestroy {
public title: any;
public res: any;
public resmessage: string;
public loggedUserid: number = 0;
public loggedUsername: string;
//API
public _chatUrl: string = 'api/chat/userChat';
//Chat
public onlineUser: any = [];
public chatUsername: string = null;
public chatConnection: string;
public chatMessages: any = [];
public chatMessage: Message = null;
public _hubConnection;
constructor(
private titleService: Title,
private _dataService: DataService) {
var loggedUser = JSON.parse(localStorage.getItem('loggedUser'));
this.loggedUsername = loggedUser.userName;
this.loggedUserid = loggedUser.userId;
}
ngOnInit() {
this.titleService.setTitle("Chat");
this.signalrConn();
}
signalrConn() {
//Init Connection
this._hubConnection = new signalR.HubConnectionBuilder().withUrl("http://localhost:63742/chatHub?user=" + this.loggedUsername).build();
//Call client methods from hub to update User
this._hubConnection.on('UpdateUserList', (onlineuser) => {
var users = JSON.parse(onlineuser);
this.onlineUser = [];
for (var key in users) {
if (users.hasOwnProperty(key)) {
if (key !== this.loggedUsername) {
this.onlineUser.push({
userName: key,
connection: users[key]
});
}
}
}
});
//Call client methods from hub to update User
this._hubConnection.on('ReceiveMessage', (message: Message) => {
this.chatUsername = message.senderid;
this.chatLog();
});
//Start Connection
this._hubConnection
.start()
.then(function () {
console.log("Connected");
}).catch(function (err) {
return console.error(err.toString());
});
}
sendMessage(message) {
//Send Message
if (message != '') {
this.chatMessage = new Message();
this.chatMessage.senderid = this.loggedUsername;
this.chatMessage.receiverid = this.chatUsername;
this.chatMessage.message = message;
this.chatMessage.messagestatus = "sent";
this.chatMessages.push(this.chatMessage);
this._hubConnection.invoke('SendMessage', this.chatMessage);
}
}
chooseUser(user) {
this.chatUsername = user.userName;
this.chatLog();
}
chatLog() {
//ChatLog
var param = { Senderid: this.loggedUsername, Receiverid: this.chatUsername };
var getchatUrl = this._chatUrl + '?param=' + JSON.stringify(param);
this._dataService.get(getchatUrl)
.subscribe(
response => {
this.res = response;
if (this.res != null) {
var chatLog = this.res.resdata;
this.chatMessages = [];
if (chatLog.length > 0) {
for (var i = 0; i < chatLog.length; i++) {
if (this.loggedUsername === chatLog[i].senderid) {
chatLog[i].messagestatus = "sent";
}
else {
chatLog[i].messagestatus = "received";
}
//Push-Data
this.chatMessages.push(chatLog[i]);
}
}
}
}, error => {
console.log(error);
}
);
}
ngOnDestroy() {
//Stop Connection
this._hubConnection
.stop()
.then(function () {
console.log("Stopped");
}).catch(function (err) {
return console.error(err.toString());
});
}
}
Component Html:
SignalR Messaging
Online Users
{{chatUsername}}
0">
{{msg.senderid}} | {{msg.messagedate | date : "shortTime"}}
{{msg.message}}
{{msg.message}}
No Message Found..
Finally:
Let’s run both application to test messaging operation. As we can see from below image how our real-time chatting application is working.
Download/clone full source code from Hope this will help 🙂
S.kavyasri says:
Hi,
I came across this page. I want to implement chat application using .NetCore and angular. I cloned this project but i was unable to run the cloned project. I request You to guide me How to run to see the final picture.
Thankyou
kavya
Shashangka Shekhar says:
Please follow : https://shashangka.com/2018/06/15/dynamic-highchart-asp-net-core-angular6/
Go to Task Runner Explorer section, see required libraries are loaded.
Thanks.
M Rahman says:
So much helpful dada … great
Sunil says:
Nice article but css files are missing.
Bitan says:
Getting the error : Error: Failed to invoke ‘SendMessage’ due to an error on the server.