I have set up a ASP.NET Server on localhost
.
When I try to fetch data from my WPF Application, it is recieved. But when I also want to fetch the data from my browser, the datastream from the WPF App is interrupted. When I restart the WPF App, the browsers connection is interrupted or the browser is not loading data anymore.
Can you tell me what is wrong?
I did not found any good example of how to set up SSE Connection with WPF.
Please check this video (Left: VS Console, right: Browser)
This is my code of ASP.NET Server:
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.Identity.Web;
using System.Text.Json;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApi(builder.Configuration.GetSection("AzureAd"));
builder.Services.AddControllers();
builder.Services.AddSingleton<ItemService>();
builder.Services.AddCors(options =>
{
options.AddPolicy("AllowAnyOrigin", p => p
.AllowAnyOrigin()
.AllowAnyHeader()
.AllowAnyMethod());
});
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.UseCors("AllowAnyOrigin");
app.MapGet("/sse_appsched", async (HttpContext ctx, ItemService service, CancellationToken ct) =>
{
ctx.Response.Headers.Add("Content-Type", "text/event-stream");
while (!ct.IsCancellationRequested)
{
var item = await service.WaitForNewItem();
await ctx.Response.WriteAsync($"data: ");
await JsonSerializer.SerializeAsync(ctx.Response.Body, item);
await ctx.Response.WriteAsync($"nn");
await ctx.Response.Body.FlushAsync();
service.Reset();
}
});
app.Run();
This is code of item service:
public record Item(string Name, double Price);
public class ItemService
{
private TaskCompletionSource<Item?> _tcs = new();
private long _id = 0;
public void Reset()
{
_tcs = new TaskCompletionSource<Item?>();
}
public void NotifyNewItemAvailable()
{
_tcs.TrySetResult(new Item($"New Item {_id++}", Random.Shared.Next(0, 500)));
}
public Task<Item?> WaitForNewItem()
{
// Simulate some delay in Item arrival
Task.Run(async () =>
{
await Task.Delay(TimeSpan.FromSeconds(Random.Shared.Next(0, 29)));
NotifyNewItemAvailable();
});
return _tcs.Task;
}
}
And this is code in WPF App:
public partial class OJISSE
{
String UriOfEvent = "https://localhost:44329/sse_appsched";
public async Task ServiceWrapperAsync()
{
using (var client = new HttpClient())
{
using (var stream = await client.GetStreamAsync(UriOfEvent))
{
using (var reader = new StreamReader(stream))
{
while (true)
{
var data = reader.ReadLine();
Trace.WriteLine(data);
}
}
}
}
}
}
OJISSE OJI_SSE_INST = new OJISSE();
Task OJI_SSE_TASK = Task.Run(OJI_SSE_INST.ServiceWrapperAsync);