diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6bb4f649..b47fd488 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,52 @@ All notable changes to this project will be documented in this file. Dates are d
Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
+#### [v7.2.0](https://github.com/Genocs/genocs-library/compare/v7.1.0...v7.2.0)
+
+> 14 December 2024
+
+- Update versions, remove Polly, and add configuration files [`bbb923f`](https://github.com/Genocs/genocs-library/commit/bbb923f2c15dc5bd99237d76a0114a2984f9d168)
+- Refactor and update codebase for C# 9.0 features [`74926b3`](https://github.com/Genocs/genocs-library/commit/74926b3edc638b9a7179ae6d3e746eec346cd0ab)
+- Add new service, project, and OpenTelemetry config [`42292cf`](https://github.com/Genocs/genocs-library/commit/42292cffc5b4b329377bf6adaf243504b3bc6073)
+- Refactor for multiple roles and sync methods [`db339c2`](https://github.com/Genocs/genocs-library/commit/db339c2ef27cd15cbbde0bfe9b1c9dac6e0a0c12)
+- Refactor authentication and JWT handling components [`5636ddc`](https://github.com/Genocs/genocs-library/commit/5636ddc9479d0a80a9c9c87c9175dc33f38d55bb)
+- Update configuration settings and service details [`1040881`](https://github.com/Genocs/genocs-library/commit/104088196666c31668f93a52fb89d6d2a70b7943)
+- Refactor namespaces and update OpenTelemetry config [`af280e0`](https://github.com/Genocs/genocs-library/commit/af280e0b6a7b08ab333f0ff2339aa068811f0f27)
+- Refactor and update configurations and dependencies [`2ba4d28`](https://github.com/Genocs/genocs-library/commit/2ba4d2829a4e635e2b52b0ea022716edd75c6f1c)
+- Add OpenTelemetry support and update various configurations [`0e6140b`](https://github.com/Genocs/genocs-library/commit/0e6140ba2ebb2bac7671e28e925546cca4611009)
+- Add CreateAdmin feature and refactor user creation [`dd2dfdf`](https://github.com/Genocs/genocs-library/commit/dd2dfdfe40cd45cc3ba02d7aaa04f7b8c1368f47)
+- Upgrade to .NET 9.0 and refine project configurations [`3fbbc7e`](https://github.com/Genocs/genocs-library/commit/3fbbc7e5597c7bb0b59383b39b0b4aedbf99bc8b)
+- Enhance JWT authentication and code organization [`5894fd7`](https://github.com/Genocs/genocs-library/commit/5894fd7232171ff202a9c2946b88602a149eec03)
+- Add JWT authentication and enhance authorization policies [`48b01f3`](https://github.com/Genocs/genocs-library/commit/48b01f31ac67b5bb9e60dcaf9d119031707bf23c)
+- Enhance logging, JWT options, and health checks [`86875f5`](https://github.com/Genocs/genocs-library/commit/86875f5d53e372be8a82f1bd2030aaacda6a7914)
+- Enable services and enhance configuration settings [`2654fe6`](https://github.com/Genocs/genocs-library/commit/2654fe6b756e97034960ba73c39b57429678295f)
+- Refactor JWT handling and improve code readability [`b525d35`](https://github.com/Genocs/genocs-library/commit/b525d35a18add383b0960d4405069b91a97decd5)
+- Refactor and improve nullability handling [`07bee95`](https://github.com/Genocs/genocs-library/commit/07bee95f1226ab4406078380da2b25744f413d8e)
+- Add console exporter support for OpenTelemetry [`5f0ca21`](https://github.com/Genocs/genocs-library/commit/5f0ca21d0f36032c62102833ea95ad63c1b809aa)
+- Update error handling, tracing, and configuration [`eda7085`](https://github.com/Genocs/genocs-library/commit/eda7085847b057983269dd6fd08c237644dfe553)
+- Enhance GenocsBuilder and update Program.cs structure [`23aa7c6`](https://github.com/Genocs/genocs-library/commit/23aa7c6418365f49be9de771be028dae7758c02a)
+- Standardize property names and improve documentation [`8e48cfa`](https://github.com/Genocs/genocs-library/commit/8e48cfa891777398b276965dd3f02d3b536e75ad)
+- Add OtlpEndpoint to LoggerOptions and update exception handling [`3df7280`](https://github.com/Genocs/genocs-library/commit/3df72803f83a03922523c036cfe2686cd9c0bfec)
+- Update package versions and modify exception logic [`f24c465`](https://github.com/Genocs/genocs-library/commit/f24c46508d67da55fab3cc96c3ebb295977e9222)
+
+#### [v7.1.0](https://github.com/Genocs/genocs-library/compare/v7.0.0...v7.1.0)
+
+> 29 November 2024
+
+- Update packages and refactor MongoDB repository methods [`#126`](https://github.com/Genocs/genocs-library/pull/126)
+- Ver 700 [`#125`](https://github.com/Genocs/genocs-library/pull/125)
+- Update CHANGELOG for v7.0.0 release with recent changes and improvements [`#121`](https://github.com/Genocs/genocs-library/pull/121)
+- Refactor RabbitMQ client to use async methods [`d5cf8ab`](https://github.com/Genocs/genocs-library/commit/d5cf8abe6b4a4a21712579373858431ea3f5589c)
+- Update appsettings and refactor code for services [`b9e6e8c`](https://github.com/Genocs/genocs-library/commit/b9e6e8c43a700c1865f1ed23c561b0c69a4ce417)
+- Update Docker, health checks, and service configurations [`828c7a7`](https://github.com/Genocs/genocs-library/commit/828c7a775b3eb095204e5df0e62614bfbebe6705)
+- Add .env template, update appsettings for Docker compatibility, and modify service configurations [`c3c6488`](https://github.com/Genocs/genocs-library/commit/c3c64884098deafec6053bd3838eaefbb67bc4ea)
+- Update package references to Genocs.Core and related packages to version 7.1.0 [`a8b8c4a`](https://github.com/Genocs/genocs-library/commit/a8b8c4a9baff9e54c9e38a0cd20bad4bbea5a0dd)
+- Refactor and update nullability and configurations [`992c33d`](https://github.com/Genocs/genocs-library/commit/992c33d33e686d5f573d899c911cd297ad086637)
+- Refactor constructors and update Program.cs endpoints [`4f14136`](https://github.com/Genocs/genocs-library/commit/4f14136419cb43d8619721f02ce4082c92d880fb)
+- Refactor service registration and update dependencies [`78a7892`](https://github.com/Genocs/genocs-library/commit/78a789238db6c2e6def7b1d8103facf1092191e5)
+- Upgrade packages and modify NotificationId property [`77bbd75`](https://github.com/Genocs/genocs-library/commit/77bbd75766d14dcde87d386e84e3ccfb248a5062)
+- Disable Azure logging and clear connection strings [`3a44081`](https://github.com/Genocs/genocs-library/commit/3a440812ef71aa64ecf0a1a829943d8c2723edd6)
+
### [v7.0.0](https://github.com/Genocs/genocs-library/compare/v6.4.0...v7.0.0)
> 24 November 2024
diff --git a/Directory.Build.props b/Directory.Build.props
index ae739882..b2374060 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -13,7 +13,7 @@
$(MSBuildThisFileDirectory)dotnet.ruleset
True
True
- 6.3.0
+ 7.1.0
13.0
Genocs
Genocs 2024
diff --git a/containers/infrastructure-monitoring.yml b/containers/infrastructure-monitoring.yml
index 6eeedab9..9956e84d 100644
--- a/containers/infrastructure-monitoring.yml
+++ b/containers/infrastructure-monitoring.yml
@@ -1,4 +1,19 @@
services:
+ aspire:
+ image: mcr.microsoft.com/dotnet/aspire-dashboard:9.0
+ hostname: aspire_dashboard
+ container_name: aspire_dashboard
+ ports:
+ - 18888:18888
+ - 4318:18889
+
+ environment:
+ - DOTNET_DASHBOARD_UNSECURED_ALLOW_ANONYMOUS=true
+
+ networks:
+ - genocs
+ # network_mode: host
+
grafana:
image: grafana/grafana
hostname: grafana
diff --git a/genocs.sln b/genocs.sln
index dac56edb..53366e9e 100644
--- a/genocs.sln
+++ b/genocs.sln
@@ -123,14 +123,18 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Application", "Application"
src\apps\docker-compose.override.yml = src\apps\docker-compose.override.yml
src\apps\docker-compose.yml = src\apps\docker-compose.yml
src\apps\identity-webapi.dockerfile = src\apps\identity-webapi.dockerfile
- src\apps\order-webapi.dockerfile = src\apps\order-webapi.dockerfile
src\apps\local.env = src\apps\local.env
+ src\apps\order-webapi.dockerfile = src\apps\order-webapi.dockerfile
src\apps\product-webapi.dockerfile = src\apps\product-webapi.dockerfile
src\apps\signalr-webapi.dockerfile = src\apps\signalr-webapi.dockerfile
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Genocs.Secrets.AzureKeyVault", "src\Genocs.Secrets.AzureKeyVault\Genocs.Secrets.AzureKeyVault.csproj", "{ECBF1AEE-AE3A-4F81-9943-5675169DEFA7}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Genocs.OpenTelemetry", "src\Genocs.OpenTelemetry\Genocs.OpenTelemetry.csproj", "{62380657-23D0-0ECD-8FFE-0B1DA5461D37}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Genocs.Core.Demo.HelloWorld", "src\Genocs.Core.Demo.HelloWorld\Genocs.Core.Demo.HelloWorld.csproj", "{D7C394CF-487D-470D-B05C-CC2DD7EC290B}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -297,6 +301,14 @@ Global
{ECBF1AEE-AE3A-4F81-9943-5675169DEFA7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{ECBF1AEE-AE3A-4F81-9943-5675169DEFA7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{ECBF1AEE-AE3A-4F81-9943-5675169DEFA7}.Release|Any CPU.Build.0 = Release|Any CPU
+ {62380657-23D0-0ECD-8FFE-0B1DA5461D37}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {62380657-23D0-0ECD-8FFE-0B1DA5461D37}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {62380657-23D0-0ECD-8FFE-0B1DA5461D37}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {62380657-23D0-0ECD-8FFE-0B1DA5461D37}.Release|Any CPU.Build.0 = Release|Any CPU
+ {D7C394CF-487D-470D-B05C-CC2DD7EC290B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {D7C394CF-487D-470D-B05C-CC2DD7EC290B}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {D7C394CF-487D-470D-B05C-CC2DD7EC290B}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {D7C394CF-487D-470D-B05C-CC2DD7EC290B}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -325,6 +337,7 @@ Global
{B2028A73-6C94-4166-A0BB-22080805E351} = {140B7191-88E9-4EEE-9D86-9A70839F8507}
{6CE8740F-8561-481B-AC9F-D1E73C449235} = {B2028A73-6C94-4166-A0BB-22080805E351}
{B184733D-2415-4517-BC65-26ED22EEB2C2} = {51A2E158-4686-4764-91D5-3CDDD06280D4}
+ {D7C394CF-487D-470D-B05C-CC2DD7EC290B} = {220036E9-322D-4D4A-BA98-21DCF111C50A}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {FF634A51-3CA4-4FB3-A8ED-71C403516166}
diff --git a/global.json b/global.json
index f6d787e3..6d77f621 100644
--- a/global.json
+++ b/global.json
@@ -1,7 +1,7 @@
{
"sdk": {
- "version": "8.0.10",
+ "version": "9.0.0",
"rollForward": "latestMajor",
"allowPrerelease": true
}
-}
\ No newline at end of file
+}
diff --git a/launchSettings.json b/launchSettings.json
index c0eaff1c..dc2b791d 100644
--- a/launchSettings.json
+++ b/launchSettings.json
@@ -8,4 +8,4 @@
}
}
}
-}
\ No newline at end of file
+}
diff --git a/src/Genocs.Auth/AccessTokenValidatorMiddleware.cs b/src/Genocs.Auth/AccessTokenValidatorMiddleware.cs
index b0de9341..3a867872 100644
--- a/src/Genocs.Auth/AccessTokenValidatorMiddleware.cs
+++ b/src/Genocs.Auth/AccessTokenValidatorMiddleware.cs
@@ -7,43 +7,36 @@ namespace Genocs.Auth;
///
/// The access token validator middleware.
///
-public class AccessTokenValidatorMiddleware : IMiddleware
+///
+/// The AccessTokenValidatorMiddleware constructor.
+///
+/// The access token service.
+/// The options.
+public class AccessTokenValidatorMiddleware(IAccessTokenService accessTokenService, JwtOptions options) : IMiddleware
{
- private readonly IAccessTokenService _accessTokenService;
- private readonly IEnumerable _endpoints;
-
- ///
- /// The AccessTokenValidatorMiddleware constructor.
- ///
- /// The access token service.
- /// The options.
- public AccessTokenValidatorMiddleware(IAccessTokenService accessTokenService, JwtOptions options)
- {
- _accessTokenService = accessTokenService;
- _endpoints = options.AllowAnonymousEndpoints ?? Enumerable.Empty();
- }
+ private readonly IAccessTokenService _accessTokenService = accessTokenService;
+ private readonly IEnumerable _allowAnonymousEndpoints = options.AllowAnonymousEndpoints ?? [];
///
/// The InvokeAsync method.
///
/// The http context.
/// The request delegate.
- ///
+ /// The task.
public async Task InvokeAsync(HttpContext context, RequestDelegate next)
{
string path = context.Request.Path.HasValue ? context.Request.Path.Value : string.Empty;
- if (_endpoints.Contains(path))
+ // Skip check on AnonymousEndpoints
+ if (_allowAnonymousEndpoints.Contains(path))
{
await next(context);
-
return;
}
- if (await _accessTokenService.IsCurrentActiveToken())
+ if (_accessTokenService.IsCurrentActiveToken())
{
await next(context);
-
return;
}
diff --git a/src/Genocs.Auth/Configurations/JwtOptions.cs b/src/Genocs.Auth/Configurations/JwtOptions.cs
index 79566a5c..3f13edf3 100644
--- a/src/Genocs.Auth/Configurations/JwtOptions.cs
+++ b/src/Genocs.Auth/Configurations/JwtOptions.cs
@@ -1,3 +1,5 @@
+using Microsoft.IdentityModel.Tokens;
+
namespace Genocs.Auth.Configurations;
public class JwtOptions
@@ -14,7 +16,12 @@ public class JwtOptions
public IEnumerable? AllowAnonymousEndpoints { get; set; }
public CertificateOptions? Certificate { get; set; }
- public string? Algorithm { get; set; }
+
+ ///
+ /// The algorithm used to sign the token.
+ /// Defaults to SecurityAlgorithms.HmacSha256 'HS256'.
+ ///
+ public string Algorithm { get; set; } = SecurityAlgorithms.HmacSha256;
public string? Issuer { get; set; }
public string? IssuerSigningKey { get; set; }
public string? Authority { get; set; }
@@ -31,7 +38,12 @@ public class JwtOptions
public bool RequireHttpsMetadata { get; set; }
public bool RequireExpirationTime { get; set; } = true;
public bool RequireSignedTokens { get; set; } = true;
- public int ExpiryMinutes { get; set; }
+
+ ///
+ /// The expiration time of the token in minutes.
+ /// Defaults to 60 minutes.
+ ///
+ public int ExpiryMinutes { get; set; } = 60;
public TimeSpan? Expiry { get; set; }
public string? ValidAudience { get; set; }
public IEnumerable? ValidAudiences { get; set; }
@@ -65,19 +77,31 @@ public class JwtOptions
/// Defaults to true.
///
public bool IncludeErrorDetails { get; set; } = true;
+
public string? AuthenticationType { get; set; }
public string? NameClaimType { get; set; }
///
/// The claim type that will be used to determine the user's roles.
- /// Defaults to "Role".
+ /// Default is "Role".
///
public string RoleClaimType { get; set; } = "Role";
public class CertificateOptions
{
+ ///
+ /// The location of the certificate.
+ ///
public string? Location { get; set; }
+
+ ///
+ /// The certificate as a byte array.
+ ///
public string? RawData { get; set; }
+
+ ///
+ /// The certificate password.
+ ///
public string? Password { get; set; }
}
}
\ No newline at end of file
diff --git a/src/Genocs.Auth/DisabledAuthenticationPolicyEvaluator.cs b/src/Genocs.Auth/DisabledAuthenticationPolicyEvaluator.cs
index 85cc1ab8..c4cf0edf 100644
--- a/src/Genocs.Auth/DisabledAuthenticationPolicyEvaluator.cs
+++ b/src/Genocs.Auth/DisabledAuthenticationPolicyEvaluator.cs
@@ -17,10 +17,7 @@ internal sealed class DisabledAuthenticationPolicyEvaluator : IPolicyEvaluator
///
public Task AuthenticateAsync(AuthorizationPolicy policy, HttpContext context)
{
- var authenticationTicket = new AuthenticationTicket(
- new ClaimsPrincipal(),
- new AuthenticationProperties(),
- JwtBearerDefaults.AuthenticationScheme);
+ var authenticationTicket = new AuthenticationTicket(new ClaimsPrincipal(), new AuthenticationProperties(), JwtBearerDefaults.AuthenticationScheme);
return Task.FromResult(AuthenticateResult.Success(authenticationTicket));
}
@@ -33,11 +30,7 @@ public Task AuthenticateAsync(AuthorizationPolicy policy, Ht
///
///
///
- public Task AuthorizeAsync(
- AuthorizationPolicy policy,
- AuthenticateResult authenticationResult,
- HttpContext context,
- object resource)
+ public Task AuthorizeAsync(AuthorizationPolicy policy, AuthenticateResult authenticationResult, HttpContext context, object resource)
{
return Task.FromResult(PolicyAuthorizationResult.Success());
}
diff --git a/src/Genocs.Auth/Extensions.cs b/src/Genocs.Auth/Extensions.cs
index 05e93b9f..6abd6e6b 100644
--- a/src/Genocs.Auth/Extensions.cs
+++ b/src/Genocs.Auth/Extensions.cs
@@ -1,3 +1,5 @@
+using System.Security.Cryptography.X509Certificates;
+using System.Text;
using Genocs.Auth.Configurations;
using Genocs.Auth.Handlers;
using Genocs.Auth.Services;
@@ -11,8 +13,6 @@
using Microsoft.IdentityModel.Protocols;
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
using Microsoft.IdentityModel.Tokens;
-using System.Security.Cryptography.X509Certificates;
-using System.Text;
namespace Genocs.Auth;
@@ -20,10 +20,14 @@ public static class Extensions
{
private const string RegistryName = "auth";
- public static IGenocsBuilder AddJwt(
- this IGenocsBuilder builder,
- string sectionName = JwtOptions.Position,
- Action? optionsFactory = null)
+ ///
+ /// Add JWT authentication.
+ ///
+ /// The Genocs builder.
+ /// The JWT configuration section in case you want to change the default name.
+ /// The option builder action in case option requires custom action to be done.
+ /// The Genocs builder you can use for chain.
+ public static IGenocsBuilder AddJwt(this IGenocsBuilder builder, string sectionName = JwtOptions.Position, Action? optionsFactory = null)
{
if (string.IsNullOrWhiteSpace(sectionName))
{
@@ -34,26 +38,32 @@ public static IGenocsBuilder AddJwt(
return builder.AddJwt(options, optionsFactory);
}
- private static IGenocsBuilder AddJwt(
- this IGenocsBuilder builder,
- JwtOptions options,
- Action? optionsFactory = null)
+ ///
+ /// Add JWT authentication. Internal function.
+ ///
+ /// The Genocs builder.
+ /// The JWT options.
+ /// The option builder action in case option requires custom action to be done.
+ /// The Genocs builder you can use for chain.
+ private static IGenocsBuilder AddJwt(this IGenocsBuilder builder, JwtOptions options, Action? optionsFactory = null)
{
if (!builder.TryRegister(RegistryName))
{
return builder;
}
- builder.Services.AddSingleton();
- builder.Services.AddSingleton();
- builder.Services.AddSingleton();
- builder.Services.AddTransient();
-
if (!options.Enabled)
{
builder.Services.AddSingleton();
}
+ // To be able to access the HttpContext in the InMemoryAccessTokenService
+ builder.Services.AddSingleton();
+
+ builder.Services.AddSingleton();
+ builder.Services.AddSingleton();
+ builder.Services.AddTransient();
+
var tokenValidationParameters = new TokenValidationParameters
{
RequireAudience = options.RequireAudience,
@@ -121,13 +131,8 @@ private static IGenocsBuilder AddJwt(
// If no certificate is provided, use symmetric encryption.
if (!string.IsNullOrWhiteSpace(options.IssuerSigningKey) && !hasCertificate)
{
- if (string.IsNullOrWhiteSpace(options.Algorithm) || hasCertificate)
- {
- options.Algorithm = SecurityAlgorithms.HmacSha256;
- }
-
- byte[] rawKey = Encoding.UTF8.GetBytes(options.IssuerSigningKey);
- tokenValidationParameters.IssuerSigningKey = new SymmetricSecurityKey(rawKey);
+ byte[] key = Encoding.UTF8.GetBytes(options.IssuerSigningKey);
+ tokenValidationParameters.IssuerSigningKey = new SymmetricSecurityKey(key);
Console.WriteLine("Using symmetric encryption for issuing tokens.");
}
@@ -141,6 +146,9 @@ private static IGenocsBuilder AddJwt(
tokenValidationParameters.RoleClaimType = options.RoleClaimType;
}
+ // Authorization settings
+ builder.Services.AddAuthorization();
+
builder.Services
.AddAuthentication(o =>
{
@@ -179,12 +187,14 @@ private static IGenocsBuilder AddJwt(
/// The Genocs builder.
/// The configuration section name.
/// The Genocs builder you can use for chain.
- public static IGenocsBuilder AddOpenIdJwt(
- this IGenocsBuilder builder,
- string sectionName = JwtOptions.Position)
+ public static IGenocsBuilder AddOpenIdJwt(this IGenocsBuilder builder, string sectionName = JwtOptions.Position)
{
+ if (string.IsNullOrWhiteSpace(sectionName))
+ {
+ sectionName = JwtOptions.Position;
+ }
- JwtOptions options = builder.Configuration.GetOptions(sectionName);
+ JwtOptions options = builder.Configuration!.GetOptions(sectionName);
string metadataAddress = $"{options.Issuer}{options.MetadataAddress}";
var configurationManager = new ConfigurationManager(metadataAddress, new OpenIdConnectConfigurationRetriever());
@@ -215,16 +225,14 @@ public static IGenocsBuilder AddOpenIdJwt(
/// The optional section name. Default name: 'jwt'.
/// The Genocs builder you can use for chaining.
/// Whenever mandatory data like 'IssuerSigningKey' is missing.
- public static IGenocsBuilder AddPrivateKeyJwt(
- this IGenocsBuilder builder,
- string sectionName = JwtOptions.Position)
+ public static IGenocsBuilder AddPrivateKeyJwt(this IGenocsBuilder builder, string sectionName = JwtOptions.Position)
{
if (string.IsNullOrWhiteSpace(sectionName))
{
sectionName = JwtOptions.Position;
}
- JwtOptions options = builder.Configuration.GetOptions(sectionName);
+ JwtOptions options = builder.Configuration!.GetOptions(sectionName);
if (string.IsNullOrWhiteSpace(options.IssuerSigningKey))
{
@@ -257,6 +265,11 @@ public static IGenocsBuilder AddPrivateKeyJwt(
return builder;
}
+ ///
+ /// This middleware validates the access token in real-time.
+ ///
+ /// The app builder.
+ /// The app builder you can use for chaining.
public static IApplicationBuilder UseAccessTokenValidator(this IApplicationBuilder app)
=> app.UseMiddleware();
}
@@ -271,5 +284,5 @@ internal static class DateExtensions
///
///
///
- public static long ToTimestamp(this DateTime dateTime) => new DateTimeOffset(dateTime).ToUnixTimeSeconds();
+ public static long ToTimestamp(this in DateTime dateTime) => new DateTimeOffset(dateTime).ToUnixTimeSeconds();
}
\ No newline at end of file
diff --git a/src/Genocs.Auth/Genocs.Auth.csproj b/src/Genocs.Auth/Genocs.Auth.csproj
index f8482eb1..0fa6533c 100644
--- a/src/Genocs.Auth/Genocs.Auth.csproj
+++ b/src/Genocs.Auth/Genocs.Auth.csproj
@@ -5,14 +5,14 @@
Genocs.Auth
Genocs.Auth
Genocs.Auth
- The authorization library useful to build .NET Core projects.
- The authorization library useful to build .NET Core projects.
+ The Genocs authorization library.
+ The authorization library.
true
5.0.0
Nocco Giovanni Emanuele
- microservice microservices solid solid-principles authentication genocs
+ authentication jwt genocs microservice microservices solid solid-principles
README_NUGET.md
- Aligned to the ecosystem
+ Upgraded to NET9.0
True
latest
@@ -20,7 +20,6 @@
-
@@ -29,22 +28,18 @@
-
-
+
-
-
-
diff --git a/src/Genocs.Auth/Handlers/JwtHandler.cs b/src/Genocs.Auth/Handlers/JwtHandler.cs
index 36e197e0..ce517fc0 100644
--- a/src/Genocs.Auth/Handlers/JwtHandler.cs
+++ b/src/Genocs.Auth/Handlers/JwtHandler.cs
@@ -1,15 +1,14 @@
-using Genocs.Auth.Configurations;
-using Microsoft.IdentityModel.Tokens;
+using System.Data;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
+using System.Text;
+using Genocs.Auth.Configurations;
+using Microsoft.IdentityModel.Tokens;
namespace Genocs.Auth.Handlers;
internal sealed class JwtHandler : IJwtHandler
{
- private static readonly IDictionary> EmptyClaims =
- new Dictionary>();
-
private static readonly ISet DefaultClaims = new HashSet
{
JwtRegisteredClaimNames.Sub,
@@ -23,41 +22,34 @@ internal sealed class JwtHandler : IJwtHandler
private readonly JwtOptions _options;
private readonly TokenValidationParameters _tokenValidationParameters;
private readonly SigningCredentials _signingCredentials;
- private readonly string? _issuer;
public JwtHandler(JwtOptions options, TokenValidationParameters tokenValidationParameters)
{
- var issuerSigningKey = tokenValidationParameters.IssuerSigningKey;
- if (issuerSigningKey is null)
- {
- throw new InvalidOperationException("Issuer signing key not set.");
- }
+ var issuerSigningKey = tokenValidationParameters.IssuerSigningKey
+ ?? throw new InvalidOperationException("Issuer signing key not set.");
if (string.IsNullOrWhiteSpace(options.Algorithm))
{
- throw new InvalidOperationException("Security algorithm not set.");
+ options.Algorithm = issuerSigningKey is SymmetricSecurityKey
+ ? SecurityAlgorithms.HmacSha256
+ : SecurityAlgorithms.RsaSha256;
}
_options = options;
_tokenValidationParameters = tokenValidationParameters;
_signingCredentials = new SigningCredentials(issuerSigningKey, _options.Algorithm);
- _issuer = options.Issuer;
}
///
/// Creates a new token.
///
- ///
- ///
- ///
- ///
+ /// The UserId.
+ /// The User Role.
+ /// The audience.
+ /// The list of claims.
///
/// It is thrown when mandatory data is empty.
- public JsonWebToken CreateToken(
- string userId,
- string? role = null,
- string? audience = null,
- IDictionary>? claims = null)
+ public JsonWebToken CreateToken(string userId, IEnumerable? roles = null, string? audience = null, IDictionary>? claims = null)
{
if (string.IsNullOrWhiteSpace(userId))
{
@@ -73,9 +65,12 @@ public JsonWebToken CreateToken(
new(JwtRegisteredClaimNames.Iat, now.ToTimestamp().ToString()),
};
- if (!string.IsNullOrWhiteSpace(role))
+ if (roles is not null)
{
- jwtClaims.Add(new Claim(ClaimTypes.Role, role));
+ foreach (string item in roles.Where(x => !string.IsNullOrEmpty(x)))
+ {
+ jwtClaims.Add(new Claim(ClaimTypes.Role, item));
+ }
}
if (!string.IsNullOrWhiteSpace(audience))
@@ -99,36 +94,33 @@ public JsonWebToken CreateToken(
: now.AddMinutes(_options.ExpiryMinutes);
var jwt = new JwtSecurityToken(
- _issuer,
+ issuer: _options.Issuer,
claims: jwtClaims,
notBefore: now,
expires: expires,
signingCredentials: _signingCredentials);
- string token = new JwtSecurityTokenHandler().WriteToken(jwt);
+ string token = _jwtSecurityTokenHandler.WriteToken(jwt);
return new JsonWebToken
{
+ Id = userId,
AccessToken = token,
RefreshToken = string.Empty,
Expires = expires.ToTimestamp(),
- Id = userId,
- Role = role ?? string.Empty,
- Claims = claims ?? EmptyClaims
+ Roles = roles,
+ Claims = claims
};
}
///
/// Gets the token payload.
///
- ///
- ///
- public JsonWebTokenPayload? GetTokenPayload(string accessToken)
+ /// The string describing the access token.
+ /// The JWT Token payload.
+ public JsonWebTokenPayload? GetTokenPayload(string token)
{
- _jwtSecurityTokenHandler.ValidateToken(
- accessToken,
- _tokenValidationParameters,
- out var validatedSecurityToken);
+ _jwtSecurityTokenHandler.ValidateToken(token, _tokenValidationParameters, out var validatedSecurityToken);
if (validatedSecurityToken is not JwtSecurityToken jwt)
{
@@ -138,11 +130,56 @@ public JsonWebToken CreateToken(
return new JsonWebTokenPayload
{
Subject = jwt.Subject,
- Role = jwt.Claims.SingleOrDefault(x => x.Type == ClaimTypes.Role)?.Value,
+ Roles = jwt.Claims.Where(x => x.Type == ClaimTypes.Role)?.Select(c => c.Value),
Expires = jwt.ValidTo.ToTimestamp(),
Claims = jwt.Claims.Where(x => !DefaultClaims.Contains(x.Type))
.GroupBy(c => c.Type)
.ToDictionary(k => k.Key, v => v.Select(c => c.Value))
};
}
+
+ ///
+ /// This method creates a token using the JwtSecurityTokenHandler class.
+ ///
+ /// The JWT token string.
+ public string CreateToken()
+ {
+ SecurityTokenDescriptor tokenDescriptor = CreateSecurityTokenDescriptor();
+
+ var tokenHandler = new JwtSecurityTokenHandler();
+ var token = tokenHandler.CreateToken(tokenDescriptor);
+ return tokenHandler.WriteToken(token);
+ }
+
+ ///
+ /// This method creates a token using the JsonWebTokenHandler class.
+ ///
+ /// The JWT token string.
+ public string CreateTokenWithJsonWebTokenHandler()
+ {
+ SecurityTokenDescriptor tokenDescriptor = CreateSecurityTokenDescriptor();
+
+ var tokenHandler = new Microsoft.IdentityModel.JsonWebTokens.JsonWebTokenHandler();
+ string token = tokenHandler.CreateToken(tokenDescriptor);
+ return token;
+ }
+
+ ///
+ /// Internal method to create a SecurityTokenDescriptor.
+ ///
+ /// The created SecurityTokenDescriptor.
+ private SecurityTokenDescriptor CreateSecurityTokenDescriptor()
+ {
+ byte[] key = Encoding.ASCII.GetBytes(_options.IssuerSigningKey!);
+ return new SecurityTokenDescriptor
+ {
+ Subject = new ClaimsIdentity(new Claim[]
+ {
+ new Claim(ClaimTypes.Name, "username"),
+ new Claim(ClaimTypes.Role, "role")
+ }),
+ Expires = DateTime.UtcNow.AddMinutes(_options.ExpiryMinutes),
+ SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), _options.Algorithm)
+ };
+ }
}
\ No newline at end of file
diff --git a/src/Genocs.Auth/IAccessTokenService.cs b/src/Genocs.Auth/IAccessTokenService.cs
index a558e622..e22ba769 100644
--- a/src/Genocs.Auth/IAccessTokenService.cs
+++ b/src/Genocs.Auth/IAccessTokenService.cs
@@ -2,8 +2,8 @@ namespace Genocs.Auth;
public interface IAccessTokenService
{
- Task IsCurrentActiveToken();
- Task DeactivateCurrentAsync();
- Task IsActiveAsync(string token);
- Task DeactivateAsync(string token);
+ bool IsCurrentActiveToken();
+ void DeactivateCurrent();
+ bool IsActive(string token);
+ void Deactivate(string token);
}
\ No newline at end of file
diff --git a/src/Genocs.Auth/IJwtHandler.cs b/src/Genocs.Auth/IJwtHandler.cs
index 5720e6fa..8cfba038 100644
--- a/src/Genocs.Auth/IJwtHandler.cs
+++ b/src/Genocs.Auth/IJwtHandler.cs
@@ -9,20 +9,16 @@ public interface IJwtHandler
/// It allows to create a new JsonWebToken.
///
/// The userId.
- /// The role.
+ /// The list of roles.
/// The audience.
/// The claims.
/// The JsonWebToken just created.
- JsonWebToken CreateToken(
- string userId,
- string? role = null,
- string? audience = null,
- IDictionary>? claims = null);
+ JsonWebToken CreateToken(string userId, IEnumerable? roles = null, string? audience = null, IDictionary>? claims = null);
///
/// Get the JsonWebTokenPayload from the accessToken.
///
- /// The access token string value.
+ /// The access token string value.
/// The JsonWebTokenPayload.
- JsonWebTokenPayload? GetTokenPayload(string accessToken);
+ JsonWebTokenPayload? GetTokenPayload(string token);
}
\ No newline at end of file
diff --git a/src/Genocs.Auth/JsonWebToken.cs b/src/Genocs.Auth/JsonWebToken.cs
index bdf2eefc..d982dafd 100644
--- a/src/Genocs.Auth/JsonWebToken.cs
+++ b/src/Genocs.Auth/JsonWebToken.cs
@@ -5,6 +5,11 @@ namespace Genocs.Auth;
///
public class JsonWebToken
{
+ ///
+ /// Gets or sets the access token unique identifier.
+ ///
+ public string? Id { get; set; }
+
///
/// Gets or sets the access token.
///
@@ -20,15 +25,10 @@ public class JsonWebToken
///
public long Expires { get; set; }
- ///
- /// Gets or sets the access token unique identifier.
- ///
- public string? Id { get; set; }
-
///
/// Gets or sets the access token role.
///
- public string? Role { get; set; }
+ public IEnumerable? Roles { get; set; }
///
/// The claims.
diff --git a/src/Genocs.Auth/JsonWebTokenPayload.cs b/src/Genocs.Auth/JsonWebTokenPayload.cs
index b3dcfdc1..1f3f86c1 100644
--- a/src/Genocs.Auth/JsonWebTokenPayload.cs
+++ b/src/Genocs.Auth/JsonWebTokenPayload.cs
@@ -13,15 +13,15 @@ public class JsonWebTokenPayload
///
/// The Identity Role.
///
- public string? Role { get; set; }
+ public IEnumerable? Roles { get; set; }
///
- /// The expiration ticks.
+ /// List of claims.
///
- public long Expires { get; set; }
+ public IDictionary>? Claims { get; set; }
///
- /// List of claims.
+ /// The expiration ticks.
///
- public IDictionary>? Claims { get; set; }
+ public long Expires { get; set; }
}
\ No newline at end of file
diff --git a/src/Genocs.Auth/JwtAuthAttribute.cs b/src/Genocs.Auth/JwtAuthAttribute.cs
index 96439a83..763e0a99 100644
--- a/src/Genocs.Auth/JwtAuthAttribute.cs
+++ b/src/Genocs.Auth/JwtAuthAttribute.cs
@@ -1,11 +1,7 @@
namespace Genocs.Auth;
-public class JwtAuthAttribute : AuthAttribute
+public class JwtAuthAttribute(string policy = "")
+ : AuthAttribute(AuthenticationScheme, policy)
{
public const string AuthenticationScheme = "Bearer";
-
- public JwtAuthAttribute(string policy = "")
- : base(AuthenticationScheme, policy)
- {
- }
}
\ No newline at end of file
diff --git a/src/Genocs.Auth/Services/InMemoryAccessTokenService.cs b/src/Genocs.Auth/Services/InMemoryAccessTokenService.cs
index 8ce4fb58..f1d51329 100644
--- a/src/Genocs.Auth/Services/InMemoryAccessTokenService.cs
+++ b/src/Genocs.Auth/Services/InMemoryAccessTokenService.cs
@@ -5,45 +5,36 @@
namespace Genocs.Auth.Services;
-internal sealed class InMemoryAccessTokenService : IAccessTokenService
+///
+/// This service allows to validate JWT Token in real-time.
+/// In this way tokens can be invalidated and the effect shall be immediate.
+///
+internal sealed class InMemoryAccessTokenService(IMemoryCache cache, IHttpContextAccessor httpContextAccessor, JwtOptions jwtOptions) : IAccessTokenService
{
- private readonly IMemoryCache _cache;
- private readonly IHttpContextAccessor _httpContextAccessor;
- private readonly TimeSpan _expires;
-
- public InMemoryAccessTokenService(
- IMemoryCache cache,
- IHttpContextAccessor httpContextAccessor,
- JwtOptions jwtOptions)
- {
- _cache = cache;
- _httpContextAccessor = httpContextAccessor;
- _expires = jwtOptions.Expiry ?? TimeSpan.FromMinutes(jwtOptions.ExpiryMinutes);
- }
+ private readonly IMemoryCache _cache = cache;
+ private readonly IHttpContextAccessor _httpContextAccessor = httpContextAccessor;
+ private readonly TimeSpan _expires = jwtOptions.Expiry ?? TimeSpan.FromMinutes(jwtOptions.ExpiryMinutes);
- public Task IsCurrentActiveToken()
- => IsActiveAsync(GetCurrentAsync());
+ public bool IsCurrentActiveToken()
+ => IsActive(GetCurrent());
- public Task DeactivateCurrentAsync()
- => DeactivateAsync(GetCurrentAsync());
+ public void DeactivateCurrent()
+ => Deactivate(GetCurrent());
- public Task IsActiveAsync(string token)
- => Task.FromResult(string.IsNullOrWhiteSpace(_cache.Get(GetKey(token))));
+ public bool IsActive(string token)
+ => string.IsNullOrWhiteSpace(_cache.Get(GetKey(token)));
- public Task DeactivateAsync(string token)
+ public void Deactivate(string token)
{
_cache.Set(GetKey(token), "revoked", new MemoryCacheEntryOptions
{
AbsoluteExpirationRelativeToNow = _expires
});
-
- return Task.CompletedTask;
}
- private string GetCurrentAsync()
+ private string GetCurrent()
{
- var authorizationHeader = _httpContextAccessor
- .HttpContext?.Request.Headers["authorization"];
+ var authorizationHeader = _httpContextAccessor.HttpContext?.Request.Headers.Authorization;
if (authorizationHeader is null)
{
@@ -52,7 +43,7 @@ private string GetCurrentAsync()
return authorizationHeader.Value == StringValues.Empty
? string.Empty
- : authorizationHeader.Value.Single().Split(' ').Last();
+ : authorizationHeader.Value.Single()?.Split(' ').Last();
}
private static string GetKey(string token) => $"blacklisted-tokens:{token}";
diff --git a/src/Genocs.Common/Genocs.Common.csproj b/src/Genocs.Common/Genocs.Common.csproj
index 5190a096..2a5a829d 100644
--- a/src/Genocs.Common/Genocs.Common.csproj
+++ b/src/Genocs.Common/Genocs.Common.csproj
@@ -5,14 +5,14 @@
Genocs.Common
Genocs.Common
Genocs.Common
- The Genocs Library - Common components.
+ The Genocs common components.
The common components to build .NET Core projects along with Genocs Library.
true
5.0.0
Nocco Giovanni Emanuele
microservice microservices solid solid-principles genocs
README_NUGET.md
- Aligned to the ecosystem
+ Upgraded to NET9.0
True
latest
diff --git a/src/Genocs.Core.Demo.HelloWorld/Controllers/WeatherForecastController.cs b/src/Genocs.Core.Demo.HelloWorld/Controllers/WeatherForecastController.cs
new file mode 100644
index 00000000..26e7957c
--- /dev/null
+++ b/src/Genocs.Core.Demo.HelloWorld/Controllers/WeatherForecastController.cs
@@ -0,0 +1,31 @@
+using Microsoft.AspNetCore.Mvc;
+
+namespace Genocs.Core.Demo.HelloWorld.Controllers;
+[ApiController]
+[Route("[controller]")]
+public class WeatherForecastController : ControllerBase
+{
+ private static readonly string[] Summaries = new[]
+ {
+ "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
+ };
+
+ private readonly ILogger _logger;
+
+ public WeatherForecastController(ILogger logger)
+ {
+ _logger = logger;
+ }
+
+ [HttpGet(Name = "GetWeatherForecast")]
+ public IEnumerable Get()
+ {
+ return Enumerable.Range(1, 5).Select(index => new WeatherForecast
+ {
+ Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
+ TemperatureC = Random.Shared.Next(-20, 55),
+ Summary = Summaries[Random.Shared.Next(Summaries.Length)]
+ })
+ .ToArray();
+ }
+}
diff --git a/src/Genocs.Core.Demo.HelloWorld/Genocs.Core.Demo.HelloWorld.csproj b/src/Genocs.Core.Demo.HelloWorld/Genocs.Core.Demo.HelloWorld.csproj
new file mode 100644
index 00000000..85556587
--- /dev/null
+++ b/src/Genocs.Core.Demo.HelloWorld/Genocs.Core.Demo.HelloWorld.csproj
@@ -0,0 +1,26 @@
+
+
+
+ net9.0
+ enable
+ enable
+ genocs
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Genocs.Core.Demo.HelloWorld/Genocs.Core.Demo.HelloWorld.http b/src/Genocs.Core.Demo.HelloWorld/Genocs.Core.Demo.HelloWorld.http
new file mode 100644
index 00000000..ed67dc51
--- /dev/null
+++ b/src/Genocs.Core.Demo.HelloWorld/Genocs.Core.Demo.HelloWorld.http
@@ -0,0 +1,6 @@
+@Genocs.Core.Demo.HelloWorld_HostAddress = http://localhost:5267
+
+GET {{Genocs.Core.Demo.HelloWorld_HostAddress}}/weatherforecast/
+Accept: application/json
+
+###
diff --git a/src/Genocs.Core.Demo.HelloWorld/Program.cs b/src/Genocs.Core.Demo.HelloWorld/Program.cs
new file mode 100644
index 00000000..db0cb88d
--- /dev/null
+++ b/src/Genocs.Core.Demo.HelloWorld/Program.cs
@@ -0,0 +1,87 @@
+using System.Security.Claims;
+using Genocs.Auth;
+using Genocs.Core.Builders;
+using Genocs.GnxOpenTelemetry;
+using Genocs.Logging;
+using Microsoft.AspNetCore.Authorization;
+using Microsoft.AspNetCore.Authorization.Infrastructure;
+
+StaticLogger.EnsureInitialized();
+
+var builder = WebApplication.CreateBuilder(args);
+
+builder.Host
+ .UseLogging();
+
+builder.AddGenocs()
+ .AddOpenTelemetry()
+ .AddJwt("simmetric_jwt")
+ .Build();
+
+// Add services to the container.
+builder.Services.AddControllers();
+
+// Learn more about configuring OpenAPI at https://aka.ms/aspnet/openapi
+builder.Services.AddOpenApi();
+
+builder.Services.AddCors(options =>
+{
+ options.AddDefaultPolicy(builder =>
+ {
+ builder.AllowAnyOrigin()
+ .AllowAnyMethod()
+ .AllowAnyHeader();
+ });
+});
+
+// Override the default authorization policy
+builder.Services.AddAuthorizationBuilder()
+ .AddPolicy("Reader", builder => builder.RequireAssertion(context => context.User.HasClaim(ClaimTypes.Role, "user")))
+ .AddPolicy("Reader2", builder => builder.RequireClaim(ClaimTypes.Role, "user"))
+ .AddPolicy("Reader3", builder => builder.RequireRole(["user"]))
+ .AddPolicy("Reader4", builder => builder.AddRequirements(new AssertionRequirement(context => context.User.IsInRole("user"))))
+ ;
+
+//builder.Services.AddAuthorizationBuilder()
+// .SetFallbackPolicy(new AuthorizationPolicyBuilder()
+// .RequireAuthenticatedUser()
+// .Build())
+// .AddPolicy(Policies.UserOnly, policy => policy.RequireAssertion(context
+// => context.User.HasClaim(ClaimTypes.Role, Roles.User)))
+// .AddPolicy(Policies.AdminOnly, policy => policy.RequireAssertion(context
+// => context.User.HasClaim(ClaimTypes.Role, Roles.Admin)))
+// .AddPolicy(Policies.UserOrAdmin, policy => policy.RequireAssertion(context
+// => context.User.HasClaim(ClaimTypes.Role, Roles.User)
+// || context.User.HasClaim(ClaimTypes.Role, Roles.Admin)));
+
+
+
+var app = builder.Build();
+
+// Configure the HTTP request pipeline.
+if (app.Environment.IsDevelopment())
+{
+ app.MapOpenApi();
+}
+
+app.UseHttpsRedirection();
+
+app.UseCors();
+app.UseRouting();
+app.UseAuthentication();
+app.UseAuthorization();
+
+// Used to validate the access token
+// In RealTime
+app.UseAccessTokenValidator();
+
+app.MapControllers();
+
+// Minimal API with authorization
+app.MapGet("/", () => "ok").RequireAuthorization();
+
+// Minimal API with authorization policy
+app.MapGet("/onlyreader", () => "ok").RequireAuthorization("Reader");
+app.MapGet("/onlyreader2", () => "ok").RequireAuthorization("Reader2");
+
+app.Run();
diff --git a/src/Genocs.Core.Demo.HelloWorld/Properties/launchSettings.json b/src/Genocs.Core.Demo.HelloWorld/Properties/launchSettings.json
new file mode 100644
index 00000000..889b3f53
--- /dev/null
+++ b/src/Genocs.Core.Demo.HelloWorld/Properties/launchSettings.json
@@ -0,0 +1,23 @@
+{
+ "$schema": "https://json.schemastore.org/launchsettings.json",
+ "profiles": {
+ "http": {
+ "commandName": "Project",
+ "dotnetRunMessages": true,
+ "launchBrowser": false,
+ "applicationUrl": "http://localhost:5267",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "https": {
+ "commandName": "Project",
+ "dotnetRunMessages": true,
+ "launchBrowser": false,
+ "applicationUrl": "https://localhost:7062;http://localhost:5267",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ }
+ }
+}
diff --git a/src/Genocs.Core.Demo.HelloWorld/WeatherForecast.cs b/src/Genocs.Core.Demo.HelloWorld/WeatherForecast.cs
new file mode 100644
index 00000000..48f14e81
--- /dev/null
+++ b/src/Genocs.Core.Demo.HelloWorld/WeatherForecast.cs
@@ -0,0 +1,12 @@
+namespace Genocs.Core.Demo.HelloWorld;
+
+public class WeatherForecast
+{
+ public DateOnly Date { get; set; }
+
+ public int TemperatureC { get; set; }
+
+ public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
+
+ public string? Summary { get; set; }
+}
diff --git a/src/Genocs.Core.Demo.HelloWorld/appsettings.Development.json b/src/Genocs.Core.Demo.HelloWorld/appsettings.Development.json
new file mode 100644
index 00000000..43b43db8
--- /dev/null
+++ b/src/Genocs.Core.Demo.HelloWorld/appsettings.Development.json
@@ -0,0 +1,8 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Debug",
+ "Microsoft.AspNetCore": "Debug"
+ }
+ }
+}
diff --git a/src/Genocs.Core.Demo.HelloWorld/appsettings.json b/src/Genocs.Core.Demo.HelloWorld/appsettings.json
new file mode 100644
index 00000000..2c245ee9
--- /dev/null
+++ b/src/Genocs.Core.Demo.HelloWorld/appsettings.json
@@ -0,0 +1,90 @@
+{
+ "app": {
+ "name": "Demo HelloWorld",
+ "service": "api-helloworld",
+ "instance": "01",
+ "version": "v1.0",
+ "displayBanner": true,
+ "displayVersion": true
+ },
+ "logger": {
+ "level": "debug",
+ "excludePaths": [
+ "/",
+ "/healthz",
+ "/alive",
+ "/metrics"
+ ],
+ "excludeProperties": [
+ "api_key",
+ "access_key",
+ "ApiKey",
+ "ApiSecret",
+ "ClientId",
+ "ClientSecret",
+ "ConnectionString",
+ "Password",
+ "Email",
+ "Login",
+ "Secret",
+ "Token"
+ ],
+ "console": {
+ "enabled": true
+ },
+ "file": {
+ "enabled": true,
+ "path": "logs/logs.txt",
+ "interval": "day"
+ },
+ "tags": {}
+ },
+ "openTelemetry": {
+ "enabled": true,
+ "exporter": {
+ "enabled": true,
+ "otlpEndpoint": "http://localhost:4318",
+ "protocol": "Grpc",
+ "processorType": "Batch",
+ "maxQueueSize": 2048,
+ "scheduledDelayMilliseconds": 5000,
+ "exporterTimeoutMilliseconds": 30000,
+ "maxExportBatchSize": 512
+ },
+ "console": {
+ "enabled": true,
+ "enableTracing": true,
+ "enableMetrics": true,
+ "enableLogging": true
+ },
+ "azure": {
+ "enabled": true,
+ "enableTracing": true,
+ "enableMetrics": true,
+ "enableLogging": true,
+ "connectionString": "InstrumentationKey=1496274b-bda7-4ac6-88ab-9f73b4d3c7b8;IngestionEndpoint=https://italynorth-0.in.applicationinsights.azure.com/;LiveEndpoint=https://italynorth.livediagnostics.monitor.azure.com/;ApplicationId=c417f66d-3611-48a2-80fe-5a6d302bed4f"
+ }
+ },
+ "Logging": {
+ "LogLevel": {
+ "Default": "Debug",
+ "Microsoft.AspNetCore": "Debug"
+ }
+ },
+ "AllowedHosts": "*",
+ "simmetric_jwt": {
+ "enabled": true,
+ "requireHttpsMetadata": false,
+ "issuer": "genocs-identity-service",
+ "issuerSigningKey": "THIS IS USED TO SIGN AND VERIFY JWT TOKENS, REPLACE IT WITH YOUR OWN SECRET, IT CAN BE ANY STRING",
+ "validateIssuer": true,
+ "validIssuer": "genocs-identity-service",
+ "validateAudience": false,
+ "validateLifetime": false,
+ "requireExpirationTime": false,
+ "requireSignedTokens": false,
+ "validateIssuerSigningKey": false,
+ "expiry": "01:00:00",
+ "saveToken": true
+ }
+}
diff --git a/src/Genocs.Core.Demo.Infrastructure/Genocs.Core.Demo.Infrastructure.csproj b/src/Genocs.Core.Demo.Infrastructure/Genocs.Core.Demo.Infrastructure.csproj
index 657c487a..833ce3ca 100644
--- a/src/Genocs.Core.Demo.Infrastructure/Genocs.Core.Demo.Infrastructure.csproj
+++ b/src/Genocs.Core.Demo.Infrastructure/Genocs.Core.Demo.Infrastructure.csproj
@@ -6,4 +6,9 @@
false
+
+
+
+
+
diff --git a/src/Genocs.Core.Demo.Infrastructure/SecurityAuthentication/TokenProvider.cs b/src/Genocs.Core.Demo.Infrastructure/SecurityAuthentication/TokenProvider.cs
new file mode 100644
index 00000000..11bee712
--- /dev/null
+++ b/src/Genocs.Core.Demo.Infrastructure/SecurityAuthentication/TokenProvider.cs
@@ -0,0 +1,63 @@
+using System.IdentityModel.Tokens.Jwt;
+using System.Security.Claims;
+using System.Text;
+using Microsoft.Extensions.Configuration;
+using Microsoft.IdentityModel.JsonWebTokens;
+using Microsoft.IdentityModel.Tokens;
+
+namespace Genocs.Core.Demo.Infrastructure.SecurityAuthentication;
+
+public sealed class TokenProvider(IConfiguration configuration)
+{
+ public string Issuer => configuration["JwtSettings:Issuer"];
+ public string Audience => configuration["JwtSettings:Audience"];
+ public string Key => configuration["JwtSettings:Key"];
+ public int Expiration => int.Parse(configuration["JwtSettings:Expiration"]);
+
+ ///
+ /// This method creates a token using the JwtSecurityTokenHandler class.
+ ///
+ ///
+ public string CreateToken()
+ {
+ var tokenHandler = new JwtSecurityTokenHandler();
+ byte[] key = Encoding.ASCII.GetBytes(Key);
+
+ var tokenDescriptor = new SecurityTokenDescriptor
+ {
+ Subject = new ClaimsIdentity(new Claim[]
+ {
+ new Claim(ClaimTypes.Name, "username"),
+ new Claim(ClaimTypes.Role, "role")
+ }),
+ Expires = DateTime.UtcNow.AddMinutes(Expiration),
+ SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
+ };
+
+ var token = tokenHandler.CreateToken(tokenDescriptor);
+ return tokenHandler.WriteToken(token);
+ }
+
+ ///
+ /// This method creates a token using the JsonWebTokenHandler class.
+ ///
+ ///
+ public string CreateTokenWithJsonWebTokenHandler()
+ {
+ var tokenHandler = new JsonWebTokenHandler();
+ byte[] key = Encoding.ASCII.GetBytes(Key);
+ var tokenDescriptor = new SecurityTokenDescriptor
+ {
+ Subject = new ClaimsIdentity(new Claim[]
+ {
+ new Claim(ClaimTypes.Name, "username"),
+ new Claim(ClaimTypes.Role, "role")
+ }),
+ Expires = DateTime.UtcNow.AddMinutes(Expiration),
+ SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
+ };
+
+ string token = tokenHandler.CreateToken(tokenDescriptor);
+ return token;
+ }
+}
diff --git a/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj b/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj
index 85e7e8b6..4352b420 100644
--- a/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj
+++ b/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj
@@ -32,9 +32,8 @@
-
+
-
@@ -43,4 +42,8 @@
+
+
+
+
diff --git a/src/Genocs.Core.Demo.WebApi/Program.cs b/src/Genocs.Core.Demo.WebApi/Program.cs
index 33d6eedd..8468cfd6 100644
--- a/src/Genocs.Core.Demo.WebApi/Program.cs
+++ b/src/Genocs.Core.Demo.WebApi/Program.cs
@@ -20,9 +20,9 @@
.UseAzureKeyVault()
.UseLogging();
-builder.AddGenocs()
+builder
+ .AddGenocs()
.AddJwt()
-// .AddOpenIdJwt()
.AddOpenTelemetry()
.AddMongoFast()
.RegisterMongoRepositories(Assembly.GetExecutingAssembly())
@@ -60,6 +60,8 @@
var app = builder.Build();
+app.UseGenocs();
+
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
diff --git a/src/Genocs.Core.Demo.Worker/Genocs.Core.Demo.Worker.csproj b/src/Genocs.Core.Demo.Worker/Genocs.Core.Demo.Worker.csproj
index f9b2dcbc..dcc3acc6 100644
--- a/src/Genocs.Core.Demo.Worker/Genocs.Core.Demo.Worker.csproj
+++ b/src/Genocs.Core.Demo.Worker/Genocs.Core.Demo.Worker.csproj
@@ -4,7 +4,7 @@
net9.0
false
false
- _Genocs
+ Genocs
@@ -21,9 +21,8 @@
-
+
-
diff --git a/src/Genocs.Core/Builders/Extensions.cs b/src/Genocs.Core/Builders/Extensions.cs
index 4c82f9eb..ca6262c1 100644
--- a/src/Genocs.Core/Builders/Extensions.cs
+++ b/src/Genocs.Core/Builders/Extensions.cs
@@ -87,7 +87,7 @@ public static TModel GetOptions(this IGenocsBuilder builder, string sect
}
///
- /// Map default endpoints to setup health checks.
+ /// Map default endpoints to setup root endpoint and health checks.
///
/// The web Application.
/// The WebApplication to be used for chain.
@@ -110,7 +110,7 @@ public static IApplicationBuilder MapDefaultEndpoints(this IApplicationBuilder a
});
// All health checks must pass for app to be considered ready to accept traffic after starting
- endpoints.MapHealthChecks("/health");
+ endpoints.MapHealthChecks("/healthz");
// Only health checks tagged with the "live" tag must pass for app to be considered alive
endpoints.MapHealthChecks("/alive", new HealthCheckOptions
@@ -136,15 +136,6 @@ public static WebApplication MapDefaultEndpoints(this WebApplication app)
return app;
}
- // All health checks must pass for app to be considered ready to accept traffic after starting
- app.MapHealthChecks("/healthz");
-
- // Only health checks tagged with the "live" tag must pass for app to be considered alive
- app.MapHealthChecks("/alive", new HealthCheckOptions
- {
- Predicate = r => r.Tags.Contains("live")
- });
-
app.MapGet("/", async context =>
{
// Get the Entry Assembly Name and Version
@@ -154,7 +145,17 @@ public static WebApplication MapDefaultEndpoints(this WebApplication app)
string message = $"Service {serviceVersion ?? assemblyVersion} is running";
await context.Response.WriteAsync(context.RequestServices.GetService()?.Name ?? message);
- });
+ }).AllowAnonymous();
+
+ // All health checks must pass for app to be considered ready to accept traffic after starting
+ app.MapHealthChecks("/healthz").AllowAnonymous();
+
+ // Only health checks tagged with the "live" tag must pass for app to be considered alive
+ app.MapHealthChecks("/alive", new HealthCheckOptions
+ {
+ Predicate = r => r.Tags.Contains("live")
+ }).AllowAnonymous();
+
return app;
}
@@ -177,11 +178,27 @@ private static void Setup(IGenocsBuilder builder)
Console.ForegroundColor = current;
// Add the health checks
+ // Add health checks to the application
+ // Since the health checks is item potent, we can add it multiple times
+ // Add a default liveness check to ensure app is responsive
builder.Services
- .AddHealthChecks();
-
- // .AddCheck("self", () => HealthCheckResult.Healthy(), ["live"]); // Add a default liveness check to ensure app is responsive
-
+ .AddHealthChecks()
+ .AddCheck("self", () => HealthCheckResult.Healthy(), ["live"]);
+
+ /*
+ * This is an example of how to add a MongoDB health check.
+ * Please note that you need to install the NuGet package AspNetCore.HealthChecks.MongoDb
+ *
+ .AddMongoDb(
+ builder.Configuration.GetSection("DBSettings:HealthConnectionString").Value!,
+ builder.Configuration.GetSection("DBSettings:Database").Value!,
+ name: "mongodb",
+ timeout: TimeSpan.FromSeconds(10),
+ tags: ["live"]);
+
+ */
+
+ // Set the memory cache as default.
builder.Services.AddMemoryCache();
builder.Services.AddSingleton();
diff --git a/src/Genocs.Core/Builders/GenocsBuilder.cs b/src/Genocs.Core/Builders/GenocsBuilder.cs
index 8be14b99..cd9e2bac 100644
--- a/src/Genocs.Core/Builders/GenocsBuilder.cs
+++ b/src/Genocs.Core/Builders/GenocsBuilder.cs
@@ -21,14 +21,22 @@ public sealed class GenocsBuilder : IGenocsBuilder
///
public IConfiguration? Configuration { get; private set; }
+ ///
+ /// The web application builder.
+ ///
public WebApplicationBuilder? WebApplicationBuilder { get; private set; }
+ ///
+ /// The Genocs builder constructor.
+ ///
+ /// The service collection.
+ /// The IConfiguration.
private GenocsBuilder(IServiceCollection services, IConfiguration? configuration)
{
_services = services;
Configuration = configuration;
- _buildActions = new List>();
+ _buildActions = [];
_services.AddSingleton(new StartupInitializer());
}
@@ -38,7 +46,7 @@ private GenocsBuilder(WebApplicationBuilder builder)
Configuration = builder.Configuration;
_services = builder.Services;
- _buildActions = new List>();
+ _buildActions = [];
_services.AddSingleton(new StartupInitializer());
}
@@ -70,6 +78,13 @@ public void AddInitializer()
startupInitializer.AddInitializer(initializer);
});
+ ///
+ /// Build the Genocs application.
+ ///
+ ///
+ /// Remember to call the Build on the application builder.
+ ///
+ /// The Service Provider to be used for chaining.
public IServiceProvider Build()
{
var serviceProvider = _services.BuildServiceProvider();
diff --git a/src/Genocs.Core/Genocs.Core.csproj b/src/Genocs.Core/Genocs.Core.csproj
index 3d789e37..7beff245 100644
--- a/src/Genocs.Core/Genocs.Core.csproj
+++ b/src/Genocs.Core/Genocs.Core.csproj
@@ -12,7 +12,7 @@
Nocco Giovanni Emanuele
microservice microservices solid solid-principles genocs
README_NUGET.md
- Updated to NET8
+ Upgraded to NET9.0
True
latest
diff --git a/src/Genocs.Discovery.Consul/Genocs.Discovery.Consul.csproj b/src/Genocs.Discovery.Consul/Genocs.Discovery.Consul.csproj
index 1b289f3d..92830b94 100644
--- a/src/Genocs.Discovery.Consul/Genocs.Discovery.Consul.csproj
+++ b/src/Genocs.Discovery.Consul/Genocs.Discovery.Consul.csproj
@@ -5,14 +5,14 @@
Genocs.Discovery.Consul
Genocs.Discovery.Consul
Genocs.Discovery.Consul
- The service discovery by Consul library useful to build .NET Core projects.
- The service discovery by Consul library useful to build .NET Core projects.
+ The service discovery library powered by Consul.
+ The service discovery library powered by Consul.
true
5.0.0
Nocco Giovanni Emanuele
- microservice microservices solid solid-principles genocs service-discovery
+ service discovery service-discovery genocs microservice microservices solid solid-principles
README_NUGET.md
- Aligned to the ecosystem
+ Upgraded to NET9.0
True
latest
diff --git a/src/Genocs.HTTP.RestEase/Genocs.HTTP.RestEase.csproj b/src/Genocs.HTTP.RestEase/Genocs.HTTP.RestEase.csproj
index fbd22554..b6e9c27e 100644
--- a/src/Genocs.HTTP.RestEase/Genocs.HTTP.RestEase.csproj
+++ b/src/Genocs.HTTP.RestEase/Genocs.HTTP.RestEase.csproj
@@ -5,14 +5,14 @@
Genocs.HTTP.RestEase
Genocs.HTTP.RestEase
Genocs.HTTP.RestEase
- The http support library useful to build .NET Core projects.
- The http support library useful to build .NET Core projects.
+ The http support library.
+ The http support library.
true
5.0.0
Nocco Giovanni Emanuele
- aggregate architecture boilerplate ddd ddd-architecture design-patterns domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles
+ aggregate dotnet dotnetcore dotnet-core microservice microservices solid solid-principles
README_NUGET.md
- Aligned to the ecosystem
+ Upgraded to NET9.0
True
latest
@@ -32,7 +32,6 @@
-
diff --git a/src/Genocs.HTTP/Genocs.HTTP.csproj b/src/Genocs.HTTP/Genocs.HTTP.csproj
index bba35e2c..c43c914e 100644
--- a/src/Genocs.HTTP/Genocs.HTTP.csproj
+++ b/src/Genocs.HTTP/Genocs.HTTP.csproj
@@ -5,14 +5,14 @@
Genocs.HTTP
Genocs.HTTP
Genocs.HTTP
- The http support library useful to build .NET Core projects.
- The http support library useful to build .NET Core projects.
+ The http client library.
+ The http client library.
true
5.0.0
Nocco Giovanni Emanuele
- microservice microservices solid solid-principles genocs http-client
+ http http-client genocs microservice microservices solid solid-principles
README_NUGET.md
- Aligned to the ecosystem
+ Upgraded to NET9.0
True
latest
diff --git a/src/Genocs.HTTP/GenocsHttpClient.cs b/src/Genocs.HTTP/GenocsHttpClient.cs
index 7ccefdad..46fbc08e 100644
--- a/src/Genocs.HTTP/GenocsHttpClient.cs
+++ b/src/Genocs.HTTP/GenocsHttpClient.cs
@@ -45,7 +45,7 @@ public GenocsHttpClient(
public virtual Task GetAsync(string uri)
=> SendAsync(uri, Method.Get);
- public virtual Task GetAsync(string uri, IHttpClientSerializer? serializer = null)
+ public virtual Task GetAsync(string uri, IHttpClientSerializer? serializer = null)
=> SendAsync(uri, Method.Get, serializer: serializer);
public Task> GetResultAsync(string uri, IHttpClientSerializer? serializer = null)
@@ -57,10 +57,10 @@ public virtual Task PostAsync(string uri, object? data = nu
public Task PostAsync(string uri, HttpContent content)
=> SendAsync(uri, Method.Post, content);
- public virtual Task PostAsync(string uri, object? data = null, IHttpClientSerializer? serializer = null)
+ public virtual Task PostAsync(string uri, object? data = null, IHttpClientSerializer? serializer = null)
=> SendAsync(uri, Method.Post, GetJsonPayload(data, serializer));
- public Task PostAsync(string uri, HttpContent content, IHttpClientSerializer? serializer = null)
+ public Task PostAsync(string uri, HttpContent content, IHttpClientSerializer? serializer = null)
=> SendAsync(uri, Method.Post, content, serializer);
public Task> PostResultAsync(string uri, object? data = null, IHttpClientSerializer? serializer = null)
@@ -75,10 +75,10 @@ public virtual Task PutAsync(string uri, object? data = nul
public Task PutAsync(string uri, HttpContent content)
=> SendAsync(uri, Method.Put, content);
- public virtual Task PutAsync(string uri, object? data = null, IHttpClientSerializer? serializer = null)
+ public virtual Task PutAsync(string uri, object? data = null, IHttpClientSerializer? serializer = null)
=> SendAsync(uri, Method.Put, GetJsonPayload(data, serializer), serializer);
- public Task PutAsync(string uri, HttpContent content, IHttpClientSerializer? serializer = null)
+ public Task PutAsync(string uri, HttpContent content, IHttpClientSerializer? serializer = null)
=> SendAsync(uri, Method.Put, content, serializer);
public Task> PutResultAsync(string uri, object? data = null, IHttpClientSerializer? serializer = null)
@@ -93,10 +93,10 @@ public Task PatchAsync(string uri, object? data = null, IHt
public Task PatchAsync(string uri, HttpContent content)
=> SendAsync(uri, Method.Patch, content);
- public Task PatchAsync(string uri, object? data = null, IHttpClientSerializer? serializer = null)
+ public Task PatchAsync(string uri, object? data = null, IHttpClientSerializer? serializer = null)
=> SendAsync(uri, Method.Patch, GetJsonPayload(data, serializer));
- public Task PatchAsync(string uri, HttpContent content, IHttpClientSerializer? serializer = null)
+ public Task PatchAsync(string uri, HttpContent content, IHttpClientSerializer? serializer = null)
=> SendAsync(uri, Method.Patch, content, serializer);
public Task> PatchResultAsync(string uri, object? data = null, IHttpClientSerializer? serializer = null)
@@ -108,7 +108,7 @@ public Task> PatchResultAsync(string uri, HttpContent content,
public virtual Task DeleteAsync(string uri)
=> SendAsync(uri, Method.Delete);
- public Task DeleteAsync(string uri, IHttpClientSerializer? serializer = null)
+ public Task DeleteAsync(string uri, IHttpClientSerializer? serializer = null)
=> SendAsync(uri, Method.Delete, serializer: serializer);
public Task> DeleteResultAsync(string uri, IHttpClientSerializer? serializer = null)
@@ -119,19 +119,22 @@ public Task SendAsync(HttpRequestMessage request)
.WaitAndRetryAsync(_settings.Retries, r => TimeSpan.FromSeconds(Math.Pow(2, r)))
.ExecuteAsync(() => _client.SendAsync(request));
- public Task SendAsync(HttpRequestMessage request, IHttpClientSerializer? serializer = null)
+ public Task SendAsync(HttpRequestMessage request, IHttpClientSerializer? serializer = null)
=> Policy.Handle()
.WaitAndRetryAsync(_settings.Retries, r => TimeSpan.FromSeconds(Math.Pow(2, r)))
.ExecuteAsync(async () =>
{
+ // Send the HTTP request
var response = await _client.SendAsync(request);
+
+ // Check if the response indicates a successful status code
if (!response.IsSuccessStatusCode)
{
- return default!;
+ // If not successful, throw an exception so the retry will come.
+ throw new HttpRequestException($"The HTTP request failed with status code {response.StatusCode}.");
}
var stream = await response.Content.ReadAsStreamAsync();
-
return await DeserializeJsonFromStream(stream, serializer);
});
@@ -173,7 +176,7 @@ public void SetHeaders(IDictionary headers)
public void SetHeaders(Action headers)
=> headers?.Invoke(_client.DefaultRequestHeaders);
- protected virtual async Task SendAsync(string uri, Method method, HttpContent? content = null, IHttpClientSerializer? serializer = null)
+ protected virtual async Task SendAsync(string uri, Method method, HttpContent? content = null, IHttpClientSerializer? serializer = null)
{
var response = await SendAsync(uri, method, content);
if (!response.IsSuccessStatusCode)
@@ -186,11 +189,7 @@ protected virtual async Task SendAsync(string uri, Method method, HttpCont
return await DeserializeJsonFromStream(stream, serializer);
}
- protected virtual async Task> SendResultAsync(
- string uri,
- Method method,
- HttpContent? content = null,
- IHttpClientSerializer? serializer = null)
+ protected virtual async Task> SendResultAsync(string uri, Method method, HttpContent? content = null, IHttpClientSerializer? serializer = null)
{
var response = await SendAsync(uri, method, content);
if (!response.IsSuccessStatusCode)
@@ -207,11 +206,18 @@ protected virtual async Task> SendResultAsync(
protected virtual Task SendAsync(string uri, Method method, HttpContent? content = null)
=> Policy.Handle()
.WaitAndRetryAsync(_settings.Retries, r => TimeSpan.FromSeconds(Math.Pow(2, r)))
- .ExecuteAsync(() =>
+ .ExecuteAsync(async () =>
{
string requestUri = uri.StartsWith("http") ? uri : $"http://{uri}";
- return GetResponseAsync(requestUri, method, content);
+ var result = await GetResponseAsync(requestUri, method, content) ?? throw new HttpRequestException("The HTTP request failed.");
+
+ if (!result.IsSuccessStatusCode)
+ {
+ throw new Exception($"The HTTP request failed with status code {result.StatusCode}.");
+ }
+
+ return result;
});
protected virtual Task GetResponseAsync(string uri, Method method, HttpContent? content = null)
diff --git a/src/Genocs.HTTP/GenocsHttpLoggingFilter.cs b/src/Genocs.HTTP/GenocsHttpLoggingFilter.cs
index 8ba7d583..dc20fb95 100644
--- a/src/Genocs.HTTP/GenocsHttpLoggingFilter.cs
+++ b/src/Genocs.HTTP/GenocsHttpLoggingFilter.cs
@@ -5,29 +5,21 @@
namespace Genocs.HTTP;
// Credits goes to https://www.stevejgordon.co.uk/httpclientfactory-asp-net-core-logging
-internal sealed class GenocsHttpLoggingFilter : IHttpMessageHandlerBuilderFilter
+internal sealed class GenocsHttpLoggingFilter(ILoggerFactory loggerFactory, HttpClientOptions options) : IHttpMessageHandlerBuilderFilter
{
- private readonly ILoggerFactory _loggerFactory;
- private readonly HttpClientOptions _options;
-
- public GenocsHttpLoggingFilter(ILoggerFactory loggerFactory, HttpClientOptions options)
- {
- _loggerFactory = loggerFactory ?? throw new ArgumentNullException(nameof(loggerFactory));
- _options = options;
- }
+ private readonly ILoggerFactory _loggerFactory = loggerFactory ?? throw new ArgumentNullException(nameof(loggerFactory));
+ private readonly HttpClientOptions _options = options;
public Action Configure(Action next)
{
- if (next is null)
- {
- throw new ArgumentNullException(nameof(next));
- }
+ return next is null
+ ? throw new ArgumentNullException(nameof(next))
+ : (builder =>
+ {
+ next(builder);
- return builder =>
- {
- next(builder);
- var logger = _loggerFactory.CreateLogger($"System.Net.Http.HttpClient.{builder.Name}.LogicalHandler");
- builder.AdditionalHandlers.Insert(0, new GenocsLoggingScopeHttpMessageHandler(logger, _options));
- };
+ var logger = _loggerFactory.CreateLogger($"System.Net.Http.HttpClient.{builder.Name}.LogicalHandler");
+ builder.AdditionalHandlers.Insert(0, new GenocsLoggingScopeHttpMessageHandler(logger, _options));
+ });
}
}
\ No newline at end of file
diff --git a/src/Genocs.HTTP/GenocsLoggingScopeHttpMessageHandler.cs b/src/Genocs.HTTP/GenocsLoggingScopeHttpMessageHandler.cs
index 468ab49d..5b044f60 100644
--- a/src/Genocs.HTTP/GenocsLoggingScopeHttpMessageHandler.cs
+++ b/src/Genocs.HTTP/GenocsLoggingScopeHttpMessageHandler.cs
@@ -14,8 +14,9 @@ public GenocsLoggingScopeHttpMessageHandler(ILogger logger, HttpClientOptions se
{
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
_ = settings ?? throw new ArgumentNullException(nameof(settings));
- _maskedRequestUrlParts =
- new HashSet(settings.RequestMasking?.UrlParts ?? Enumerable.Empty());
+
+ _maskedRequestUrlParts = [.. settings.RequestMasking?.UrlParts ?? []];
+
_maskTemplate = string.IsNullOrWhiteSpace(settings.RequestMasking?.MaskTemplate)
? "*****"
: settings.RequestMasking.MaskTemplate;
@@ -23,10 +24,7 @@ public GenocsLoggingScopeHttpMessageHandler(ILogger logger, HttpClientOptions se
protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
- if (request is null)
- {
- throw new ArgumentNullException(nameof(request));
- }
+ ArgumentNullException.ThrowIfNull(request);
using (Log.BeginRequestPipelineScope(_logger, request, _maskedRequestUrlParts, _maskTemplate))
{
diff --git a/src/Genocs.HTTP/ICorrelationContextFactory.cs b/src/Genocs.HTTP/ICorrelationContextFactory.cs
index 1e042c08..378f2f11 100644
--- a/src/Genocs.HTTP/ICorrelationContextFactory.cs
+++ b/src/Genocs.HTTP/ICorrelationContextFactory.cs
@@ -1,6 +1,13 @@
namespace Genocs.HTTP;
+///
+/// The CorrelationContext Factory interface.
+///
public interface ICorrelationContextFactory
{
+ ///
+ /// Create a correlationId.
+ ///
+ /// The correlationId just created.
string Create();
}
\ No newline at end of file
diff --git a/src/Genocs.HTTP/ICorrelationIdFactory.cs b/src/Genocs.HTTP/ICorrelationIdFactory.cs
index 099e8075..d67042e3 100644
--- a/src/Genocs.HTTP/ICorrelationIdFactory.cs
+++ b/src/Genocs.HTTP/ICorrelationIdFactory.cs
@@ -1,7 +1,7 @@
namespace Genocs.HTTP;
///
-/// Generic CorrelationId Factory interface.
+/// The CorrelationId Factory interface.
///
public interface ICorrelationIdFactory
{
diff --git a/src/Genocs.HTTP/IHttpClient.cs b/src/Genocs.HTTP/IHttpClient.cs
index 568bae1e..ebc2be53 100644
--- a/src/Genocs.HTTP/IHttpClient.cs
+++ b/src/Genocs.HTTP/IHttpClient.cs
@@ -8,39 +8,47 @@ namespace Genocs.HTTP;
public interface IHttpClient
{
Task GetAsync(string uri);
- Task GetAsync(string uri, IHttpClientSerializer? serializer = null);
+ Task GetAsync(string uri, IHttpClientSerializer? serializer = null);
Task> GetResultAsync(string uri, IHttpClientSerializer? serializer = null);
Task PostAsync(string uri, object? data = null, IHttpClientSerializer? serializer = null);
Task PostAsync(string uri, HttpContent content);
- Task PostAsync(string uri, object? data = null, IHttpClientSerializer? serializer = null);
- Task PostAsync(string uri, HttpContent content, IHttpClientSerializer? serializer = null);
+ Task PostAsync(string uri, object? data = null, IHttpClientSerializer? serializer = null);
+ Task PostAsync(string uri, HttpContent content, IHttpClientSerializer? serializer = null);
Task> PostResultAsync(string uri, object? data = null, IHttpClientSerializer? serializer = null);
Task> PostResultAsync(string uri, HttpContent content, IHttpClientSerializer? serializer = null);
Task PutAsync(string uri, object? data = null, IHttpClientSerializer? serializer = null);
Task PutAsync(string uri, HttpContent content);
- Task PutAsync(string uri, object? data = null, IHttpClientSerializer? serializer = null);
- Task PutAsync(string uri, HttpContent content, IHttpClientSerializer? serializer = null);
+ Task PutAsync(string uri, object? data = null, IHttpClientSerializer? serializer = null);
+ Task PutAsync(string uri, HttpContent content, IHttpClientSerializer? serializer = null);
Task> PutResultAsync(string uri, object? data = null, IHttpClientSerializer? serializer = null);
Task> PutResultAsync(string uri, HttpContent content, IHttpClientSerializer? serializer = null);
Task PatchAsync(string uri, object? data = null, IHttpClientSerializer? serializer = null);
Task PatchAsync(string uri, HttpContent content);
- Task PatchAsync(string uri, object? data = null, IHttpClientSerializer? serializer = null);
- Task PatchAsync(string uri, HttpContent content, IHttpClientSerializer? serializer = null);
+ Task PatchAsync(string uri, object? data = null, IHttpClientSerializer? serializer = null);
+ Task PatchAsync(string uri, HttpContent content, IHttpClientSerializer? serializer = null);
Task> PatchResultAsync(string uri, object? data = null, IHttpClientSerializer? serializer = null);
Task> PatchResultAsync(string uri, HttpContent content, IHttpClientSerializer? serializer = null);
Task DeleteAsync(string uri);
- Task DeleteAsync(string uri, IHttpClientSerializer? serializer = null);
+ Task DeleteAsync(string uri, IHttpClientSerializer? serializer = null);
Task> DeleteResultAsync(string uri, IHttpClientSerializer? serializer = null);
Task SendAsync(HttpRequestMessage request);
- Task SendAsync(HttpRequestMessage request, IHttpClientSerializer? serializer = null);
///
/// Send the request and return the result.
///
/// The type to be send.
- ///
- ///
- ///
+ /// The request.
+ /// The serializer.
+ /// The return object.
+ Task SendAsync(HttpRequestMessage request, IHttpClientSerializer? serializer = null);
+
+ ///
+ /// Send the request and return the result.
+ ///
+ /// The type to be send.
+ /// The request.
+ /// The serializer.
+ /// The HttpResult object.
Task> SendResultAsync(HttpRequestMessage request, IHttpClientSerializer? serializer = null);
///
diff --git a/src/Genocs.LoadBalancing.Fabio/Genocs.LoadBalancing.Fabio.csproj b/src/Genocs.LoadBalancing.Fabio/Genocs.LoadBalancing.Fabio.csproj
index 0f2f27a5..1848deb8 100644
--- a/src/Genocs.LoadBalancing.Fabio/Genocs.LoadBalancing.Fabio.csproj
+++ b/src/Genocs.LoadBalancing.Fabio/Genocs.LoadBalancing.Fabio.csproj
@@ -5,14 +5,14 @@
Genocs.LoadBalancing.Fabio
Genocs.LoadBalancing.Fabio
Genocs.LoadBalancing.Fabio
- The load balacer based on Fabio library useful to build .NET Core projects.
- The load balacer based on Fabio library useful to build .NET Core projects.
+ The load balacer based on Fabio.
+ The load balacer based on Fabio.
true
5.0.0
Nocco Giovanni Emanuele
- aggregate architecture boilerplate ddd ddd-architecture design-patterns domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles
+ load balancer load-balancer design-patterns dotnet dotnetcore dotnet-core microservice microservices solid solid-principles
README_NUGET.md
- Aligned to the ecosystem
+ Upgraded to NET9.0
True
latest
diff --git a/src/Genocs.Logging/Configurations/AzureOptions.cs b/src/Genocs.Logging/Configurations/AzureOptions.cs
index 81af694c..47d0d4e5 100644
--- a/src/Genocs.Logging/Configurations/AzureOptions.cs
+++ b/src/Genocs.Logging/Configurations/AzureOptions.cs
@@ -6,7 +6,7 @@ namespace Genocs.Logging.Configurations;
public class AzureOptions
{
///
- /// It define whether the Azure application insights logger and tracing are enabled or not.
+ /// It defines whether the Azure application insights logger and tracing are enabled or not.
///
public bool Enabled { get; set; }
@@ -15,14 +15,13 @@ public class AzureOptions
///
public string? ConnectionString { get; set; }
-
///
- /// It define whether the Azure application insights logger and tracing are enabled or not.
+ /// It defines whether the Azure application insights logger and tracing are enabled or not.
///
public bool EnableTracing { get; set; }
///
- /// It define whether the Azure application insights logger and metrics are enabled or not.
+ /// It defines whether the Azure application insights logger and metrics are enabled or not.
///
public bool EnableMetrics { get; set; }
}
\ No newline at end of file
diff --git a/src/Genocs.Logging/Configurations/ConsoleOptions.cs b/src/Genocs.Logging/Configurations/ConsoleOptions.cs
index 4112f484..383d3634 100644
--- a/src/Genocs.Logging/Configurations/ConsoleOptions.cs
+++ b/src/Genocs.Logging/Configurations/ConsoleOptions.cs
@@ -6,17 +6,22 @@ namespace Genocs.Logging.Configurations;
public class ConsoleOptions
{
///
- /// It define whether the console logger and tracing are enabled or not.
+ /// It defines whether the console logger and tracing are enabled or not.
///
public bool Enabled { get; set; }
///
- /// It define whether the console logger and tracing are enabled or not.
+ /// It defines whether the console logger will use structured logging or not.
+ ///
+ public bool EnableStructured { get; set; }
+
+ ///
+ /// It defines whether the console logger and tracing are enabled or not.
///
public bool EnableTracing { get; set; }
///
- /// It define whether the console logger and metrics are enabled or not.
+ /// It defines whether the console logger and metrics are enabled or not.
///
public bool EnableMetrics { get; set; }
}
\ No newline at end of file
diff --git a/src/Genocs.Logging/Configurations/ElkOptions.cs b/src/Genocs.Logging/Configurations/ElkOptions.cs
index b090e0ed..9bb043ae 100644
--- a/src/Genocs.Logging/Configurations/ElkOptions.cs
+++ b/src/Genocs.Logging/Configurations/ElkOptions.cs
@@ -6,12 +6,12 @@ namespace Genocs.Logging.Configurations;
public class ElkOptions
{
///
- /// It define whether the Elasticsearch logger and tracing are enabled or not.
+ /// It defines whether the Elasticsearch logger and tracing are enabled or not.
///
public bool Enabled { get; set; }
///
- /// It define whether the Elasticsearch authentication is enabled or not.
+ /// It defines whether the Elasticsearch authentication is enabled or not.
///
public bool BasicAuthEnabled { get; set; }
diff --git a/src/Genocs.Logging/Configurations/LoggerOptions.cs b/src/Genocs.Logging/Configurations/LoggerOptions.cs
index 59afbad2..fbe3503a 100644
--- a/src/Genocs.Logging/Configurations/LoggerOptions.cs
+++ b/src/Genocs.Logging/Configurations/LoggerOptions.cs
@@ -17,6 +17,11 @@ public class LoggerOptions
public string? Level { get; set; }
+ ///
+ /// It defines the OpenTelemetry exporter endpoint. In case you are using Serilog with OpenTelemetry.
+ ///
+ public string? OtlpEndpoint { get; set; }
+
///
/// The Console Logging and tracing Settings.
///
diff --git a/src/Genocs.Logging/Configurations/MongoOptions.cs b/src/Genocs.Logging/Configurations/MongoOptions.cs
index c2750e18..e8c5b384 100644
--- a/src/Genocs.Logging/Configurations/MongoOptions.cs
+++ b/src/Genocs.Logging/Configurations/MongoOptions.cs
@@ -6,7 +6,7 @@ namespace Genocs.Logging.Configurations;
public class MongoOptions
{
///
- /// It define whether the MongoDb logger and tracing are enabled or not.
+ /// It defines whether the MongoDb logger and tracing are enabled or not.
///
public bool Enabled { get; set; }
}
\ No newline at end of file
diff --git a/src/Genocs.Logging/Configurations/SeqOptions.cs b/src/Genocs.Logging/Configurations/SeqOptions.cs
index 7e20ccb1..2508d13e 100644
--- a/src/Genocs.Logging/Configurations/SeqOptions.cs
+++ b/src/Genocs.Logging/Configurations/SeqOptions.cs
@@ -6,7 +6,7 @@ namespace Genocs.Logging.Configurations;
public class SeqOptions
{
///
- /// It define whether the Seq logger and tracing are enabled or not.
+ /// It defines whether the Seq logger and tracing are enabled or not.
///
public bool Enabled { get; set; }
diff --git a/src/Genocs.Logging/Extensions.cs b/src/Genocs.Logging/Extensions.cs
index 41997920..34a1b8ee 100644
--- a/src/Genocs.Logging/Extensions.cs
+++ b/src/Genocs.Logging/Extensions.cs
@@ -9,8 +9,11 @@
using Microsoft.Extensions.Hosting;
using Serilog;
using Serilog.Core;
+using Serilog.Enrichers.Span;
using Serilog.Events;
+using Serilog.Exceptions;
using Serilog.Filters;
+using Serilog.Formatting.Compact;
using Serilog.Sinks.Elasticsearch;
using Serilog.Sinks.Grafana.Loki;
@@ -28,23 +31,23 @@ public static IHostBuilder UseLogging(
=> hostBuilder
.ConfigureServices(services => services.AddSingleton())
.UseSerilog((context, loggerConfiguration) =>
- {
- if (string.IsNullOrWhiteSpace(loggerSectionName))
{
- loggerSectionName = LoggerOptions.Position;
- }
+ if (string.IsNullOrWhiteSpace(loggerSectionName))
+ {
+ loggerSectionName = LoggerOptions.Position;
+ }
- if (string.IsNullOrWhiteSpace(appSectionName))
- {
- appSectionName = AppOptions.Position;
- }
+ if (string.IsNullOrWhiteSpace(appSectionName))
+ {
+ appSectionName = AppOptions.Position;
+ }
- var loggerOptions = context.Configuration.GetOptions(loggerSectionName);
- var appOptions = context.Configuration.GetOptions(appSectionName);
+ var loggerOptions = context.Configuration.GetOptions(loggerSectionName);
+ var appOptions = context.Configuration.GetOptions(appSectionName);
- MapOptions(loggerOptions, appOptions, loggerConfiguration, context.HostingEnvironment.EnvironmentName);
- configure?.Invoke(context, loggerConfiguration);
- });
+ MapOptions(loggerOptions, appOptions, loggerConfiguration, context.HostingEnvironment.EnvironmentName);
+ configure?.Invoke(context, loggerConfiguration);
+ });
public static IEndpointConventionBuilder MapLogLevelHandler(
this IEndpointRouteBuilder builder,
@@ -64,7 +67,12 @@ private static void MapOptions(
.Enrich.WithProperty("Environment", environmentName)
.Enrich.WithProperty("Application", appOptions.Service)
.Enrich.WithProperty("Instance", appOptions.Instance)
- .Enrich.WithProperty("Version", appOptions.Version);
+ .Enrich.WithProperty("Version", appOptions.Version)
+ .Enrich.WithExceptionDetails()
+ .Enrich.WithMachineName()
+ .Enrich.WithProcessId()
+ .Enrich.WithThreadId()
+ .Enrich.WithSpan();
foreach (var (key, value) in loggerOptions.Tags ?? new Dictionary())
{
@@ -95,10 +103,26 @@ private static void Configure(LoggerConfiguration loggerConfiguration, LoggerOpt
var lokiOptions = options.Loki ?? new LokiOptions();
var azureOptions = options.Azure ?? new AzureOptions();
+ // OpenTelemetry setup
+ if (!string.IsNullOrWhiteSpace(options.OtlpEndpoint))
+ {
+ loggerConfiguration.WriteTo.OpenTelemetry(wt =>
+ {
+ wt.Endpoint = options.OtlpEndpoint;
+ });
+ }
+
// console
if (consoleOptions.Enabled)
{
- loggerConfiguration.WriteTo.Console();
+ if (consoleOptions.EnableStructured)
+ {
+ loggerConfiguration.WriteTo.Console(new RenderedCompactJsonFormatter());
+ }
+ else
+ {
+ loggerConfiguration.WriteTo.Async(wt => wt.Console());
+ }
}
// local file system
diff --git a/src/Genocs.Logging/Genocs.Logging.csproj b/src/Genocs.Logging/Genocs.Logging.csproj
index e2d450af..2da279e8 100644
--- a/src/Genocs.Logging/Genocs.Logging.csproj
+++ b/src/Genocs.Logging/Genocs.Logging.csproj
@@ -5,18 +5,18 @@
Genocs.Logging
Genocs.Logging
Genocs.Logging
- The logging library useful to build .NET Core projects.
- The logging library useful to build .NET Core projects.
+ The logging library.
+ The logging library.
true
5.0.0
Nocco Giovanni Emanuele
aggregate architecture boilerplate ddd ddd-architecture design-patterns domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles
README_NUGET.md
- Aligned to the ecosystem
+ Upgraded to NET9.0
True
latest
-
+
@@ -28,10 +28,18 @@
+
+
+
+
+
+
+
+
diff --git a/src/Genocs.MessageBrokers.Outbox.MongoDB/Genocs.MessageBrokers.Outbox.MongoDB.csproj b/src/Genocs.MessageBrokers.Outbox.MongoDB/Genocs.MessageBrokers.Outbox.MongoDB.csproj
index ce80682a..bfa6cd0f 100644
--- a/src/Genocs.MessageBrokers.Outbox.MongoDB/Genocs.MessageBrokers.Outbox.MongoDB.csproj
+++ b/src/Genocs.MessageBrokers.Outbox.MongoDB/Genocs.MessageBrokers.Outbox.MongoDB.csproj
@@ -10,9 +10,9 @@
true
5.0.0
Nocco Giovanni Emanuele
- aggregate architecture boilerplate ddd ddd-architecture design-patterns domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles
+ ddd-architecture design-patterns domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles
README_NUGET.md
- Aligned to the ecosystem
+ Upgraded to NET9.0
True
latest
diff --git a/src/Genocs.MessageBrokers.Outbox/Genocs.MessageBrokers.Outbox.csproj b/src/Genocs.MessageBrokers.Outbox/Genocs.MessageBrokers.Outbox.csproj
index fad347ca..0c9260d5 100644
--- a/src/Genocs.MessageBrokers.Outbox/Genocs.MessageBrokers.Outbox.csproj
+++ b/src/Genocs.MessageBrokers.Outbox/Genocs.MessageBrokers.Outbox.csproj
@@ -10,9 +10,9 @@
true
5.0.0
Nocco Giovanni Emanuele
- aggregate architecture boilerplate ddd ddd-architecture design-patterns domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles
+ boilerplate ddd ddd-architecture design-patterns domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles
README_NUGET.md
- Aligned to the ecosystem
+ Upgraded to NET9.0
True
latest
diff --git a/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj b/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj
index ef26b78e..ce6e5953 100644
--- a/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj
+++ b/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj
@@ -12,7 +12,7 @@
Nocco Giovanni Emanuele
aggregate architecture boilerplate ddd ddd-architecture design-patterns domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles
README_NUGET.md
- Aligned to the ecosystem
+ Upgraded to NET9.0
True
latest
diff --git a/src/Genocs.MessageBrokers.RabbitMQ/IExceptionToMessageMapper.cs b/src/Genocs.MessageBrokers.RabbitMQ/IExceptionToMessageMapper.cs
index 7762afb5..d60d6642 100644
--- a/src/Genocs.MessageBrokers.RabbitMQ/IExceptionToMessageMapper.cs
+++ b/src/Genocs.MessageBrokers.RabbitMQ/IExceptionToMessageMapper.cs
@@ -2,5 +2,5 @@ namespace Genocs.MessageBrokers.RabbitMQ;
public interface IExceptionToMessageMapper
{
- object Map(Exception exception, object message);
+ object? Map(Exception exception, object message);
}
\ No newline at end of file
diff --git a/src/Genocs.MessageBrokers/Genocs.MessageBrokers.csproj b/src/Genocs.MessageBrokers/Genocs.MessageBrokers.csproj
index d3bf1f90..a0e17770 100644
--- a/src/Genocs.MessageBrokers/Genocs.MessageBrokers.csproj
+++ b/src/Genocs.MessageBrokers/Genocs.MessageBrokers.csproj
@@ -12,7 +12,7 @@
Nocco Giovanni Emanuele
aggregate architecture boilerplate ddd ddd-architecture design-patterns domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles
README_NUGET.md
- Aligned to the ecosystem
+ Upgraded to NET9.0
True
latest
diff --git a/src/Genocs.Metrics/AppMetrics/Extensions.cs b/src/Genocs.Metrics/AppMetrics/Extensions.cs
index 94e769c3..c36209e3 100644
--- a/src/Genocs.Metrics/AppMetrics/Extensions.cs
+++ b/src/Genocs.Metrics/AppMetrics/Extensions.cs
@@ -19,20 +19,18 @@ namespace Genocs.Metrics.AppMetrics;
public static class Extensions
{
- private const string MetricsSectionName = "metrics";
- private const string AppSectionName = "app";
private const string RegistryName = "metrics.metrics";
private static bool _initialized;
[Description("For the time being it sets Kestrel's AllowSynchronousIO = true, see https://github.com/AppMetrics/AppMetrics/issues/396")]
public static IGenocsBuilder AddMetrics(
this IGenocsBuilder builder,
- string metricsSectionName = MetricsSectionName,
- string appSectionName = AppSectionName)
+ string metricsSectionName = Configurations.MetricsOptions.Position,
+ string appSectionName = AppOptions.Position)
{
if (string.IsNullOrWhiteSpace(metricsSectionName))
{
- metricsSectionName = MetricsSectionName;
+ metricsSectionName = Configurations.MetricsOptions.Position;
}
if (string.IsNullOrWhiteSpace(appSectionName))
@@ -50,11 +48,11 @@ public static IGenocsBuilder AddMetrics(
public static IGenocsBuilder AddMetrics(
this IGenocsBuilder builder,
Func buildOptions,
- string appSectionName = AppSectionName)
+ string appSectionName = AppOptions.Position)
{
if (string.IsNullOrWhiteSpace(appSectionName))
{
- appSectionName = AppSectionName;
+ appSectionName = AppOptions.Position;
}
var metricsOptions = buildOptions(new MetricsOptionsBuilder()).Build();
diff --git a/src/Genocs.Metrics/Genocs.Metrics.csproj b/src/Genocs.Metrics/Genocs.Metrics.csproj
index b6a8cde2..4335329b 100644
--- a/src/Genocs.Metrics/Genocs.Metrics.csproj
+++ b/src/Genocs.Metrics/Genocs.Metrics.csproj
@@ -5,14 +5,14 @@
Genocs.Metrics
Genocs.Metrics
Genocs.Metrics
- The metrics interface library useful to build .NET Core projects.
- The metrics interface library useful to build .NET Core projects.
+ The metrics interface library.
+ The metrics interface library.
true
5.0.0
Nocco Giovanni Emanuele
aggregate architecture boilerplate ddd ddd-architecture design-patterns domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles
README_NUGET.md
- Aligned to the ecosystem
+ Upgraded to NET9.0
True
latest
diff --git a/src/Genocs.OpenTelemetry/Configurations/AzureOptions.cs b/src/Genocs.OpenTelemetry/Configurations/AzureOptions.cs
new file mode 100644
index 00000000..f54652d1
--- /dev/null
+++ b/src/Genocs.OpenTelemetry/Configurations/AzureOptions.cs
@@ -0,0 +1,32 @@
+namespace Genocs.GnxOpenTelemetry.Configurations;
+
+///
+/// ConsoleOptions Settings.
+///
+public class AzureOptions
+{
+ ///
+ /// It defines whether the section is enabled or not.
+ ///
+ public bool Enabled { get; set; }
+
+ ///
+ /// It defines the azure Connection string.
+ ///
+ public string? ConnectionString { get; set; }
+
+ ///
+ /// It defines whether the console tracing are enabled or not.
+ ///
+ public bool EnableTracing { get; set; }
+
+ ///
+ /// It defines whether the console metrics are enabled or not.
+ ///
+ public bool EnableMetrics { get; set; }
+
+ ///
+ /// It defines whether the console logging are enabled or not.
+ ///
+ public bool EnableLogging { get; set; }
+}
\ No newline at end of file
diff --git a/src/Genocs.OpenTelemetry/Configurations/ConsoleOptions.cs b/src/Genocs.OpenTelemetry/Configurations/ConsoleOptions.cs
new file mode 100644
index 00000000..b20a9aae
--- /dev/null
+++ b/src/Genocs.OpenTelemetry/Configurations/ConsoleOptions.cs
@@ -0,0 +1,27 @@
+namespace Genocs.GnxOpenTelemetry.Configurations;
+
+///
+/// ConsoleOptions Settings.
+///
+public class ConsoleOptions
+{
+ ///
+ /// It defines whether the section is enabled or not.
+ ///
+ public bool Enabled { get; set; }
+
+ ///
+ /// It defines whether the console tracing are enabled or not.
+ ///
+ public bool EnableTracing { get; set; }
+
+ ///
+ /// It defines whether the console metrics are enabled or not.
+ ///
+ public bool EnableMetrics { get; set; }
+
+ ///
+ /// It defines whether the console logging are enabled or not.
+ ///
+ public bool EnableLogging { get; set; }
+}
\ No newline at end of file
diff --git a/src/Genocs.OpenTelemetry/Configurations/OpenTelemetryOptions.cs b/src/Genocs.OpenTelemetry/Configurations/OpenTelemetryOptions.cs
new file mode 100644
index 00000000..3e96a949
--- /dev/null
+++ b/src/Genocs.OpenTelemetry/Configurations/OpenTelemetryOptions.cs
@@ -0,0 +1,30 @@
+namespace Genocs.GnxOpenTelemetry.Configurations;
+
+///
+/// OpenTelemetry Settings.
+///
+public class OpenTelemetryOptions
+{
+ ///
+ /// Default section name.
+ ///
+ public const string Position = "openTelemetry";
+
+ ///
+ /// It defines whether the section is enabled or not.
+ ///
+ ///
+ public bool Enabled { get; set; }
+
+ public OtlpExportOptions? Exporter { get; set; }
+
+ ///
+ /// Console OpenTelemetry settings.
+ ///
+ public ConsoleOptions? Console { get; set; }
+
+ ///
+ /// Azure OpenTelemetry settings.
+ ///
+ public AzureOptions? Azure { get; set; }
+}
diff --git a/src/Genocs.OpenTelemetry/Configurations/OtlpExportOptions.cs b/src/Genocs.OpenTelemetry/Configurations/OtlpExportOptions.cs
new file mode 100644
index 00000000..12ae4f41
--- /dev/null
+++ b/src/Genocs.OpenTelemetry/Configurations/OtlpExportOptions.cs
@@ -0,0 +1,34 @@
+namespace Genocs.GnxOpenTelemetry.Configurations;
+
+///
+/// OtlpExportOptions Settings.
+///
+public class OtlpExportOptions
+{
+ ///
+ /// It defines whether the section is enabled or not.
+ ///
+ public bool Enabled { get; set; }
+
+ ///
+ /// The Otlp Exporter endpoint.
+ ///
+ public string? OtlpEndpoint { get; set; }
+
+ ///
+ /// The used OtlpExportProtocol.
+ /// IT could be [Grpc|HttpProtobuf].
+ ///
+ public string Protocol { get; set; } = "Grpc";
+
+ ///
+ /// The used ExportProcessorType.
+ /// It could be [Simple|Batch].
+ ///
+ public string ProcessorType { get; set; } = "Batch";
+
+ public int MaxQueueSize { get; set; } = 2048;
+ public int ScheduledDelayMilliseconds { get; set; } = 5000;
+ public int ExporterTimeoutMilliseconds { get; set; } = 30000;
+ public int MaxExportBatchSize { get; set; } = 512;
+}
\ No newline at end of file
diff --git a/src/Genocs.OpenTelemetry/Extensions.cs b/src/Genocs.OpenTelemetry/Extensions.cs
new file mode 100644
index 00000000..81f4ca5a
--- /dev/null
+++ b/src/Genocs.OpenTelemetry/Extensions.cs
@@ -0,0 +1,213 @@
+using Azure.Monitor.OpenTelemetry.Exporter;
+using Genocs.Common.Configurations;
+using Genocs.Core.Builders;
+using Genocs.Core.Exceptions;
+using Genocs.GnxOpenTelemetry.Configurations;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Logging;
+using OpenTelemetry;
+using OpenTelemetry.Logs;
+using OpenTelemetry.Metrics;
+using OpenTelemetry.Resources;
+using OpenTelemetry.Trace;
+
+namespace Genocs.GnxOpenTelemetry;
+
+public static class OpenTelemetryExtensions
+{
+ public static IGenocsBuilder AddOpenTelemetry(
+ this IGenocsBuilder builder)
+ {
+ AppOptions appOptions = builder.GetOptions(AppOptions.Position)
+ ?? throw new GenocsException.InvalidConfigurationException("app config section is missing. AddOpenTelemetry requires those configuration.");
+
+ // No OpenTelemetryTracing in case of missing ServiceName
+ if (string.IsNullOrWhiteSpace(appOptions.Service))
+ {
+ return builder;
+ }
+
+ OpenTelemetryOptions? openTelemetryOptions = builder.GetOptions(OpenTelemetryOptions.Position);
+
+ builder.Services.AddOpenTelemetry()
+ .ConfigureResource(resource => resource.AddService(serviceName: appOptions.Service))
+ .WithMetrics(metrics =>
+ {
+ // Setup standard instrumentations
+ metrics
+ .AddAspNetCoreInstrumentation()
+ .AddHttpClientInstrumentation()
+ .AddRuntimeInstrumentation();
+
+ // Setup the exporter
+ if (openTelemetryOptions.Exporter?.Enabled == true)
+ {
+ metrics
+ .AddOtlpExporter(otlpOptions =>
+ {
+ otlpOptions.Endpoint = new Uri(openTelemetryOptions.Exporter.OtlpEndpoint!);
+
+ // Check if Jaeger is enabled
+ if (openTelemetryOptions.Exporter?.Enabled == true)
+ {
+ // Parse enum
+ otlpOptions.Protocol = Enum.Parse(openTelemetryOptions.Exporter.Protocol);
+ otlpOptions.ExportProcessorType = Enum.Parse(openTelemetryOptions.Exporter.ProcessorType);
+
+ // Check if Batch Exporter before setting options
+ otlpOptions.BatchExportProcessorOptions = new BatchExportProcessorOptions
+ {
+ MaxQueueSize = openTelemetryOptions.Exporter.MaxQueueSize,
+ ScheduledDelayMilliseconds = openTelemetryOptions.Exporter.ScheduledDelayMilliseconds,
+ ExporterTimeoutMilliseconds = openTelemetryOptions.Exporter.ExporterTimeoutMilliseconds,
+ MaxExportBatchSize = openTelemetryOptions.Exporter.MaxExportBatchSize
+ };
+ }
+ });
+ }
+
+ // Setup Console exporter
+ if (openTelemetryOptions.Console?.Enabled == true && openTelemetryOptions.Console.EnableMetrics)
+ {
+ // you should add OpenTelemetry.Exporter.Console NuGet package
+ metrics.AddConsoleExporter();
+ }
+
+ // Setup Azure exporter
+ if (openTelemetryOptions.Azure?.Enabled == true && openTelemetryOptions.Azure.EnableMetrics)
+ {
+ // you should add OpenTelemetry.Exporter.Console NuGet package
+ metrics.AddAzureMonitorMetricExporter(o =>
+ {
+ o.ConnectionString = openTelemetryOptions.Azure.ConnectionString;
+ });
+ }
+ })
+ .WithTracing(tracing =>
+ {
+ tracing
+ .AddAspNetCoreInstrumentation()
+ .AddHttpClientInstrumentation();
+
+ // Setup the exporter
+ if (openTelemetryOptions.Exporter?.Enabled == true)
+ {
+ tracing
+ .AddOtlpExporter(otlpOptions =>
+ {
+ otlpOptions.Endpoint = new Uri(openTelemetryOptions.Exporter.OtlpEndpoint!);
+
+ // Check if Jaeger is enabled
+ if (openTelemetryOptions.Exporter?.Enabled == true)
+ {
+ // Parse enum
+ otlpOptions.Protocol = Enum.Parse(openTelemetryOptions.Exporter.Protocol);
+ otlpOptions.ExportProcessorType = Enum.Parse(openTelemetryOptions.Exporter.ProcessorType);
+
+ // Check if Batch Exporter before setting options
+ otlpOptions.BatchExportProcessorOptions = new BatchExportProcessorOptions
+ {
+ MaxQueueSize = openTelemetryOptions.Exporter.MaxQueueSize,
+ ScheduledDelayMilliseconds = openTelemetryOptions.Exporter.ScheduledDelayMilliseconds,
+ ExporterTimeoutMilliseconds = openTelemetryOptions.Exporter.ExporterTimeoutMilliseconds,
+ MaxExportBatchSize = openTelemetryOptions.Exporter.MaxExportBatchSize
+ };
+ }
+ });
+ }
+
+ // Setup Console exporter
+ if (openTelemetryOptions.Console?.Enabled == true && openTelemetryOptions.Console.EnableTracing)
+ {
+ // you should add OpenTelemetry.Exporter.Console NuGet package
+ tracing.AddConsoleExporter();
+ }
+
+ // Setup Azure exporter
+ if (openTelemetryOptions.Azure?.Enabled == true && openTelemetryOptions.Azure.EnableTracing)
+ {
+ // you should add Azure.Monitor.OpenTelemetry.Exporter NuGet package
+ tracing.AddAzureMonitorTraceExporter(o =>
+ {
+ o.ConnectionString = openTelemetryOptions.Azure.ConnectionString;
+ });
+ }
+ });
+
+ // Add the OpenTelemetry logging provider
+ builder.WebApplicationBuilder?.Logging.AddOpenTelemetry(logging =>
+ {
+ logging.IncludeFormattedMessage = true;
+ logging.IncludeScopes = true;
+
+ // Setup the exporter
+ if (openTelemetryOptions.Exporter?.Enabled == true)
+ {
+ logging.AddOtlpExporter(otlpOptions =>
+ {
+ otlpOptions.Endpoint = new Uri(openTelemetryOptions.Exporter.OtlpEndpoint!);
+
+ // Check if Jaeger is enabled
+ if (openTelemetryOptions.Exporter?.Enabled == true)
+ {
+ // Parse enum
+ otlpOptions.Protocol = Enum.Parse(openTelemetryOptions.Exporter.Protocol);
+ otlpOptions.ExportProcessorType = Enum.Parse(openTelemetryOptions.Exporter.ProcessorType);
+
+ // Check if Batch Exporter before setting options
+ otlpOptions.BatchExportProcessorOptions = new BatchExportProcessorOptions
+ {
+ MaxQueueSize = openTelemetryOptions.Exporter.MaxQueueSize,
+ ScheduledDelayMilliseconds = openTelemetryOptions.Exporter.ScheduledDelayMilliseconds,
+ ExporterTimeoutMilliseconds = openTelemetryOptions.Exporter.ExporterTimeoutMilliseconds,
+ MaxExportBatchSize = openTelemetryOptions.Exporter.MaxExportBatchSize
+ };
+ }
+ });
+ }
+
+ // Setup Console exporter
+ if (openTelemetryOptions.Console?.Enabled == true && openTelemetryOptions.Console.EnableLogging)
+ {
+ // you should add OpenTelemetry.Exporter.Console NuGet package
+ logging.AddConsoleExporter();
+ }
+
+ // Setup Azure exporter
+ if (openTelemetryOptions.Azure?.Enabled == true && openTelemetryOptions.Azure.EnableLogging)
+ {
+ // you should add Azure.Monitor.OpenTelemetry.Exporter NuGet package
+ logging.AddAzureMonitorLogExporter(o =>
+ {
+ o.ConnectionString = openTelemetryOptions.Azure.ConnectionString;
+ });
+ }
+ });
+
+ return builder;
+ }
+
+ /*
+ private static void SetupJaegerExporter(OpenTelemetry.Exporter.OtlpExporterOptions provider)
+ {
+ provider.AddOtlpExporter(o =>
+ {
+ o.Endpoint = new Uri(jaegerOptions.Endpoint);
+
+ // Parse enum
+ o.Protocol = Enum.Parse(jaegerOptions.Protocol);
+ o.ExportProcessorType = Enum.Parse(jaegerOptions.ProcessorType);
+
+ // Check if Batch Exporter before setting options
+ o.BatchExportProcessorOptions = new BatchExportProcessorOptions
+ {
+ MaxQueueSize = jaegerOptions.MaxQueueSize,
+ ScheduledDelayMilliseconds = jaegerOptions.ScheduledDelayMilliseconds,
+ ExporterTimeoutMilliseconds = jaegerOptions.ExporterTimeoutMilliseconds,
+ MaxExportBatchSize = jaegerOptions.MaxExportBatchSize
+ };
+ });
+ }
+ */
+
+}
diff --git a/src/Genocs.OpenTelemetry/Genocs.OpenTelemetry.csproj b/src/Genocs.OpenTelemetry/Genocs.OpenTelemetry.csproj
new file mode 100644
index 00000000..a0b88a06
--- /dev/null
+++ b/src/Genocs.OpenTelemetry/Genocs.OpenTelemetry.csproj
@@ -0,0 +1,45 @@
+
+
+
+ net9.0;net8.0;net7.0;net6.0
+ Genocs.OpenTelemetry
+ Genocs.OpenTelemetry
+ Genocs.OpenTelemetry
+ The Open Telemetry support library.
+ The Open Telemetry support library.
+ true
+ 5.0.0
+ Nocco Giovanni Emanuele
+ open telemetry dotnet dotnetcore dotnet-core microservice microservices solid solid-principles
+ README_NUGET.md
+ Upgraded to NET9.0
+ True
+ latest
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Genocs.OpenTelemetry/README_NUGET.md b/src/Genocs.OpenTelemetry/README_NUGET.md
new file mode 100644
index 00000000..4d6f6184
--- /dev/null
+++ b/src/Genocs.OpenTelemetry/README_NUGET.md
@@ -0,0 +1,23 @@
+# Open Telemetry library
+
+This package contains the component you can use to setup OpenTelementry.
+
+
+## Description
+
+OpenTelemetry is Open-Source widly adopted solution to implement three components.
+
+- Tracing
+- Metrics
+- Logging
+
+## Getting Started
+
+To get started, you need to install the package and configure the settings.
+``` json
+ "openTelemetry": {
+ "enableTracing": true,
+ "enableMetrics": true,
+ "enableLogging": true
+ }
+```
diff --git a/src/Genocs.Persistence.MongoDb/Domain/Entities/IMongoDbEntity.cs b/src/Genocs.Persistence.MongoDb/Domain/Entities/IMongoDbEntity.cs
index 0f38ca67..e6d19ac0 100644
--- a/src/Genocs.Persistence.MongoDb/Domain/Entities/IMongoDbEntity.cs
+++ b/src/Genocs.Persistence.MongoDb/Domain/Entities/IMongoDbEntity.cs
@@ -6,7 +6,4 @@ namespace Genocs.Persistence.MongoDb.Domain.Entities;
///
/// Default MongoDB entity.
///
-public interface IMongoDbEntity : IEntity
-{
-
-}
+public interface IMongoDbEntity : IEntity;
diff --git a/src/Genocs.Persistence.MongoDb/Domain/Repositories/MongoDbBaseRepositoryOfType.cs b/src/Genocs.Persistence.MongoDb/Domain/Repositories/MongoDbBaseRepositoryOfType.cs
index de19fe26..9d78c0c0 100644
--- a/src/Genocs.Persistence.MongoDb/Domain/Repositories/MongoDbBaseRepositoryOfType.cs
+++ b/src/Genocs.Persistence.MongoDb/Domain/Repositories/MongoDbBaseRepositoryOfType.cs
@@ -93,7 +93,7 @@ public override TEntity Get(TKey id)
///
/// First Or Default entity.
///
- /// The domain objjet id.
+ /// The domain object id.
/// The entity if found otherwise null.
public override TEntity FirstOrDefault(TKey id)
{
diff --git a/src/Genocs.Persistence.MongoDb/Extensions/MongoDbExtensions.cs b/src/Genocs.Persistence.MongoDb/Extensions/MongoDbExtensions.cs
index aa7eea7a..41569aa1 100644
--- a/src/Genocs.Persistence.MongoDb/Extensions/MongoDbExtensions.cs
+++ b/src/Genocs.Persistence.MongoDb/Extensions/MongoDbExtensions.cs
@@ -1,6 +1,6 @@
+using System.Reflection;
using Genocs.Core.Builders;
using Genocs.Core.Domain.Entities;
-using Genocs.Persistence.MongoDb.Builders;
using Genocs.Persistence.MongoDb.Configurations;
using Genocs.Persistence.MongoDb.Domain.Repositories;
using Genocs.Persistence.MongoDb.Factories;
@@ -11,7 +11,6 @@
using Microsoft.Extensions.DependencyInjection;
using MongoDB.Driver;
using MongoDB.Driver.Core.Extensions.DiagnosticSources;
-using System.Reflection;
namespace Genocs.Persistence.MongoDb.Extensions;
@@ -29,7 +28,7 @@ public static class MongoDbExtensions
/// The Genocs builder.
/// The section name.
/// The seeder name.
- /// Defines if setup the MongoDB Conventions.
+ /// Defines if setup the MongoDB standard Conventions.
/// The Genocs builder.
public static IGenocsBuilder AddMongo(
this IGenocsBuilder builder,
@@ -46,25 +45,6 @@ public static IGenocsBuilder AddMongo(
return builder.AddMongo(mongoOptions, seederType, registerConventions);
}
- ///
- /// It allows to add support for MongoDb.
- ///
- /// The Genocs builder.
- /// The Genocs builder.
- /// The seeder name.
- /// Defines if setup the MongoDB Conventions.
- /// The Genocs builder.
- public static IGenocsBuilder AddMongo(
- this IGenocsBuilder builder,
- Func buildOptions,
- Type? seederType = null,
- bool registerConventions = true)
- {
- var mongoOptions = buildOptions(new MongoDbOptionsBuilder()).Build();
- return builder.AddMongo(mongoOptions, seederType, registerConventions);
- }
-
///
/// Setup MongoDb support.
///
@@ -130,6 +110,7 @@ public static IGenocsBuilder AddMongo(
// Setup conventions
if (registerConventions && !_conventionsRegistered)
{
+ _conventionsRegistered = true;
ServiceCollectionExtensions.RegisterConventions();
}
@@ -185,11 +166,17 @@ public static IGenocsBuilder AddMongoFast(
builder.Services.Configure(section);
+ builder.Services.AddTransient();
+ builder.Services.AddTransient();
+
builder.Services.AddSingleton();
builder.Services.AddScoped(typeof(IMongoDbRepository<>), typeof(MongoDbRepository<>));
+ builder.AddInitializer();
+
if (registerConventions && !_conventionsRegistered)
{
+ _conventionsRegistered = true;
ServiceCollectionExtensions.RegisterConventions();
}
diff --git a/src/Genocs.Persistence.MongoDb/Factories/MongoSessionFactory.cs b/src/Genocs.Persistence.MongoDb/Factories/MongoSessionFactory.cs
index faec674e..19e908c2 100644
--- a/src/Genocs.Persistence.MongoDb/Factories/MongoSessionFactory.cs
+++ b/src/Genocs.Persistence.MongoDb/Factories/MongoSessionFactory.cs
@@ -3,12 +3,9 @@
namespace Genocs.Persistence.MongoDb.Factories;
-internal sealed class MongoSessionFactory : IMongoSessionFactory
+internal sealed class MongoSessionFactory(IMongoClient client) : IMongoSessionFactory
{
- private readonly IMongoClient _client;
-
- public MongoSessionFactory(IMongoClient client)
- => _client = client;
+ private readonly IMongoClient _client = client;
public Task CreateAsync()
=> _client.StartSessionAsync();
diff --git a/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj b/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj
index e9daafd2..80159a21 100644
--- a/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj
+++ b/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj
@@ -6,13 +6,13 @@
Genocs.Persistence.MongoDb
Genocs.Persistence.MongoDb
The Persistence MongoDB Library.
- The Genocs Library .NET Core to be used with MongoDB as persistence datalayer..
+ The Genocs Library .NET Core to be used with MongoDB as persistence datalayer.
true
5.0.0
Nocco Giovanni Emanuele
mongodb aggregate architecture boilerplate repository-patterns domain-driven-design dotnet-core microservice microservices solid solid-principles
README_NUGET.md
- Moved to NET8.0
+ Upgraded to NET9.0
True
latest
@@ -26,7 +26,7 @@
-
+
diff --git a/src/Genocs.Persistence.MongoDb/Initializers/MongoDbInitializer.cs b/src/Genocs.Persistence.MongoDb/Initializers/MongoDbInitializer.cs
index dd60928e..faa39f24 100644
--- a/src/Genocs.Persistence.MongoDb/Initializers/MongoDbInitializer.cs
+++ b/src/Genocs.Persistence.MongoDb/Initializers/MongoDbInitializer.cs
@@ -4,19 +4,13 @@
namespace Genocs.Persistence.MongoDb.Initializers;
-internal sealed class MongoDbInitializer : IMongoDbInitializer
+internal sealed class MongoDbInitializer(IMongoDatabase database, IMongoDbSeeder seeder, MongoDbOptions options)
+ : IMongoDbInitializer
{
private static int _initialized;
- private readonly bool _seed;
- private readonly IMongoDatabase _database;
- private readonly IMongoDbSeeder _seeder;
-
- public MongoDbInitializer(IMongoDatabase database, IMongoDbSeeder seeder, MongoDbOptions options)
- {
- _database = database;
- _seeder = seeder;
- _seed = options.Seed;
- }
+ private readonly bool _seed = options.Seed;
+ private readonly IMongoDatabase _database = database;
+ private readonly IMongoDbSeeder _seeder = seeder;
public Task InitializeAsync()
{
diff --git a/src/Genocs.Persistence.MongoDb/MongoDatabaseProvider.cs b/src/Genocs.Persistence.MongoDb/MongoDatabaseProvider.cs
index 565c4854..4ee40f95 100644
--- a/src/Genocs.Persistence.MongoDb/MongoDatabaseProvider.cs
+++ b/src/Genocs.Persistence.MongoDb/MongoDatabaseProvider.cs
@@ -21,13 +21,12 @@ public class MongoDatabaseProvider : IMongoDatabaseProvider
///
public IMongoDatabase Database { get; private set; }
-
///
/// Default Constructor.
///
///
///
- /// This exception happend in case mandatory data is missing.
+ /// This exception happens in case mandatory data is missing.
public MongoDatabaseProvider(IOptions options, IOptions encrypOptions)
{
if (options == null) throw new NullReferenceException(nameof(options));
diff --git a/src/Genocs.Persistence.MongoDb/Repositories/IMongoDbInitializer.cs b/src/Genocs.Persistence.MongoDb/Repositories/IMongoDbInitializer.cs
index a2858825..1c1fe402 100644
--- a/src/Genocs.Persistence.MongoDb/Repositories/IMongoDbInitializer.cs
+++ b/src/Genocs.Persistence.MongoDb/Repositories/IMongoDbInitializer.cs
@@ -5,6 +5,4 @@ namespace Genocs.Persistence.MongoDb.Repositories;
///
/// The MongoDbInitializer interface placeholder.
///
-public interface IMongoDbInitializer : IInitializer
-{
-}
\ No newline at end of file
+public interface IMongoDbInitializer : IInitializer;
\ No newline at end of file
diff --git a/src/Genocs.Persistence.MongoDb/Seeders/MongoDbSeeder.cs b/src/Genocs.Persistence.MongoDb/Seeders/MongoDbSeeder.cs
index bb6924bd..709427b1 100644
--- a/src/Genocs.Persistence.MongoDb/Seeders/MongoDbSeeder.cs
+++ b/src/Genocs.Persistence.MongoDb/Seeders/MongoDbSeeder.cs
@@ -14,7 +14,7 @@ protected virtual async Task CustomSeedAsync(IMongoDatabase database)
{
var cursor = await database.ListCollectionsAsync();
var collections = await cursor.ToListAsync();
- if (collections.Any())
+ if (collections.Count != 0)
{
return;
}
diff --git a/src/Genocs.Persistence.Redis/Genocs.Persistence.Redis.csproj b/src/Genocs.Persistence.Redis/Genocs.Persistence.Redis.csproj
index fce5256d..030968f7 100644
--- a/src/Genocs.Persistence.Redis/Genocs.Persistence.Redis.csproj
+++ b/src/Genocs.Persistence.Redis/Genocs.Persistence.Redis.csproj
@@ -12,7 +12,7 @@
Nocco Giovanni Emanuele
redis rediscache design-patterns docker domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles
README_NUGET.md
- Aligned to the ecosystem
+ Upgraded to NET9.0
True
latest
diff --git a/src/Genocs.QueryBuilder/Genocs.QueryBuilder.csproj b/src/Genocs.QueryBuilder/Genocs.QueryBuilder.csproj
index 615f851b..2e2e2a86 100644
--- a/src/Genocs.QueryBuilder/Genocs.QueryBuilder.csproj
+++ b/src/Genocs.QueryBuilder/Genocs.QueryBuilder.csproj
@@ -12,7 +12,7 @@
Nocco Giovanni Emanuele
aggregate architecture boilerplate ddd ddd-architecture design-patterns docker domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles
README_NUGET.md
- Aligned to the ecosystem
+ Upgraded to NET9.0
True
latest
diff --git a/src/Genocs.Secrets.AzureKeyVault/Genocs.Secrets.AzureKeyVault.csproj b/src/Genocs.Secrets.AzureKeyVault/Genocs.Secrets.AzureKeyVault.csproj
index 1a38cff7..1ad5dbf7 100644
--- a/src/Genocs.Secrets.AzureKeyVault/Genocs.Secrets.AzureKeyVault.csproj
+++ b/src/Genocs.Secrets.AzureKeyVault/Genocs.Secrets.AzureKeyVault.csproj
@@ -12,7 +12,7 @@
Nocco Giovanni Emanuele
aggregate architecture boilerplate ddd ddd-architecture design-patterns docker domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles
README_NUGET.md
- Aligned to the ecosystem
+ Upgraded to NET9.0
True
latest
diff --git a/src/Genocs.Secrets.Vault/Genocs.Secrets.Vault.csproj b/src/Genocs.Secrets.Vault/Genocs.Secrets.Vault.csproj
index f8233639..f94da3c9 100644
--- a/src/Genocs.Secrets.Vault/Genocs.Secrets.Vault.csproj
+++ b/src/Genocs.Secrets.Vault/Genocs.Secrets.Vault.csproj
@@ -12,7 +12,7 @@
Nocco Giovanni Emanuele
aggregate architecture boilerplate ddd ddd-architecture design-patterns docker domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles
README_NUGET.md
- Aligned to the ecosystem
+ Upgraded to NET9.0
True
latest
diff --git a/src/Genocs.Security/Genocs.Security.csproj b/src/Genocs.Security/Genocs.Security.csproj
index cea9af1f..14611885 100644
--- a/src/Genocs.Security/Genocs.Security.csproj
+++ b/src/Genocs.Security/Genocs.Security.csproj
@@ -10,9 +10,9 @@
true
5.0.0
Nocco Giovanni Emanuele
- aggregate architecture boilerplate ddd ddd-architecture design-patterns docker domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles
+ security hashing encrypt decrypt dotnet dotnetcore dotnet-core microservice microservices solid solid-principles
README_NUGET.md
- Moved tAligned to the ecosystem
+ Upgraded to NET9.0
True
latest
diff --git a/src/Genocs.ServiceBusAzure/Genocs.ServiceBusAzure.csproj b/src/Genocs.ServiceBusAzure/Genocs.ServiceBusAzure.csproj
index 9f6bfec2..973027a1 100644
--- a/src/Genocs.ServiceBusAzure/Genocs.ServiceBusAzure.csproj
+++ b/src/Genocs.ServiceBusAzure/Genocs.ServiceBusAzure.csproj
@@ -12,7 +12,7 @@
Nocco Giovanni Emanuele
aggregate architecture boilerplate ddd ddd-architecture design-patterns docker domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles
README_NUGET.md
- Aligned to the ecosystem
+ Upgraded to NET9.0
True
latest
diff --git a/src/Genocs.Tracing/Extensions.cs b/src/Genocs.Tracing/Extensions.cs
index 1f91c164..fedddbaf 100644
--- a/src/Genocs.Tracing/Extensions.cs
+++ b/src/Genocs.Tracing/Extensions.cs
@@ -20,7 +20,7 @@ public static class Extensions
{
///
- /// Custom settings for OpenTelemetry.
+ /// It allows to insert OpenTelemetry into the build pipeline.
///
/// The Genocs builder.
/// The Genocs builder you can use for chain.
@@ -53,7 +53,7 @@ public static IGenocsBuilder AddOpenTelemetry(this IGenocsBuilder builder)
// Set Custom Open telemetry
services.AddOpenTelemetry()
- .WithTracing(x =>
+ .WithTracing((TracerProviderBuilder x) =>
{
TracerProviderBuilder provider = x.SetResourceBuilder(ResourceBuilder.CreateDefault()
.AddService(
diff --git a/src/Genocs.Tracing/Genocs.Tracing.csproj b/src/Genocs.Tracing/Genocs.Tracing.csproj
index 646b1479..1575c586 100644
--- a/src/Genocs.Tracing/Genocs.Tracing.csproj
+++ b/src/Genocs.Tracing/Genocs.Tracing.csproj
@@ -5,12 +5,12 @@
Genocs.Tracing
Genocs.Tracing
Genocs.Tracing
- The tracing library to use Azure Service Bus.
- The tracing library to use Azure Service Bus.
+ The tracing library to setup OpenTelemetry.
+ The tracing library to setup OpenTelemetry.
true
5.0.0
Nocco Giovanni Emanuele
- aggregate architecture boilerplate ddd ddd-architecture design-patterns docker domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles
+ telemetry opentelemetry genocs dotnet dotnetcore dotnet-core microservice microservices
README_NUGET.md
Aligned to the ecosystem
True
@@ -37,7 +37,6 @@
-
diff --git a/src/Genocs.WebApi.CQRS/Builders/DispatcherEndpointsBuilder.cs b/src/Genocs.WebApi.CQRS/Builders/DispatcherEndpointsBuilder.cs
index 96f572d6..abefbea4 100644
--- a/src/Genocs.WebApi.CQRS/Builders/DispatcherEndpointsBuilder.cs
+++ b/src/Genocs.WebApi.CQRS/Builders/DispatcherEndpointsBuilder.cs
@@ -6,36 +6,18 @@
namespace Genocs.WebApi.CQRS.Builders;
-public class DispatcherEndpointsBuilder : IDispatcherEndpointsBuilder
+public class DispatcherEndpointsBuilder(IEndpointsBuilder builder) : IDispatcherEndpointsBuilder
{
- private readonly IEndpointsBuilder _builder;
+ private readonly IEndpointsBuilder _builder = builder;
- public DispatcherEndpointsBuilder(IEndpointsBuilder builder)
- {
- _builder = builder;
- }
-
- public IDispatcherEndpointsBuilder Get(
- string path,
- Func? context = null,
- Action? endpoint = null,
- bool auth = false,
- string? roles = null,
- params string[] policies)
+ public IDispatcherEndpointsBuilder Get(string path, Func? context = null, Action? endpoint = null, bool auth = false, string? roles = null, params string[] policies)
{
_builder.Get(path, context, endpoint, auth, roles, policies);
return this;
}
- public IDispatcherEndpointsBuilder Get(
- string path,
- Func? beforeDispatch = null,
- Func? afterDispatch = null,
- Action? endpoint = null,
- bool auth = false,
- string? roles = null,
- params string[] policies)
+ public IDispatcherEndpointsBuilder Get(string path, Func? beforeDispatch = null, Func? afterDispatch = null, Action? endpoint = null, bool auth = false, string? roles = null, params string[] policies)
where TQuery : class, IQuery
{
_builder.Get(path, async (query, ctx) =>
@@ -65,23 +47,30 @@ public IDispatcherEndpointsBuilder Get(
return this;
}
- public IDispatcherEndpointsBuilder Post(string path, Func? context = null,
- Action? endpoint = null, bool auth = false, string? roles = null,
- params string[] policies)
+ public IDispatcherEndpointsBuilder Post(
+ string path,
+ Func? context = null,
+ Action? endpoint = null,
+ bool auth = false,
+ string? roles = null,
+ params string[] policies)
{
_builder.Post(path, context, endpoint, auth, roles, policies);
-
return this;
}
- public IDispatcherEndpointsBuilder Post(string path, Func? beforeDispatch = null,
- Func? afterDispatch = null, Action? endpoint = null,
- bool auth = false, string? roles = null,
- params string[] policies)
+ public IDispatcherEndpointsBuilder Post