https://github.com/fkucukkara/server-sent-events
This project demonstrates how to implement Server-Sent Events (SSE) using the new features introduced in .NET 10.
https://github.com/fkucukkara/server-sent-events
csharp net10 netcore-webapi server-sent-events sse
Last synced: 17 days ago
JSON representation
This project demonstrates how to implement Server-Sent Events (SSE) using the new features introduced in .NET 10.
- Host: GitHub
- URL: https://github.com/fkucukkara/server-sent-events
- Owner: fkucukkara
- License: mit
- Created: 2025-10-04T10:09:27.000Z (10 months ago)
- Default Branch: main
- Last Pushed: 2026-05-17T15:01:52.000Z (2 months ago)
- Last Synced: 2026-05-17T17:29:11.165Z (2 months ago)
- Topics: csharp, net10, netcore-webapi, server-sent-events, sse
- Language: C#
- Homepage:
- Size: 29.3 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Server-Sent Events (SSE) with .NET 10
This project demonstrates how to implement **Server-Sent Events (SSE)** using the new features introduced in **.NET 10**. It's a simple educational proof-of-concept that shows real-time heart rate monitoring using minimal APIs.
## ๐ฏ What is Server-Sent Events (SSE)?
Server-Sent Events is a web standard that allows a server to push data to a web page in real-time. Unlike WebSockets, SSE is unidirectional (server-to-client only) and simpler to implement for scenarios where you only need to send data from server to client.
> **Note:** This project uses "server-sent-events" (with hyphens) as the standard naming convention for SSE, which is the correct terminology according to the W3C specification.
## ๐ What's New in .NET 10
.NET 10 introduces native support for Server-Sent Events with:
- **`SseItem`** - Strongly-typed SSE item representation
- **`TypedResults.ServerSentEvents()`** - Built-in minimal API support
- **`System.Net.ServerSentEvents`** namespace - Complete SSE framework
## ๐ Project Structure
```
server-sent-events/
โโโ API/
โ โโโ API.csproj # .NET 10 project file
โ โโโ Program.cs # Main application with SSE endpoint
โ โโโ API.http # HTTP test requests
โ โโโ Properties/
โ โโโ launchSettings.json # Development settings
โโโ global.json # .NET SDK version pinning
โโโ server-sent-events.sln # Solution file
โโโ README.md # This file
```
## ๐ Features
- โ
**Pure API** - No UI, just the SSE endpoint
- โ
Real-time heart rate simulation (60-100 BPM)
- โ
Native .NET 10 SSE implementation
- โ
Minimal API with OpenAPI documentation
- โ
Proper cancellation token handling
- โ
Automatic reconnection support
- โ
Type-safe event streaming
- โ
Ready for integration with any frontend
## ๐ Prerequisites
- **.NET 10 SDK** - [Download here](https://dotnet.microsoft.com/download/dotnet/10.0)
- **Visual Studio 2026** or **VS Code** (optional)
## ๐ ๏ธ Getting Started
### 1. Clone the Repository
```bash
git clone https://github.com/fkucukkara/server-sent-events.git
cd server-sent-events
```
### 2. Verify .NET 10 Installation
```bash
dotnet --version
# Should show: 10.0.100 or later
```
### 3. Restore Dependencies
```bash
dotnet restore
```
### 4. Build the Project
```bash
dotnet build
```
### 5. Run the Application
```bash
cd API
dotnet run
```
The application will start at `https://localhost:7144`
## ๐ API Endpoints
| Endpoint | Method | Description | Response Type |
|----------|--------|-------------|---------------|
| `/string-item` | GET | SSE stream of heart rate data as plain strings | `text/event-stream` |
| `/json-item` | GET | SSE stream of heart rate data as JSON objects | `text/event-stream` |
| `/sse-item` | GET | SSE stream using strongly-typed `SseItem` with reconnection metadata | `text/event-stream` |
| `/openapi/v1.json` | GET | OpenAPI specification | `application/json` |
## ๐งช Testing the SSE Endpoint
### Option 1: Using VS Code REST Client
Open `API/API.http` and click "Send Request" on the SSE endpoint:
```http
GET https://localhost:7144/sse-item
Accept: text/event-stream
Cache-Control: no-cache
```
### Option 2: Using Browser
Navigate to: `https://localhost:7144/sse-item`
You'll see a continuous stream of heart rate data:
```
event: heartRate
data: 75
event: heartRate
data: 82
event: heartRate
data: 68
```
### Option 3: Using curl
```bash
curl -N -H "Accept: text/event-stream" https://localhost:7144/sse-item
```
### Option 4: Using JavaScript Client
Create your own HTML file to test the SSE endpoint:
```html
Heart Rate Monitor
Real-time Heart Rate
Connecting...
const eventSource = new EventSource('https://localhost:7144/sse-item');
eventSource.addEventListener('heartRate', function(event) {
document.getElementById('heartRate').innerHTML =
`โค๏ธ Heart Rate: ${event.data} BPM`;
});
eventSource.onerror = function(event) {
console.error('SSE error:', event);
};
```
## ๐ Code Explanation
### Pattern 1 โ Plain String Events
```csharp
app.MapGet("/string-item", (CancellationToken cancellationToken) =>
{
async IAsyncEnumerable GetHeartRate(
[EnumeratorCancellation] CancellationToken cancellationToken)
{
while (!cancellationToken.IsCancellationRequested)
{
var heartRate = Random.Shared.Next(60, 100);
yield return $"Heart Rate: {heartRate} bpm";
await Task.Delay(2000, cancellationToken);
}
}
return TypedResults.ServerSentEvents(GetHeartRate(cancellationToken), eventType: "heartRate");
});
```
### Pattern 2 โ JSON Object Events
```csharp
app.MapGet("/json-item", (CancellationToken cancellationToken) =>
{
async IAsyncEnumerable GetHeartRate(
[EnumeratorCancellation] CancellationToken cancellationToken)
{
while (!cancellationToken.IsCancellationRequested)
{
var heartRate = Random.Shared.Next(60, 100);
yield return HeartRateRecord.Create(heartRate);
await Task.Delay(2000, cancellationToken);
}
}
return TypedResults.ServerSentEvents(GetHeartRate(cancellationToken), eventType: "heartRate");
});
record HeartRateRecord(int HeartRate, DateTime Timestamp)
{
public static HeartRateRecord Create(int heartRate) => new(heartRate, DateTime.UtcNow);
}
```
### Pattern 3 โ Strongly-Typed `SseItem` with Metadata
```csharp
app.MapGet("/sse-item", (CancellationToken cancellationToken) =>
{
async IAsyncEnumerable> GetHeartRate(
[EnumeratorCancellation] CancellationToken cancellationToken)
{
while (!cancellationToken.IsCancellationRequested)
{
var heartRate = Random.Shared.Next(60, 100);
yield return new SseItem(heartRate, eventType: "heartRate")
{
ReconnectionInterval = TimeSpan.FromMinutes(1)
};
await Task.Delay(2000, cancellationToken);
}
}
return TypedResults.ServerSentEvents(GetHeartRate(cancellationToken));
});
```
### Key Components
1. **`IAsyncEnumerable`** - Async stream of events; `T` can be `string`, a record, or `SseItem`
2. **`TypedResults.ServerSentEvents()`** - Converts the stream to an SSE (`text/event-stream`) response
3. **`[EnumeratorCancellation]`** - Proper cancellation token propagation through async enumerables
4. **`eventType`** - Custom event type for client-side filtering via `addEventListener('heartRate', handler)`
5. **`ReconnectionInterval`** - Instructs the client how long to wait before reconnecting (only on `SseItem`)
## โ๏ธ Configuration
### global.json
Ensures the project uses .NET 10 SDK:
```json
{
"sdk": {
"version": "10.0.300",
"rollForward": "latestPatch"
}
}
```
### Project File (API.csproj)
```xml
net10.0
enable
enable
```
## ๐ SSE vs WebSockets
| Feature | Server-Sent Events | WebSockets |
|---------|-------------------|------------|
| **Direction** | Server โ Client only | Bidirectional |
| **Protocol** | HTTP | WebSocket Protocol |
| **Complexity** | Simple | More complex |
| **Auto-reconnect** | Built-in | Manual implementation |
| **Firewall-friendly** | Yes (HTTP) | Sometimes blocked |
| **Use cases** | Live feeds, notifications | Chat, gaming, collaboration |
## ๐ Educational Objectives
This POC demonstrates:
1. **Modern .NET 10 SSE APIs** - Latest framework features
2. **Minimal APIs** - Simplified web API development
3. **Async Streaming** - `IAsyncEnumerable` patterns
4. **Real-time Communication** - Server-to-client data push
5. **Cancellation Patterns** - Proper resource cleanup
6. **Type Safety** - Strongly-typed event streaming
## ๐ Next Steps & Extensions
### Beginner Extensions
- Add different event types (temperature, pressure, etc.)
- Implement event filtering on the client side
- Add basic error handling and retry logic
### Intermediate Extensions
- Add authentication and authorization
- Implement multiple SSE endpoints
- Add persistent data storage (Entity Framework)
- Create a web dashboard with charts
### Advanced Extensions
- Add horizontal scaling with Redis
- Implement SSE with SignalR fallback
- Add monitoring and logging
- Performance testing and optimization
## ๐ Additional Resources
- [Microsoft Docs - SSE in Minimal APIs](https://learn.microsoft.com/en-us/aspnet/core/fundamentals/minimal-apis/responses?view=aspnetcore-10.0#server-sent-events-sse)
- [MDN - Server-Sent Events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events)
- [.NET 10 Preview Features](https://devblogs.microsoft.com/dotnet/)
- [Minimal APIs Documentation](https://learn.microsoft.com/en-us/aspnet/core/fundamentals/minimal-apis)
## License
[](LICENSE)
This project is licensed under the MIT License, which allows you to freely use, modify, and distribute the code. See the [`LICENSE`](LICENSE) file for full details.