SSE

Introduction

Server-Sent Events (SSE) is a server push technology enabling a server to push real-time updates to the browser over a single HTTP connection. This article demonstrates how to implement SSE in a .NET Core API to push updates to an Angular UI in real-time.

Prerequisites

Step 1. Setting Up the .NET Core Web API.

Create a New .NET Core Web API Project

 dotnet new webapi -n QuickNotifyAPI
cd QuickNotifyAPI

Implement SSE in the Controller

Create a NotificationController to handle SSE connections and push updates to the client.

using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using System.Collections.Concurrent;
using System.Text;

namespace QuickNotifyAPI.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class NotificationController : ControllerBase
    {
        private static readonly ConcurrentDictionary<string, StreamWriter> _clients = new ConcurrentDictionary<string, StreamWriter>();

        [HttpGet("subscribe")]
        public async Task Subscribe(CancellationToken cancellationToken)
        {
            Response.Headers.Add("Content-Type", "text/event-stream");
            var clientId = Guid.NewGuid().ToString();
            var clientStream = new StreamWriter(Response.Body, Encoding.UTF8);
            _clients.TryAdd(clientId, clientStream);

            try
            {
                while (!cancellationToken.IsCancellationRequested)
                {
                    await Task.Delay(1000, cancellationToken);
                }
            }
            catch (TaskCanceledException) { }
            finally
            {
                _clients.TryRemove(clientId, out _);
            }
        }

        public static async Task SendNotificationAsync(string message)
        {
            foreach (var client in _clients.Values)
            {
                try
                {
                    await client.WriteLineAsync($"data: {message}\n");
                    await client.FlushAsync();
                }
                catch (Exception) { }
            }
        }
    }
}

Create an Endpoint to Add Entries and Trigger Notifications

using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;

namespace QuickNotifyAPI.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class EntryController : ControllerBase
    {
        [HttpPost]
        public async Task<IActionResult> CreateEntry([FromBody] string entry)
        {
            try
            {
                await NotificationController.SendNotificationAsync($"New entry created: {entry}");
                return Ok(new { StatusCode = 200, message = "Entry created", entry });
            }
            catch (Exception ex)
            {
                return Ok(new { StatusCode = 400, message = "Something went wrong", entry });
            }
        }
    }
}

API

Step 2. Setting Up the Angular Frontend.

Create a New Angular Project

​​​​​​​  ng new QuickNotifyUI

 Angular Frontend

Angular Project

Angular

Create a Service to Handle SSE

Using the Service in a Component

Now, you can use this service in your component by calling getNotify().

import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class PushNotifyService {
  eventSource!: EventSource;
  url = 'https://localhost:7165/api/Notification/subscribe';

  constructor() { }

  getNotify() {
    return new Observable(obs => {
      this.eventSource = new EventSource(this.url);

      this.eventSource.onerror = (error) => {
        console.log(error);
      }

      this.eventSource.onmessage = (message) => {
        obs.next(message.data);
      }
    });
  }
}

Component to Display Live Notifications

import { ChangeDetectorRef, Component, OnInit } from '@angular/core';
import { RouterOutlet } from '@angular/router';
import { PushNotifyService } from './push-notify.service';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
  title = "QuickNotify";

  constructor(private notify: PushNotifyService, private cdf: ChangeDetectorRef) { }

  ngOnInit(): void {
    this.notify.getNotify().subscribe({
      next: (data: any) => {
        this.title = data;
        console.log(typeof (data));
        this.cdf.detectChanges();
      }
    });
  }
}

Update Component Template

<h1>Hello, {{ title }}</h1>

Running the Applications

Both Applications run CLI here.

Run the .NET Core Web API

dotnet run

Run the Angular Application

ng serve

Open Your Browser

Here both Applications run snaps.

 Applications run

Test Creating an Entry

Use tools like Postman or create a simple Angular form to send a POST request to the EntryController to create a new entry. For example, using Postman, send a POST request to https://localhost:7165/api/Entry with a JSON body like: "Welcome to Angular Community".

 JSON body

Conclusion

This guide demonstrated how to implement Server-Sent Events (SSE) in a .NET Core Web API to push real-time updates to an Angular frontend. SSE is an efficient way to achieve real-time communication from server to client, suitable for applications requiring live updates such as notifications, live scores, or monitoring dashboards.