Notifications system in .NET 6 and Angular with SignalR
Notifications can be very useful in any application and add very interesting features in terms of user experience. Here, we want to create a notification that is triggered by the backend without the frontend requesting. This means that the backend pushes the data towards the frontend.
We will be using SignalR , a ASP.NET core library that adds real-time web functionality to applications.
This article will contains two parts:
- Backend Server
- Frontend Application
Backend Server
- Create an ASP.NET core Web Api and choose .NET 6 as a framework.
- In the solution add a Class Library that will contains the buisiness logic , I called it Domain.
- We add the needed Product model
Your solution should look like this :
- Next, add this code to your Domain layer to include the needed library, since SignalR now is part of the framework and you don’t need to install it separately
<ItemGroup>
<FrameworkReference Include="Microsoft.AspNetCore.App" />
</ItemGroup>
- Now let’s add a folder I called it Hub, feel free to name it however you want, this folder will hold the notification logic.
- In this folder we add our Notification class :
- Then we create an Interface named INotificationHub :
The name of the method here is very important, it is the connection between our boadcasting server and our listeners. Listeners will wait and respond when this method is invoked.
- Next, we create a class. I named it ProductNotificationHub
public class ProductNotificationHub : Hub<INotificationHub>
{
}
This class inherits from the strongly-typed hub Hub<T> in the SignalR library. This is better than the classic Hub class, which forces us to use the SendAsync method combined with a string to know which method to invoke which leaves a bigger room for error.
This class will be modified later to add a feature.
- We need to map incoming client requests to the proper Hub and give it a route . We do that by adding this line in the Program.cs file :
app.MapHub<ProductNotificationHub>("/Notify");
Our clients will use “/Notify” to connect to our server.
- We modify our repository so it calls our hub and invokes the SendMessage method whenever a product is updated:
We are using IHubContext<THub, T> to get an istance of our hub through dependency injection
and in line 49 we call our SendMessage method and pass a newly created notification.
Frontend Application
We create an Angular application in wich we install @microsoft/signalr
npm install @microsoft/signalr
- We create a Modules folder inside we add a Product Module in wich we add 3 folders : Components,Models and Services :
In the services folder we create a SingalrService
>ng g service signalr
Your service should look like :
We have a startConnection() method that will use our private hubConnection object to build on it a HubConnection through the HubConnectionBuilder and start it.
Then the addProductListener() will add a listener to the SendMessage method and if it’s invoked it will create a toast notification via the showNotification(notification: Notification) method.
Of course we already created our productService that will call our api to get list of products ,the product model and the notification model :
In our component :
constructor(public productService: ProductService,private singlarService:SingalrService) {
this.getProducts();
this.singlarService.startConnection();
this.singlarService.addProductListener();
}
Let’s see the magic happen !
Pretty cool right ? let’s add small feature : I want to get a notification only for a certain product. We do that by adding a method to our ProductNotificationHub that allows a client to subscribe to a certain product
public Task SuscribeToProduct(string productId)
{
return this.Groups.AddToGroupAsync(Context.ConnectionId, productId);
}
Update the InMemoryProductService by making it send the notification to only a certain group of users
await _productNotification.Clients.Group(product.ProductId).SendMessage(new Notification
{
ProductID = product.ProductId,
ProductName = product.ProductName,
Message = "Product Updated"
});
in the signalR service in the frontend application we add this method:
public subscribeToProduct(productId:string)
{
this.hubConnection.invoke("SuscribeToProduct",productId)
}
In the component :
subscribeToProduct(productId:string)
{
this.singlarService.subscribeToProduct(productId);
}
And an HTML button to call this method.
Watch the result
If you liked the tutorial don’t hesitate to buy me a coffe:
All the code can be found on my github :