Commit aeb6e2aa authored by Almouhannad's avatar Almouhannad

(B) Add SignalR, test using server time notifier

parent 33ad80b5
...@@ -3,6 +3,8 @@ using API.Options.JWT; ...@@ -3,6 +3,8 @@ using API.Options.JWT;
using API.SeedDatabaseHelper; using API.SeedDatabaseHelper;
using Application.Behaviors; using Application.Behaviors;
using FluentValidation; using FluentValidation;
using Infrastructure.BackgroundServices.Notifications;
using Infrastructure.NotificationsService;
using MediatR; using MediatR;
using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
...@@ -12,6 +14,10 @@ using Persistence.Context; ...@@ -12,6 +14,10 @@ using Persistence.Context;
var builder = WebApplication.CreateBuilder(args); var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
#region Add Database context #region Add Database context
// First, get database options // First, get database options
builder.Services.ConfigureOptions<DatabaseOptionsSetup>(); builder.Services.ConfigureOptions<DatabaseOptionsSetup>();
...@@ -35,7 +41,16 @@ builder.Services.AddDbContext<ClinicsDbContext>( ...@@ -35,7 +41,16 @@ builder.Services.AddDbContext<ClinicsDbContext>(
}); });
#endregion #endregion
// Add services to the container. #region Add SignalR
builder.Services.AddSignalR();
// Background services:
builder.Services.AddHostedService<ServerTimeNotifier>();
#endregion
#region Add CORS
#endregion
#region Link interfaces implemented in persistence #region Link interfaces implemented in persistence
// Using Scrutor library // Using Scrutor library
...@@ -126,6 +141,10 @@ if (app.Environment.IsDevelopment()) ...@@ -126,6 +141,10 @@ if (app.Environment.IsDevelopment())
app.UseHttpsRedirection(); app.UseHttpsRedirection();
#region Map notification HUB
app.MapHub<NotificationHub>("notifications");
#endregion
#region CORS #region CORS
// TODO: Configure allows // TODO: Configure allows
app.UseCors(policy => policy.AllowAnyHeader().AllowAnyMethod().AllowAnyHeader().AllowAnyOrigin()); app.UseCors(policy => policy.AllowAnyHeader().AllowAnyMethod().AllowAnyHeader().AllowAnyOrigin());
......
using Infrastructure.NotificationsService;
using Microsoft.AspNetCore.SignalR;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
namespace Infrastructure.BackgroundServices.Notifications;
public class ServerTimeNotifier : BackgroundService
{
private static readonly TimeSpan Period = TimeSpan.FromSeconds(3);
#region CTOR DI
private readonly ILogger<ServerTimeNotifier> _logger;
private readonly IHubContext<NotificationHub, INotificationClient> _context;
public ServerTimeNotifier(ILogger<ServerTimeNotifier> logger, IHubContext<NotificationHub, INotificationClient> context)
{
_logger = logger;
_context = context;
}
#endregion
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
using var timer = new PeriodicTimer(Period);
while (!stoppingToken.IsCancellationRequested &&
await timer.WaitForNextTickAsync(stoppingToken))
{
var dateTime = DateTime.Now;
_logger.LogInformation("Executing {Service} {Time}", nameof(ServerTimeNotifier), dateTime);
await _context.Clients.All.ReceiveNotification($"Server time = {dateTime}");
}
}
}
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="FluentValidation.DependencyInjectionExtensions" Version="11.9.2" />
<PackageReference Include="MediatR" Version="12.4.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.8" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.8">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.8" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.8">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Scrutor" Version="4.2.2" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.7.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Application\Application.csproj" />
<ProjectReference Include="..\Domain\Domain.csproj" />
</ItemGroup>
<ItemGroup>
<Folder Include="BackgroundServices\" />
</ItemGroup>
</Project>
using Microsoft.AspNetCore.SignalR;
namespace Infrastructure.NotificationsService;
public class NotificationHub : Hub<INotificationClient>
{
public override async Task OnConnectedAsync()
{
await Clients.Client(Context.ConnectionId).ReceiveNotification(
$"Connected successfully { Context.User?.Identity?.Name}");
await base.OnConnectedAsync();
}
}
public interface INotificationClient
{
Task ReceiveNotification(string message);
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment