mirror of
https://github.com/alex289/CleanArchitecture.git
synced 2025-06-29 18:21:08 +00:00
feat: dotnet 9
This commit is contained in:
parent
18f458332f
commit
804679d676
2
.github/workflows/codeql.yml
vendored
2
.github/workflows/codeql.yml
vendored
@ -30,7 +30,7 @@ jobs:
|
|||||||
- name: Install .NET Core
|
- name: Install .NET Core
|
||||||
uses: actions/setup-dotnet@v4
|
uses: actions/setup-dotnet@v4
|
||||||
with:
|
with:
|
||||||
dotnet-version: '8.x.x'
|
dotnet-version: '9.x.x'
|
||||||
|
|
||||||
- name: Initialize CodeQL
|
- name: Initialize CodeQL
|
||||||
uses: github/codeql-action/init@v3
|
uses: github/codeql-action/init@v3
|
||||||
|
2
.github/workflows/dependency-check.yml
vendored
2
.github/workflows/dependency-check.yml
vendored
@ -20,7 +20,7 @@ jobs:
|
|||||||
uses: actions/setup-dotnet@v4
|
uses: actions/setup-dotnet@v4
|
||||||
with:
|
with:
|
||||||
dotnet-version: |
|
dotnet-version: |
|
||||||
8.x.x
|
9.x.x
|
||||||
|
|
||||||
- name: Restore dependencies
|
- name: Restore dependencies
|
||||||
run: dotnet restore
|
run: dotnet restore
|
||||||
|
2
.github/workflows/dotnet.yml
vendored
2
.github/workflows/dotnet.yml
vendored
@ -27,7 +27,7 @@ jobs:
|
|||||||
uses: actions/setup-dotnet@v4
|
uses: actions/setup-dotnet@v4
|
||||||
with:
|
with:
|
||||||
dotnet-version: |
|
dotnet-version: |
|
||||||
8.x.x
|
9.x.x
|
||||||
|
|
||||||
- name: Restore dependencies
|
- name: Restore dependencies
|
||||||
run: dotnet restore
|
run: dotnet restore
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net8.0</TargetFramework>
|
<TargetFramework>net9.0</TargetFramework>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<UserSecretsId>64377c40-44d6-4989-9662-5d778f8b3b92</UserSecretsId>
|
<UserSecretsId>64377c40-44d6-4989-9662-5d778f8b3b92</UserSecretsId>
|
||||||
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
|
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
|
||||||
@ -14,17 +14,17 @@
|
|||||||
<PackageReference Include="AspNetCore.HealthChecks.SqlServer" Version="8.0.2" />
|
<PackageReference Include="AspNetCore.HealthChecks.SqlServer" Version="8.0.2" />
|
||||||
<PackageReference Include="AspNetCore.HealthChecks.UI.Client" Version="8.0.1" />
|
<PackageReference Include="AspNetCore.HealthChecks.UI.Client" Version="8.0.1" />
|
||||||
<PackageReference Include="Grpc.AspNetCore.Server.Reflection" Version="2.66.0" />
|
<PackageReference Include="Grpc.AspNetCore.Server.Reflection" Version="2.66.0" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.10" />
|
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="9.0.0" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="8.0.10" />
|
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="9.0.0" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.10">
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="9.0.0">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Proxies" Version="8.0.10" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Proxies" Version="9.0.0" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Caching.StackExchangeRedis" Version="8.0.10" />
|
<PackageReference Include="Microsoft.Extensions.Caching.StackExchangeRedis" Version="9.0.0" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore" Version="8.0.10" />
|
<PackageReference Include="Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore" Version="9.0.0" />
|
||||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.9.0" />
|
<PackageReference Include="Swashbuckle.AspNetCore" Version="7.0.0" />
|
||||||
<PackageReference Include="Swashbuckle.AspNetCore.Annotations" Version="6.9.0" />
|
<PackageReference Include="Swashbuckle.AspNetCore.Annotations" Version="7.0.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net8.0</TargetFramework>
|
<TargetFramework>net9.0</TargetFramework>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
|
|
||||||
<IsPackable>false</IsPackable>
|
<IsPackable>false</IsPackable>
|
||||||
@ -9,7 +9,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="FluentAssertions" Version="6.12.1" />
|
<PackageReference Include="FluentAssertions" Version="6.12.2" />
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.11.1" />
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.11.1" />
|
||||||
<PackageReference Include="MockQueryable.NSubstitute" Version="7.0.3" />
|
<PackageReference Include="MockQueryable.NSubstitute" Version="7.0.3" />
|
||||||
<PackageReference Include="NSubstitute" Version="5.3.0" />
|
<PackageReference Include="NSubstitute" Version="5.3.0" />
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net8.0</TargetFramework>
|
<TargetFramework>net9.0</TargetFramework>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.10" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net8.0</TargetFramework>
|
<TargetFramework>net9.0</TargetFramework>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
|
|
||||||
<IsPackable>false</IsPackable>
|
<IsPackable>false</IsPackable>
|
||||||
@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="BCrypt.Net-Next" Version="4.0.3" />
|
<PackageReference Include="BCrypt.Net-Next" Version="4.0.3" />
|
||||||
<PackageReference Include="FluentAssertions" Version="6.12.1" />
|
<PackageReference Include="FluentAssertions" Version="6.12.2" />
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.11.1" />
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.11.1" />
|
||||||
<PackageReference Include="NSubstitute" Version="5.3.0" />
|
<PackageReference Include="NSubstitute" Version="5.3.0" />
|
||||||
<PackageReference Include="xunit" Version="2.9.2" />
|
<PackageReference Include="xunit" Version="2.9.2" />
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net8.0</TargetFramework>
|
<TargetFramework>net9.0</TargetFramework>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
@ -9,10 +9,10 @@
|
|||||||
<PackageReference Include="BCrypt.Net-Next" Version="4.0.3" />
|
<PackageReference Include="BCrypt.Net-Next" Version="4.0.3" />
|
||||||
<PackageReference Include="FluentValidation" Version="11.10.0" />
|
<PackageReference Include="FluentValidation" Version="11.10.0" />
|
||||||
<PackageReference Include="MediatR" Version="12.4.1" />
|
<PackageReference Include="MediatR" Version="12.4.1" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Options" Version="8.0.2" />
|
<PackageReference Include="Microsoft.Extensions.Options" Version="9.0.0" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||||
<PackageReference Include="RabbitMQ.Client" Version="6.8.1" />
|
<PackageReference Include="RabbitMQ.Client" Version="7.0.0" />
|
||||||
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="8.1.2" />
|
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="8.2.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -14,7 +14,7 @@ public static partial class CustomValidator
|
|||||||
private static bool IsBase64String(string base64)
|
private static bool IsBase64String(string base64)
|
||||||
{
|
{
|
||||||
base64 = base64.Trim();
|
base64 = base64.Trim();
|
||||||
return base64.Length % 4 == 0 && Base64Regex().IsMatch(base64);
|
return base64.Length % 4 == 0 && new Regex("^[a-zA-Z0-9\\+/]*={0,3}$").IsMatch(base64);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IRuleBuilder<T, string> Password<T>(
|
public static IRuleBuilder<T, string> Password<T>(
|
||||||
@ -32,7 +32,4 @@ public static partial class CustomValidator
|
|||||||
.Matches("[^a-zA-Z0-9]").WithErrorCode(DomainErrorCodes.User.SpecialCharPassword);
|
.Matches("[^a-zA-Z0-9]").WithErrorCode(DomainErrorCodes.User.SpecialCharPassword);
|
||||||
return options;
|
return options;
|
||||||
}
|
}
|
||||||
|
|
||||||
[GeneratedRegex("^[a-zA-Z0-9\\+/]*={0,3}$", RegexOptions.None)]
|
|
||||||
private static partial Regex Base64Regex();
|
|
||||||
}
|
}
|
@ -1,3 +1,4 @@
|
|||||||
|
using System.Threading.Tasks;
|
||||||
using RabbitMQ.Client;
|
using RabbitMQ.Client;
|
||||||
|
|
||||||
namespace CleanArchitecture.Domain.Rabbitmq.Actions;
|
namespace CleanArchitecture.Domain.Rabbitmq.Actions;
|
||||||
@ -15,8 +16,8 @@ public sealed class BindQueueToExchange : IRabbitMqAction
|
|||||||
_queueName = queueName;
|
_queueName = queueName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Perform(IModel channel)
|
public async Task Perform(IChannel channel)
|
||||||
{
|
{
|
||||||
channel.QueueBind(_queueName, _exchangeName, _routingKey);
|
await channel.QueueBindAsync(_queueName, _exchangeName, _routingKey);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,3 +1,4 @@
|
|||||||
|
using System.Threading.Tasks;
|
||||||
using RabbitMQ.Client;
|
using RabbitMQ.Client;
|
||||||
|
|
||||||
namespace CleanArchitecture.Domain.Rabbitmq.Actions;
|
namespace CleanArchitecture.Domain.Rabbitmq.Actions;
|
||||||
@ -13,8 +14,8 @@ public sealed class CreateExchange : IRabbitMqAction
|
|||||||
_type = type;
|
_type = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Perform(IModel channel)
|
public async Task Perform(IChannel channel)
|
||||||
{
|
{
|
||||||
channel.ExchangeDeclare(_name, _type);
|
await channel.ExchangeDeclareAsync(_name, _type);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,3 +1,4 @@
|
|||||||
|
using System.Threading.Tasks;
|
||||||
using RabbitMQ.Client;
|
using RabbitMQ.Client;
|
||||||
|
|
||||||
namespace CleanArchitecture.Domain.Rabbitmq.Actions;
|
namespace CleanArchitecture.Domain.Rabbitmq.Actions;
|
||||||
@ -11,9 +12,9 @@ public sealed class CreateQueue : IRabbitMqAction
|
|||||||
QueueName = queueName;
|
QueueName = queueName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Perform(IModel channel)
|
public async Task Perform(IChannel channel)
|
||||||
{
|
{
|
||||||
channel.QueueDeclare(
|
await channel.QueueDeclareAsync(
|
||||||
QueueName,
|
QueueName,
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
|
using System.Threading.Tasks;
|
||||||
using RabbitMQ.Client;
|
using RabbitMQ.Client;
|
||||||
|
|
||||||
namespace CleanArchitecture.Domain.Rabbitmq.Actions;
|
namespace CleanArchitecture.Domain.Rabbitmq.Actions;
|
||||||
|
|
||||||
public interface IRabbitMqAction
|
public interface IRabbitMqAction
|
||||||
{
|
{
|
||||||
void Perform(IModel channel);
|
Task Perform(IChannel channel);
|
||||||
}
|
}
|
@ -1,11 +1,12 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using RabbitMQ.Client;
|
using RabbitMQ.Client;
|
||||||
|
|
||||||
namespace CleanArchitecture.Domain.Rabbitmq.Actions;
|
namespace CleanArchitecture.Domain.Rabbitmq.Actions;
|
||||||
|
|
||||||
public sealed class RegisterConsumer : IRabbitMqAction
|
public sealed class RegisterConsumer : IRabbitMqAction
|
||||||
{
|
{
|
||||||
private readonly Action<string, string, string, ConsumeEventHandler> _addConsumer;
|
private readonly Func<string, string, string, ConsumeEventHandler, Task> _addConsumer;
|
||||||
private readonly ConsumeEventHandler _consumer;
|
private readonly ConsumeEventHandler _consumer;
|
||||||
private readonly string _exchange;
|
private readonly string _exchange;
|
||||||
private readonly string _queue;
|
private readonly string _queue;
|
||||||
@ -16,7 +17,7 @@ public sealed class RegisterConsumer : IRabbitMqAction
|
|||||||
string queue,
|
string queue,
|
||||||
string routingKey,
|
string routingKey,
|
||||||
ConsumeEventHandler consumer,
|
ConsumeEventHandler consumer,
|
||||||
Action<string, string, string, ConsumeEventHandler> addConsumer)
|
Func<string, string, string, ConsumeEventHandler, Task> addConsumer)
|
||||||
{
|
{
|
||||||
_exchange = exchange;
|
_exchange = exchange;
|
||||||
_queue = queue;
|
_queue = queue;
|
||||||
@ -25,8 +26,8 @@ public sealed class RegisterConsumer : IRabbitMqAction
|
|||||||
_addConsumer = addConsumer;
|
_addConsumer = addConsumer;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Perform(IModel channel)
|
public async Task Perform(IChannel channel)
|
||||||
{
|
{
|
||||||
_addConsumer(_exchange, _queue, _routingKey, _consumer);
|
await _addConsumer(_exchange, _queue, _routingKey, _consumer);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,3 +1,4 @@
|
|||||||
|
using System.Threading.Tasks;
|
||||||
using RabbitMQ.Client;
|
using RabbitMQ.Client;
|
||||||
|
|
||||||
namespace CleanArchitecture.Domain.Rabbitmq.Actions;
|
namespace CleanArchitecture.Domain.Rabbitmq.Actions;
|
||||||
@ -11,8 +12,8 @@ public sealed class SendAcknowledgement : IRabbitMqAction
|
|||||||
DeliveryTag = deliveryTag;
|
DeliveryTag = deliveryTag;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Perform(IModel channel)
|
public async Task Perform(IChannel channel)
|
||||||
{
|
{
|
||||||
channel.BasicAck(DeliveryTag, false);
|
await channel.BasicAckAsync(DeliveryTag, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,4 +1,5 @@
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using RabbitMQ.Client;
|
using RabbitMQ.Client;
|
||||||
|
|
||||||
@ -23,16 +24,15 @@ public sealed class SendMessage : IRabbitMqAction
|
|||||||
_message = message;
|
_message = message;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Perform(IModel channel)
|
public async Task Perform(IChannel channel)
|
||||||
{
|
{
|
||||||
var json = JsonConvert.SerializeObject(_message, s_serializerSettings);
|
var json = JsonConvert.SerializeObject(_message, s_serializerSettings);
|
||||||
|
|
||||||
var content = Encoding.UTF8.GetBytes(json);
|
var content = Encoding.UTF8.GetBytes(json);
|
||||||
|
|
||||||
channel.BasicPublish(
|
await channel.BasicPublishAsync(
|
||||||
_exchange,
|
_exchange,
|
||||||
_routingKey,
|
_routingKey,
|
||||||
null,
|
|
||||||
content);
|
content);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -13,7 +13,7 @@ namespace CleanArchitecture.Domain.Rabbitmq;
|
|||||||
|
|
||||||
public sealed class RabbitMqHandler : BackgroundService
|
public sealed class RabbitMqHandler : BackgroundService
|
||||||
{
|
{
|
||||||
private readonly IModel? _channel;
|
private IChannel? _channel;
|
||||||
private readonly RabbitMqConfiguration _configuration;
|
private readonly RabbitMqConfiguration _configuration;
|
||||||
|
|
||||||
private readonly ConcurrentDictionary<string, List<ConsumeEventHandler>> _consumers = new();
|
private readonly ConcurrentDictionary<string, List<ConsumeEventHandler>> _consumers = new();
|
||||||
@ -28,27 +28,30 @@ public sealed class RabbitMqHandler : BackgroundService
|
|||||||
{
|
{
|
||||||
_configuration = configuration;
|
_configuration = configuration;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
if (!configuration.Enabled)
|
public override async Task StartAsync(CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
if (!_configuration.Enabled)
|
||||||
{
|
{
|
||||||
logger.LogInformation("RabbitMQ is disabled. Connection will not be established");
|
_logger.LogInformation("RabbitMQ is disabled. Connection will not be established");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var factory = new ConnectionFactory
|
var factory = new ConnectionFactory
|
||||||
{
|
{
|
||||||
AutomaticRecoveryEnabled = true,
|
AutomaticRecoveryEnabled = true,
|
||||||
HostName = configuration.Host,
|
HostName = _configuration.Host,
|
||||||
Port = configuration.Port,
|
Port = _configuration.Port,
|
||||||
UserName = configuration.Username,
|
UserName = _configuration.Username,
|
||||||
Password = configuration.Password,
|
Password = _configuration.Password,
|
||||||
DispatchConsumersAsync = true
|
|
||||||
};
|
};
|
||||||
|
|
||||||
var connection = factory.CreateConnection();
|
var connection = await factory.CreateConnectionAsync(cancellationToken);
|
||||||
_channel = connection.CreateModel();
|
_channel = await connection.CreateChannelAsync(null, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void InitializeExchange(string exchangeName, string type = ExchangeType.Fanout)
|
public void InitializeExchange(string exchangeName, string type = ExchangeType.Fanout)
|
||||||
{
|
{
|
||||||
if (!_configuration.Enabled)
|
if (!_configuration.Enabled)
|
||||||
@ -126,8 +129,14 @@ public sealed class RabbitMqHandler : BackgroundService
|
|||||||
AddExchangeConsumer(exchange, string.Empty, queue, consumer);
|
AddExchangeConsumer(exchange, string.Empty, queue, consumer);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AddEventConsumer(string exchange, string queueName, string routingKey, ConsumeEventHandler consumer)
|
private async Task AddEventConsumer(string exchange, string queueName, string routingKey, ConsumeEventHandler consumer)
|
||||||
{
|
{
|
||||||
|
if (!_configuration.Enabled)
|
||||||
|
{
|
||||||
|
_logger.LogInformation("RabbitMQ is disabled. Event consumer will not be added.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var key = $"{exchange}-{routingKey}";
|
var key = $"{exchange}-{routingKey}";
|
||||||
|
|
||||||
if (!_consumers.TryGetValue(key, out var consumers))
|
if (!_consumers.TryGetValue(key, out var consumers))
|
||||||
@ -135,10 +144,10 @@ public sealed class RabbitMqHandler : BackgroundService
|
|||||||
consumers = new List<ConsumeEventHandler>();
|
consumers = new List<ConsumeEventHandler>();
|
||||||
_consumers.TryAdd(key, consumers);
|
_consumers.TryAdd(key, consumers);
|
||||||
|
|
||||||
var eventHandler = new AsyncEventingBasicConsumer(_channel);
|
var eventHandler = new AsyncEventingBasicConsumer(_channel!);
|
||||||
eventHandler.Received += CallEventConsumersAsync;
|
eventHandler.ReceivedAsync += CallEventConsumersAsync;
|
||||||
|
|
||||||
_channel!.BasicConsume(queueName, false, eventHandler);
|
await _channel!.BasicConsumeAsync(queueName, false, eventHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
consumers.Add(consumer);
|
consumers.Add(consumer);
|
||||||
@ -202,19 +211,19 @@ public sealed class RabbitMqHandler : BackgroundService
|
|||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
HandleEnqueuedActions();
|
await HandleEnqueuedActions();
|
||||||
|
|
||||||
await Task.Delay(1000, stoppingToken);
|
await Task.Delay(1000, stoppingToken);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void HandleEnqueuedActions()
|
private async Task HandleEnqueuedActions()
|
||||||
{
|
{
|
||||||
while (_pendingActions.TryDequeue(out var action))
|
while (_pendingActions.TryDequeue(out var action))
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
action.Perform(_channel!);
|
await action.Perform(_channel!);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net8.0</TargetFramework>
|
<TargetFramework>net9.0</TargetFramework>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
|
|
||||||
<IsPackable>false</IsPackable>
|
<IsPackable>false</IsPackable>
|
||||||
@ -9,7 +9,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="FluentAssertions" Version="6.12.1" />
|
<PackageReference Include="FluentAssertions" Version="6.12.2" />
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.11.1" />
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.11.1" />
|
||||||
<PackageReference Include="NSubstitute" Version="5.3.0" />
|
<PackageReference Include="NSubstitute" Version="5.3.0" />
|
||||||
<PackageReference Include="xunit" Version="2.9.2" />
|
<PackageReference Include="xunit" Version="2.9.2" />
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net8.0</TargetFramework>
|
<TargetFramework>net9.0</TargetFramework>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
@ -12,10 +12,10 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="MediatR" Version="12.4.1" />
|
<PackageReference Include="MediatR" Version="12.4.1" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.10" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.0" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="8.0.10" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="9.0.0" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.10" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="9.0.0" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.10">
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="9.0.0">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net8.0</TargetFramework>
|
<TargetFramework>net9.0</TargetFramework>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
|
|
||||||
<IsPackable>false</IsPackable>
|
<IsPackable>false</IsPackable>
|
||||||
@ -9,9 +9,9 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="FluentAssertions" Version="6.12.1" />
|
<PackageReference Include="FluentAssertions" Version="6.12.2" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="8.0.10" />
|
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="9.0.0" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Proxies" Version="8.0.10" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Proxies" Version="9.0.0" />
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.11.1" />
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.11.1" />
|
||||||
<PackageReference Include="NUnit" Version="4.2.2" />
|
<PackageReference Include="NUnit" Version="4.2.2" />
|
||||||
<PackageReference Include="NUnit.Analyzers" Version="4.3.0">
|
<PackageReference Include="NUnit.Analyzers" Version="4.3.0">
|
||||||
@ -20,10 +20,10 @@
|
|||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="NUnit3TestAdapter" Version="4.6.0" />
|
<PackageReference Include="NUnit3TestAdapter" Version="4.6.0" />
|
||||||
<PackageReference Include="Respawn" Version="6.2.1" />
|
<PackageReference Include="Respawn" Version="6.2.1" />
|
||||||
<PackageReference Include="Testcontainers" Version="3.10.0" />
|
<PackageReference Include="Testcontainers" Version="4.0.0" />
|
||||||
<PackageReference Include="Testcontainers.MsSql" Version="3.10.0" />
|
<PackageReference Include="Testcontainers.MsSql" Version="4.0.0" />
|
||||||
<PackageReference Include="Testcontainers.RabbitMq" Version="3.10.0" />
|
<PackageReference Include="Testcontainers.RabbitMq" Version="4.0.0" />
|
||||||
<PackageReference Include="Testcontainers.Redis" Version="3.10.0" />
|
<PackageReference Include="Testcontainers.Redis" Version="4.0.0" />
|
||||||
<PackageReference Include="coverlet.collector" Version="6.0.2">
|
<PackageReference Include="coverlet.collector" Version="6.0.2">
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net8.0</TargetFramework>
|
<TargetFramework>net9.0</TargetFramework>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net8.0</TargetFramework>
|
<TargetFramework>net9.0</TargetFramework>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net8.0</TargetFramework>
|
<TargetFramework>net9.0</TargetFramework>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
|
|
||||||
<IsPackable>false</IsPackable>
|
<IsPackable>false</IsPackable>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="FluentAssertions" Version="6.12.1" />
|
<PackageReference Include="FluentAssertions" Version="6.12.2" />
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.11.1" />
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.11.1" />
|
||||||
<PackageReference Include="MockQueryable.NSubstitute" Version="7.0.3" />
|
<PackageReference Include="MockQueryable.NSubstitute" Version="7.0.3" />
|
||||||
<PackageReference Include="NSubstitute" Version="5.3.0" />
|
<PackageReference Include="NSubstitute" Version="5.3.0" />
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net8.0</TargetFramework>
|
<TargetFramework>net9.0</TargetFramework>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
FROM --platform=$BUILDPLATFORM mcr.microsoft.com/dotnet/aspnet:8.0 AS base
|
FROM --platform=$BUILDPLATFORM mcr.microsoft.com/dotnet/aspnet:9.0 AS base
|
||||||
USER $APP_UID
|
USER $APP_UID
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
FROM --platform=$BUILDPLATFORM mcr.microsoft.com/dotnet/sdk:8.0 AS build
|
FROM --platform=$BUILDPLATFORM mcr.microsoft.com/dotnet/sdk:9.0 AS build
|
||||||
ARG BUILD_CONFIGURATION=Release
|
ARG BUILD_CONFIGURATION=Release
|
||||||
ARG TARGETARCH
|
ARG TARGETARCH
|
||||||
WORKDIR /src
|
WORKDIR /src
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
# Clean Architecture Dotnet 8 API Project
|
# Clean Architecture Dotnet 9 API Project
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
@ -78,4 +78,4 @@ To run the tests, follow these steps:
|
|||||||
This project uses GitHub Actions to build and test the project on every commit to the main branch. The workflow consists of several steps, including restoring packages, building the project and running tests.
|
This project uses GitHub Actions to build and test the project on every commit to the main branch. The workflow consists of several steps, including restoring packages, building the project and running tests.
|
||||||
|
|
||||||
## Conclusion
|
## Conclusion
|
||||||
This project is a sample implementation of the Clean Architecture principles, Onion Architecture, MediatR, and Entity Framework. It demonstrates how to organize a .NET 8 API project into layers, how to use the MediatR library to implement the mediator pattern, and how to use Entity Framework to access data. It also includes unit tests for all layers and integration tests using xUnit.
|
This project is a sample implementation of the Clean Architecture principles, Onion Architecture, MediatR, and Entity Framework. It demonstrates how to organize a .NET 9 API project into layers, how to use the MediatR library to implement the mediator pattern, and how to use Entity Framework to access data. It also includes unit tests for all layers and integration tests using xUnit.
|
||||||
|
Loading…
Reference in New Issue
Block a user