Friday, June 26, 2020

SignalR and Angular


Currently, we want to keep our dashboard data updated through push notification instead of polling.
This note is written for how to implement it.
We will divide this note into two parts: One is for back-end service, and another one is for front-end app.

Back-end: SignalR Hub

1. First, we need to use Visual Studio to create a .Net Core 3.1 Web API project.

2. Then we need to install ‘SignalR’ via NgGet.


3. Now, we are able to create our hub class.

In this experiment, I created a class called ‘NotifyHub’ and inherit from 'Hub', and keep it empty.

    public class NotifyHub:Hub
    {
    
    }


4. Then I created a Controller to support Post Action for demo purpose instead of writing some code with timer to raise an event.

    [Route("api/[controller]")]
    [ApiController]
    public class NotificationController : ControllerBase
    {
        private IHubContext<NotifyHub> notifyHubContext;

        public NotificationController(IHubContext<NotifyHub> notifyHubContext)
        {
            this.notifyHubContext = notifyHubContext;
        }

        public IActionResult Post()
        {
            //Broadcast message to client  
            notifyHubContext.Clients.All.SendAsync("BroadcastMessage", "Hello World");

            return Ok();
        }
    }


5. In the end, we need to change the Startup.cs file for configuration.

Since our signalR hub project will have different origin comparing with angular client app, we need to config CORS. Below "htttp://localhost:4200" is for angular client.

    public void ConfigureServices(IServiceCollection services)
    { 
        services.AddCors(options =>
        {
            options.AddPolicy("CorsPolicy", builder => builder
                .WithOrigins("http://localhost:4200")
                .AllowAnyMethod()
                .AllowAnyHeader()
                .AllowCredentials());
        });

        services.AddSignalR();

        services.AddControllers();
    }

Also, under ‘Configure’ function, add below code to apply CORS and hub.

    papp.UseCors("CorsPolicy");

    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllers();
        endpoints.MapHub<NotifyHub>("/notification");
    });

Finally, our SignalR back-end is ready.

Front-end: Angular Client App

1. First, we need to use Angular CLI to create a brand new project.

    ng new angular-client

2. Then, install signalr to this project

    npm install @aspnet/signalr --save

After that, you will see some changes in package.json file.

"@aspnet/signalr""^1.1.4",

3. Now, we are ready to use this library. In order to make it simple, we will not organize code structure. We put everything in app.component.ts for demo purpose.

    import { Component, OnInit } from '@angular/core';
    import * as signalR from "@aspnet/signalr";

    @Component({
        selector: 'app-root',
        templateUrl: './app.component.html',
        styleUrls: ['./app.component.css']
    })
    export class AppComponent implements OnInit {
        // Variables
        private hubConnection: signalR.HubConnection

        ngOnInit(): void {
            // Binding
            this.hubConnection = new signalR.HubConnectionBuilder()
                .withUrl('https://localhost:5001/notification')
                .build();

            // Connect
            this.hubConnection
                .start()
                .then(
                    () => { } // Success
                )
                .catch(
                    err => { } // Failed
                )

            // Listening
            this.hubConnection.on('BroadcastMessage', (data) => {
                console.log(data);
            });
        }
    }


4. Once we send data through postman to our back-end Web API (https://localhost:5001/api/notification) , signalR hub server will push "Hello World' message to all its connected angular app.



 



And that is it.