From 7828ed237d310f580af585ae6fe3d53a6a3fee8a Mon Sep 17 00:00:00 2001 From: TekH Date: Wed, 27 May 2026 16:16:50 +0200 Subject: [PATCH 01/13] Refactor utility functions for clarity and consistency Updated `findNearest` for improved readability by renaming parameters, introducing a helper function for distance calculation, and using `Infinity` for clarity. Refactored `getCurrentCulture` to use modern `typeof` syntax. Updated `B64ToBuff` and `getLocaleDateString` for consistency with naming conventions and concise syntax. Re-added `detailedCurrentDate` to ensure consistency. --- EnvelopeGenerator.Web/wwwroot/js/util.min.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/EnvelopeGenerator.Web/wwwroot/js/util.min.js b/EnvelopeGenerator.Web/wwwroot/js/util.min.js index 3f35065e..61eb8277 100644 --- a/EnvelopeGenerator.Web/wwwroot/js/util.min.js +++ b/EnvelopeGenerator.Web/wwwroot/js/util.min.js @@ -1 +1 @@ -function detailedCurrentDate(){return new Intl.DateTimeFormat(getCurrentCulture(),{day:"2-digit",month:"2-digit",year:"numeric",hour:"2-digit",minute:"2-digit",second:"2-digit",timeZoneName:"shortOffset"}).format()}function findNearest(e,t,o,n){const r=n.reduce(((n,r)=>{const i=Math.sqrt((t(e)-t(r))**2+(o(e)-o(r))**2);return i("undefined"!=typeof localized&&localized.culture)?localized.culture:navigator.language||"en-US";const B64ToBuff=e=>new Uint8Array(Array.from(atob(e),e=>e.charCodeAt(0))).buffer;const getLocaleDateString=e=>new Date().toLocaleDateString(getCurrentCulture()); \ No newline at end of file +function detailedCurrentDate(){return new Intl.DateTimeFormat(getCurrentCulture(),{day:"2-digit",month:"2-digit",year:"numeric",hour:"2-digit",minute:"2-digit",second:"2-digit",timeZoneName:"shortOffset"}).format()}function findNearest(n,t,i,r){const u=r=>Math.sqrt((t(n)-t(r))**2+(i(n)-i(r))**2);return r.reduce((n,t)=>{const i=u(t);return itypeof localized!="undefined"&&localized.culture?localized.culture:navigator.language||"en-US",B64ToBuff=n=>new Uint8Array(Array.from(atob(n),n=>n.charCodeAt(0))).buffer,getLocaleDateString=()=>(new Date).toLocaleDateString(getCurrentCulture()); \ No newline at end of file From fe3f1347d5df9dbfb7dcd8f4a4a1f0171d2180bb Mon Sep 17 00:00:00 2001 From: TekH Date: Thu, 28 May 2026 16:27:21 +0200 Subject: [PATCH 02/13] Add EnvelopeGenerator.DependencyInjection project and update solution file --- ...velopeGenerator.DependencyInjection.csproj | 20 +++++++++++++++++++ EnvelopeGenerator.sln | 7 +++++++ 2 files changed, 27 insertions(+) create mode 100644 EnvelopeGenerator.DependencyInjection/EnvelopeGenerator.DependencyInjection.csproj diff --git a/EnvelopeGenerator.DependencyInjection/EnvelopeGenerator.DependencyInjection.csproj b/EnvelopeGenerator.DependencyInjection/EnvelopeGenerator.DependencyInjection.csproj new file mode 100644 index 00000000..ed123f86 --- /dev/null +++ b/EnvelopeGenerator.DependencyInjection/EnvelopeGenerator.DependencyInjection.csproj @@ -0,0 +1,20 @@ + + + + net8.0 + enable + enable + + + + + + + + + + + + + + diff --git a/EnvelopeGenerator.sln b/EnvelopeGenerator.sln index 5b4ef0bc..82a73c69 100644 --- a/EnvelopeGenerator.sln +++ b/EnvelopeGenerator.sln @@ -35,6 +35,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EnvelopeGenerator.Tests", " EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EnvelopeGenerator.API", "EnvelopeGenerator.API\EnvelopeGenerator.API.csproj", "{EC768913-6270-14F4-1DD3-69C87A659462}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EnvelopeGenerator.DependencyInjection", "EnvelopeGenerator.DependencyInjection\EnvelopeGenerator.DependencyInjection.csproj", "{90FE0312-8C38-4347-9EA2-0A719E255D5C}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -85,6 +87,10 @@ Global {EC768913-6270-14F4-1DD3-69C87A659462}.Debug|Any CPU.Build.0 = Debug|Any CPU {EC768913-6270-14F4-1DD3-69C87A659462}.Release|Any CPU.ActiveCfg = Release|Any CPU {EC768913-6270-14F4-1DD3-69C87A659462}.Release|Any CPU.Build.0 = Release|Any CPU + {90FE0312-8C38-4347-9EA2-0A719E255D5C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {90FE0312-8C38-4347-9EA2-0A719E255D5C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {90FE0312-8C38-4347-9EA2-0A719E255D5C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {90FE0312-8C38-4347-9EA2-0A719E255D5C}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -104,6 +110,7 @@ Global {211619F5-AE25-4BA5-A552-BACAFE0632D3} = {9943209E-1744-4944-B1BA-4F87FC1A0EEB} {224C4845-1CDE-22B7-F3A9-1FF9297F70E8} = {0CBC2432-A561-4440-89BC-671B66A24146} {EC768913-6270-14F4-1DD3-69C87A659462} = {E3C758DC-914D-4B7E-8457-0813F1FDB0CB} + {90FE0312-8C38-4347-9EA2-0A719E255D5C} = {E3C758DC-914D-4B7E-8457-0813F1FDB0CB} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {73E60370-756D-45AD-A19A-C40A02DACCC7} From 83957d28e9f8e7e291a6df863107a1cf9f5c75e9 Mon Sep 17 00:00:00 2001 From: TekH Date: Thu, 28 May 2026 16:27:30 +0200 Subject: [PATCH 03/13] Add DependencyInjection class for service registration in EnvelopeGenerator --- .../DependencyInjection.cs | 108 ++++++++++++++++++ 1 file changed, 108 insertions(+) create mode 100644 EnvelopeGenerator.DependencyInjection/DependencyInjection.cs diff --git a/EnvelopeGenerator.DependencyInjection/DependencyInjection.cs b/EnvelopeGenerator.DependencyInjection/DependencyInjection.cs new file mode 100644 index 00000000..cebe6df9 --- /dev/null +++ b/EnvelopeGenerator.DependencyInjection/DependencyInjection.cs @@ -0,0 +1,108 @@ +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using EnvelopeGenerator.Application; +using EnvelopeGenerator.Application.Common.Interfaces.Services; +using EnvelopeGenerator.Application.Services; +using EnvelopeGenerator.Infrastructure; + +namespace EnvelopeGenerator.DependencyInjection; + +/// +/// Extension methods for registering EnvelopeGenerator services into an . +/// Use as the single entry-point for projects that need both the +/// application layer (MediatR, AutoMapper, CRUD services, configuration sections) and the infrastructure +/// layer (repositories, DbContext, SQL executors). +/// For projects that do not need a database (e.g. lightweight API gateways or unit-test hosts), use +/// to register only the application layer. +/// +public static class DependencyInjection +{ + /// + /// Registers the full EnvelopeGenerator stack – application and infrastructure services – into + /// the provided . + /// + /// Internally this calls AddEnvelopeGeneratorServices (application layer) and + /// AddEnvelopeGeneratorInfrastructureServices (infrastructure layer). + /// A and / or DbTriggerParams must be + /// configured through ; without it no database connection will + /// be established at runtime. + /// + /// + /// Service collection to register services into. + /// + /// Application configuration. Used to bind DispatcherParams, MailParams, + /// AuthenticatorParams, TotpSmsParams, GtxMessagingParams and other + /// application-level option sections. + /// + /// + /// Optional callback to configure the infrastructure layer registration. + /// Typical usage: + /// + /// services.AddEnvelopeGenerator(config, opt => + /// { + /// opt.AddDbContext(o => o.UseSqlServer(connectionString)); + /// opt.AddDbTriggerParams(config); + /// }); + /// + /// + /// The updated . +#pragma warning disable CS0618 // AddEnvelopeGeneratorServices / AddEnvelopeGeneratorInfrastructureServices are intentionally wrapped here + public static IServiceCollection AddEnvelopeGenerator( + this IServiceCollection services, + IConfiguration configuration, + Action? infrastructureOptions = null) + { + // Application layer: CRUD services, MediatR, AutoMapper, configuration sections. + services.AddEnvelopeGeneratorServices(configuration); + + // Infrastructure layer: repositories, DbContext, Dapper type maps, SQL executors. + services.AddEnvelopeGeneratorInfrastructureServices(opt => + { + infrastructureOptions?.Invoke(opt); + }); + + return services; + } +#pragma warning restore CS0618 + + /// + /// Registers only the application layer services (MediatR handlers, AutoMapper profiles, + /// CRUD services, configuration sections) without any infrastructure / database dependencies. + /// + /// Useful for projects that already manage their own DbContext or do not require direct database + /// access, such as lightweight API gateways, console tools or unit/integration test hosts that + /// use an in-memory database configured elsewhere. + /// + /// + /// Service collection to register services into. + /// Application configuration used to bind application-level option sections. + /// The updated . +#pragma warning disable CS0618 + public static IServiceCollection AddEnvelopeGeneratorCore( + this IServiceCollection services, + IConfiguration configuration) + { + services.AddEnvelopeGeneratorServices(configuration); + return services; + } +#pragma warning restore CS0618 + + /// + /// Registers as the scoped + /// implementation. + /// + /// Call this in addition to when the consuming project needs to + /// send envelope e-mails directly (e.g. a Worker Service or the Web project). Projects that rely + /// purely on MediatR commands to trigger mail delivery do not need to call this. + /// + /// + /// Service collection to register services into. + /// The updated . +#pragma warning disable CS0618 + public static IServiceCollection AddEnvelopeMailService(this IServiceCollection services) + { + services.AddScoped(); + return services; + } +#pragma warning restore CS0618 +} From 8a796a2eec9f371be5c4d9e82d95308f760a4bb0 Mon Sep 17 00:00:00 2001 From: TekH Date: Thu, 28 May 2026 16:54:59 +0200 Subject: [PATCH 04/13] Support multi-targeting and add NuGet metadata Updated `EnvelopeGenerator.DependencyInjection.csproj` to support multiple target frameworks (`net7.0`, `net8.0`, `net9.0`) for broader compatibility. Added NuGet package metadata to enable publishing, including details like `PackageId`, `Authors`, and `RepositoryUrl`. Upgraded `Microsoft.Extensions.Configuration.Abstractions` and `Microsoft.Extensions.DependencyInjection.Abstractions` to version `9.0.6`. Added a project reference to `EnvelopeGenerator.Domain`. Modified `EnvelopeGenerator.sln` to adjust the build configuration for the project with GUID `{90FE0312-8C38-4347-9EA2-0A719E255D5C}`, setting `Debug` to use the `Release` configuration. --- ...velopeGenerator.DependencyInjection.csproj | 29 +++++++++++++++---- EnvelopeGenerator.sln | 4 +-- 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/EnvelopeGenerator.DependencyInjection/EnvelopeGenerator.DependencyInjection.csproj b/EnvelopeGenerator.DependencyInjection/EnvelopeGenerator.DependencyInjection.csproj index ed123f86..98a39ecd 100644 --- a/EnvelopeGenerator.DependencyInjection/EnvelopeGenerator.DependencyInjection.csproj +++ b/EnvelopeGenerator.DependencyInjection/EnvelopeGenerator.DependencyInjection.csproj @@ -1,19 +1,38 @@  - net8.0 + net7.0;net8.0;net9.0 enable enable + + + EnvelopeGenerator + Digital Data GmbH + Digital Data GmbH + EnvelopeGenerator + + Envelope Generator ist eine Bibliothek zur Verwaltung und Verarbeitung digitaler Umschläge (Envelopes). + Dieses Paket enthält die Dependency-Injection-Erweiterungsmethoden und bündelt die Application- + sowie Infrastructure-Schicht in einer einzigen NuGet-Referenz. + + Copyright 2024 Digital Data GmbH + http://git.dd:3000/AppStd/EnvelopeGenerator.git + digital data envelope generator di dependency injection + false + 1.0.0 + 1.0.0 + 1.0.0 + false - - - - + + + + diff --git a/EnvelopeGenerator.sln b/EnvelopeGenerator.sln index 82a73c69..e22dbb07 100644 --- a/EnvelopeGenerator.sln +++ b/EnvelopeGenerator.sln @@ -87,8 +87,8 @@ Global {EC768913-6270-14F4-1DD3-69C87A659462}.Debug|Any CPU.Build.0 = Debug|Any CPU {EC768913-6270-14F4-1DD3-69C87A659462}.Release|Any CPU.ActiveCfg = Release|Any CPU {EC768913-6270-14F4-1DD3-69C87A659462}.Release|Any CPU.Build.0 = Release|Any CPU - {90FE0312-8C38-4347-9EA2-0A719E255D5C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {90FE0312-8C38-4347-9EA2-0A719E255D5C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {90FE0312-8C38-4347-9EA2-0A719E255D5C}.Debug|Any CPU.ActiveCfg = Release|Any CPU + {90FE0312-8C38-4347-9EA2-0A719E255D5C}.Debug|Any CPU.Build.0 = Release|Any CPU {90FE0312-8C38-4347-9EA2-0A719E255D5C}.Release|Any CPU.ActiveCfg = Release|Any CPU {90FE0312-8C38-4347-9EA2-0A719E255D5C}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection From 7c737ee6ad849c7d818ab8dab5ba82c2a3ba9635 Mon Sep 17 00:00:00 2001 From: TekH Date: Thu, 28 May 2026 20:13:51 +0200 Subject: [PATCH 05/13] Update project versioning and dependency handling Updated project version to 1.0.1, including ``, ``, and ``. Added `all` to `` elements to prevent exposing referenced projects' assets. Introduced `IncludeDependencyDlls` and `BundleReferencedDlls` targets to include and bundle dependent project DLLs for multiple target frameworks (`net7.0`, `net8.0`, `net9.0`). Removed redundant `` entries and improved packaging to ensure proper handling of dependencies. --- ...velopeGenerator.DependencyInjection.csproj | 42 ++++++++++++++++--- 1 file changed, 36 insertions(+), 6 deletions(-) diff --git a/EnvelopeGenerator.DependencyInjection/EnvelopeGenerator.DependencyInjection.csproj b/EnvelopeGenerator.DependencyInjection/EnvelopeGenerator.DependencyInjection.csproj index 98a39ecd..e1df3bc2 100644 --- a/EnvelopeGenerator.DependencyInjection/EnvelopeGenerator.DependencyInjection.csproj +++ b/EnvelopeGenerator.DependencyInjection/EnvelopeGenerator.DependencyInjection.csproj @@ -19,9 +19,9 @@ http://git.dd:3000/AppStd/EnvelopeGenerator.git digital data envelope generator di dependency injection false - 1.0.0 - 1.0.0 - 1.0.0 + 1.0.1 + 1.0.1 + 1.0.1 false @@ -31,9 +31,39 @@ - - - + + all + + + all + + + all + + + + + <_DepDlls Include=" + ..\EnvelopeGenerator.Application\bin\$(Configuration)\%(ProjectReference.TargetFramework)\EnvelopeGenerator.Application.dll; + ..\EnvelopeGenerator.Domain\bin\$(Configuration)\%(ProjectReference.TargetFramework)\EnvelopeGenerator.Domain.dll; + ..\EnvelopeGenerator.Infrastructure\bin\$(Configuration)\%(ProjectReference.TargetFramework)\EnvelopeGenerator.Infrastructure.dll" /> + + + + + + + + + + + + + + + + + From bc4905d2f4ab6580f89e577c16cc99b83096d3a3 Mon Sep 17 00:00:00 2001 From: TekH Date: Thu, 28 May 2026 20:23:14 +0200 Subject: [PATCH 06/13] Refactor DI setup and simplify service registration Centralized dependency injection setup by adding a reference to `EnvelopeGenerator.DependencyInjection` in the project file and replacing multiple `using` directives with a single one. Replaced obsolete `AddEnvelopeGeneratorInfrastructureServices` and `AddEnvelopeGeneratorServices` methods with the new `AddEnvelopeGenerator` method, consolidating service and infrastructure setup. Encapsulated `EGDbContext` configuration within `AddEnvelopeGenerator` and removed obsolete `#pragma` directives. Simplified mail service registration by replacing manual `IEnvelopeMailService` setup with `AddEnvelopeMailService`. These changes improve maintainability, reduce redundancy, and modernize the codebase. --- .../EnvelopeGenerator.Web.csproj | 1 + EnvelopeGenerator.Web/Program.cs | 35 +++++++------------ 2 files changed, 13 insertions(+), 23 deletions(-) diff --git a/EnvelopeGenerator.Web/EnvelopeGenerator.Web.csproj b/EnvelopeGenerator.Web/EnvelopeGenerator.Web.csproj index 6c0e5d59..d0071918 100644 --- a/EnvelopeGenerator.Web/EnvelopeGenerator.Web.csproj +++ b/EnvelopeGenerator.Web/EnvelopeGenerator.Web.csproj @@ -2175,6 +2175,7 @@ + diff --git a/EnvelopeGenerator.Web/Program.cs b/EnvelopeGenerator.Web/Program.cs index 4e158971..c4b2b521 100644 --- a/EnvelopeGenerator.Web/Program.cs +++ b/EnvelopeGenerator.Web/Program.cs @@ -1,4 +1,3 @@ -using EnvelopeGenerator.Application.Services; using Microsoft.EntityFrameworkCore; using NLog; using Quartz; @@ -9,14 +8,13 @@ using EnvelopeGenerator.Web.Models; using System.Text.Encodings.Web; using Ganss.Xss; using Microsoft.Extensions.Options; -using EnvelopeGenerator.Application; using DigitalData.EmailProfilerDispatcher; using EnvelopeGenerator.Infrastructure; using EnvelopeGenerator.Web.Sanitizers; using EnvelopeGenerator.Web.Models.Annotation; using DigitalData.UserManager.DependencyInjection; using EnvelopeGenerator.Web.Middleware; -using EnvelopeGenerator.Application.Common.Interfaces.Services; +using EnvelopeGenerator.DependencyInjection; using EnvelopeGenerator.Web; var logger = LogManager.Setup().LoadConfigurationFromAppSettings().GetCurrentClassLogger(); @@ -103,25 +101,18 @@ try }); // Add envelope generator services -#pragma warning disable CS0618 // Type or member is obsolete - builder.Services.AddEnvelopeGeneratorInfrastructureServices( - opt => + builder.Services.AddEnvelopeGenerator(config, opt => + { + opt.AddDbTriggerParams(config); + opt.AddDbContext((provider, options) => { - opt.AddDbTriggerParams(config); - opt.AddDbContext((provider, options) => - { - var logger = provider.GetRequiredService>(); - options.UseSqlServer(connStr) - .LogTo(log => logger.LogInformation("{log}", log), Microsoft.Extensions.Logging.LogLevel.Trace) - .EnableSensitiveDataLogging() - .EnableDetailedErrors(); - }); + var logger = provider.GetRequiredService>(); + options.UseSqlServer(connStr) + .LogTo(log => logger.LogInformation("{log}", log), Microsoft.Extensions.Logging.LogLevel.Trace) + .EnableSensitiveDataLogging() + .EnableDetailedErrors(); }); -#pragma warning restore CS0618 // Type or member is obsolete - -#pragma warning disable CS0618 // Type or member is obsolete - builder.Services.AddEnvelopeGeneratorServices(config); -#pragma warning restore CS0618 // Type or member is obsolete + }); builder.Services.Configure(options => { @@ -169,9 +160,7 @@ try builder.Services.AddSingleton(sp => sp.GetRequiredService>().Value); // Register mail services -#pragma warning disable CS0618 // Type or member is obsolete - builder.Services.AddScoped(); -#pragma warning restore CS0618 // Type or member is obsolete + builder.Services.AddEnvelopeMailService(); builder.Services.AddDispatcher(); From 0a4daccc0f6a7276c7deba92b6a471ac1acbb3db Mon Sep 17 00:00:00 2001 From: TekH Date: Thu, 28 May 2026 21:57:03 +0200 Subject: [PATCH 07/13] Refactor service registration for modularity Introduced `EnvelopeGeneratorOptions` and `SqlCacheOptions` to enable fine-grained control over optional service registrations in `AddEnvelopeGenerator`. Updated `AddEnvelopeGenerator` to conditionally register services like `HttpContextAccessor`, `DistributedSqlServerCache`, `Dispatcher`, `MemoryCache`, and `UserManager` based on these options. Updated `DependencyInjection.csproj` to include necessary framework references and package dependencies. Simplified `Program.cs` by consolidating service registrations into `AddEnvelopeGenerator`, reducing boilerplate and improving maintainability. Improved extensibility by centralizing service registration logic, allowing consuming projects to customize configurations without modifying the core library. Updated documentation and removed unused directives. --- .../DependencyInjection.cs | 123 ++++++++++++------ ...velopeGenerator.DependencyInjection.csproj | 19 +++ EnvelopeGenerator.Web/Program.cs | 48 +++---- 3 files changed, 119 insertions(+), 71 deletions(-) diff --git a/EnvelopeGenerator.DependencyInjection/DependencyInjection.cs b/EnvelopeGenerator.DependencyInjection/DependencyInjection.cs index cebe6df9..8bbbc853 100644 --- a/EnvelopeGenerator.DependencyInjection/DependencyInjection.cs +++ b/EnvelopeGenerator.DependencyInjection/DependencyInjection.cs @@ -4,12 +4,59 @@ using EnvelopeGenerator.Application; using EnvelopeGenerator.Application.Common.Interfaces.Services; using EnvelopeGenerator.Application.Services; using EnvelopeGenerator.Infrastructure; +using DigitalData.EmailProfilerDispatcher; +using DigitalData.UserManager.DependencyInjection; namespace EnvelopeGenerator.DependencyInjection; +/// +/// Controls which optional services are registered by . +/// All flags default to true. Set a flag to false if the consuming project +/// already registers that service itself or simply does not need it. +/// +public sealed class EnvelopeGeneratorOptions +{ + /// Calls AddHttpContextAccessor(). Default: true. + public bool AddHttpContextAccessor { get; set; } = true; + + /// + /// Calls AddDistributedSqlServerCache() with the supplied . + /// Requires to be configured. Default: true. + /// + public bool AddDistributedSqlServerCache { get; set; } = true; + + /// + /// Options for the distributed SQL Server cache. + /// Required when is true. + /// + public SqlCacheOptions? SqlCacheOptions { get; set; } + + /// Calls AddDispatcher<TDbContext>(). Default: true. + public bool AddDispatcher { get; set; } = true; + + /// Calls AddMemoryCache(). Default: true. + public bool AddMemoryCache { get; set; } = true; + + /// Calls AddUserManager<TDbContext>(). Default: true. + public bool AddUserManager { get; set; } = true; +} + +/// Options for AddDistributedSqlServerCache. +public sealed class SqlCacheOptions +{ + /// SQL Server connection string. + public string ConnectionString { get; set; } = string.Empty; + + /// Schema name. Default: dbo. + public string SchemaName { get; set; } = "dbo"; + + /// Table name. Default: TBDD_CACHE. + public string TableName { get; set; } = "TBDD_CACHE"; +} + /// /// Extension methods for registering EnvelopeGenerator services into an . -/// Use as the single entry-point for projects that need both the +/// Use as the single entry-point for projects that need both the /// application layer (MediatR, AutoMapper, CRUD services, configuration sections) and the infrastructure /// layer (repositories, DbContext, SQL executors). /// For projects that do not need a database (e.g. lightweight API gateways or unit-test hosts), use @@ -18,61 +65,56 @@ namespace EnvelopeGenerator.DependencyInjection; public static class DependencyInjection { /// - /// Registers the full EnvelopeGenerator stack – application and infrastructure services – into - /// the provided . - /// - /// Internally this calls AddEnvelopeGeneratorServices (application layer) and - /// AddEnvelopeGeneratorInfrastructureServices (infrastructure layer). - /// A and / or DbTriggerParams must be - /// configured through ; without it no database connection will - /// be established at runtime. - /// + /// Registers the full EnvelopeGenerator stack using as the DbContext type. /// - /// Service collection to register services into. - /// - /// Application configuration. Used to bind DispatcherParams, MailParams, - /// AuthenticatorParams, TotpSmsParams, GtxMessagingParams and other - /// application-level option sections. - /// - /// - /// Optional callback to configure the infrastructure layer registration. - /// Typical usage: - /// - /// services.AddEnvelopeGenerator(config, opt => - /// { - /// opt.AddDbContext(o => o.UseSqlServer(connectionString)); - /// opt.AddDbTriggerParams(config); - /// }); - /// - /// - /// The updated . -#pragma warning disable CS0618 // AddEnvelopeGeneratorServices / AddEnvelopeGeneratorInfrastructureServices are intentionally wrapped here public static IServiceCollection AddEnvelopeGenerator( this IServiceCollection services, IConfiguration configuration, - Action? infrastructureOptions = null) + Action? infrastructureOptions = null, + Action? options = null) { + var opt = new EnvelopeGeneratorOptions(); + options?.Invoke(opt); + +#pragma warning disable CS0618 // Application layer: CRUD services, MediatR, AutoMapper, configuration sections. services.AddEnvelopeGeneratorServices(configuration); // Infrastructure layer: repositories, DbContext, Dapper type maps, SQL executors. - services.AddEnvelopeGeneratorInfrastructureServices(opt => + services.AddEnvelopeGeneratorInfrastructureServices(cfg => { - infrastructureOptions?.Invoke(opt); + infrastructureOptions?.Invoke(cfg); }); +#pragma warning restore CS0618 + + if (opt.AddHttpContextAccessor) + services.AddHttpContextAccessor(); + + if (opt.AddDistributedSqlServerCache && opt.SqlCacheOptions is { } cacheOpts) + services.AddDistributedSqlServerCache(o => + { + o.ConnectionString = cacheOpts.ConnectionString; + o.SchemaName = cacheOpts.SchemaName; + o.TableName = cacheOpts.TableName; + }); + + if (opt.AddDispatcher) + services.AddDispatcher(); + + if (opt.AddMemoryCache) + services.AddMemoryCache(); + +#pragma warning disable CS0618 + if (opt.AddUserManager) + services.AddUserManager(); +#pragma warning restore CS0618 return services; } -#pragma warning restore CS0618 /// /// Registers only the application layer services (MediatR handlers, AutoMapper profiles, /// CRUD services, configuration sections) without any infrastructure / database dependencies. - /// - /// Useful for projects that already manage their own DbContext or do not require direct database - /// access, such as lightweight API gateways, console tools or unit/integration test hosts that - /// use an in-memory database configured elsewhere. - /// /// /// Service collection to register services into. /// Application configuration used to bind application-level option sections. @@ -90,11 +132,6 @@ public static class DependencyInjection /// /// Registers as the scoped /// implementation. - /// - /// Call this in addition to when the consuming project needs to - /// send envelope e-mails directly (e.g. a Worker Service or the Web project). Projects that rely - /// purely on MediatR commands to trigger mail delivery do not need to call this. - /// /// /// Service collection to register services into. /// The updated . diff --git a/EnvelopeGenerator.DependencyInjection/EnvelopeGenerator.DependencyInjection.csproj b/EnvelopeGenerator.DependencyInjection/EnvelopeGenerator.DependencyInjection.csproj index e1df3bc2..96e2398e 100644 --- a/EnvelopeGenerator.DependencyInjection/EnvelopeGenerator.DependencyInjection.csproj +++ b/EnvelopeGenerator.DependencyInjection/EnvelopeGenerator.DependencyInjection.csproj @@ -25,9 +25,28 @@ false + + + + + + + + + + + + + + + + + + + diff --git a/EnvelopeGenerator.Web/Program.cs b/EnvelopeGenerator.Web/Program.cs index c4b2b521..f25a9888 100644 --- a/EnvelopeGenerator.Web/Program.cs +++ b/EnvelopeGenerator.Web/Program.cs @@ -12,7 +12,6 @@ using DigitalData.EmailProfilerDispatcher; using EnvelopeGenerator.Infrastructure; using EnvelopeGenerator.Web.Sanitizers; using EnvelopeGenerator.Web.Models.Annotation; -using DigitalData.UserManager.DependencyInjection; using EnvelopeGenerator.Web.Middleware; using EnvelopeGenerator.DependencyInjection; using EnvelopeGenerator.Web; @@ -55,8 +54,6 @@ try }); }); - builder.Services.AddHttpContextAccessor(); - builder.ConfigureBySection(); // Add controllers and razor views @@ -93,26 +90,29 @@ try var connStr = config.GetConnectionString(cnnStrName) ?? throw new InvalidOperationException($"Connection string '{cnnStrName}' is missing in the application configuration."); - builder.Services.AddDistributedSqlServerCache(options => - { - options.ConnectionString = connStr; - options.SchemaName = "dbo"; - options.TableName = "TBDD_CACHE"; - }); - // Add envelope generator services - builder.Services.AddEnvelopeGenerator(config, opt => - { - opt.AddDbTriggerParams(config); - opt.AddDbContext((provider, options) => + builder.Services.AddEnvelopeGenerator(config, + infrastructureOptions: opt => { - var logger = provider.GetRequiredService>(); - options.UseSqlServer(connStr) - .LogTo(log => logger.LogInformation("{log}", log), Microsoft.Extensions.Logging.LogLevel.Trace) - .EnableSensitiveDataLogging() - .EnableDetailedErrors(); + opt.AddDbTriggerParams(config); + opt.AddDbContext((provider, options) => + { + var logger = provider.GetRequiredService>(); + options.UseSqlServer(connStr) + .LogTo(log => logger.LogInformation("{log}", log), Microsoft.Extensions.Logging.LogLevel.Trace) + .EnableSensitiveDataLogging() + .EnableDetailedErrors(); + }); + }, + options: opt => + { + opt.SqlCacheOptions = new() + { + ConnectionString = connStr, + SchemaName = "dbo", + TableName = "TBDD_CACHE" + }; }); - }); builder.Services.Configure(options => { @@ -162,18 +162,10 @@ try // Register mail services builder.Services.AddEnvelopeMailService(); - builder.Services.AddDispatcher(); - - builder.Services.AddMemoryCache(); - builder.ConfigureBySection(); builder.ConfigureBySection(); -#pragma warning disable CS0618 // Type or member is obsolete - builder.Services.AddUserManager(); -#pragma warning restore CS0618 // Type or member is obsolete - var app = builder.Build(); app.UseMiddleware(); From 750b9f1b57806761c741925b75463460dd162ac1 Mon Sep 17 00:00:00 2001 From: TekH Date: Thu, 28 May 2026 21:57:19 +0200 Subject: [PATCH 08/13] Bump project version to 1.1.0 Updated the project version from 1.0.1 to 1.1.0 in the `EnvelopeGenerator.DependencyInjection.csproj` file. This includes changes to the ``, ``, and `` properties, reflecting the addition of new features or improvements. --- .../EnvelopeGenerator.DependencyInjection.csproj | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/EnvelopeGenerator.DependencyInjection/EnvelopeGenerator.DependencyInjection.csproj b/EnvelopeGenerator.DependencyInjection/EnvelopeGenerator.DependencyInjection.csproj index 96e2398e..0c0d35c2 100644 --- a/EnvelopeGenerator.DependencyInjection/EnvelopeGenerator.DependencyInjection.csproj +++ b/EnvelopeGenerator.DependencyInjection/EnvelopeGenerator.DependencyInjection.csproj @@ -19,9 +19,9 @@ http://git.dd:3000/AppStd/EnvelopeGenerator.git digital data envelope generator di dependency injection false - 1.0.1 - 1.0.1 - 1.0.1 + 1.1.0 + 1.1.0 + 1.1.0 false From 823bafeeb98f79d37993614b688ea311f992fd42 Mon Sep 17 00:00:00 2001 From: TekH Date: Thu, 28 May 2026 22:50:45 +0200 Subject: [PATCH 09/13] Refactor project dependencies and add TFM-specific packages Restructured `EnvelopeGenerator.DependencyInjection.csproj` to: - Add multiple `PackageReference` entries for application services, ORM/Database, security/identity, utilities, and DI abstractions. - Introduce conditional `ItemGroup` sections for `net7.0`, `net8.0`, and `net9.0` with framework-specific package versions. - Move `UserManager` package reference to align with the updated dependency structure. - Update comments for clarity, including replacing a Turkish comment with an English one. - Add a comment explaining the rationale for centralizing `PackageReference` declarations to ensure correct `.nuspec` generation and simplify consumption. --- ...velopeGenerator.DependencyInjection.csproj | 58 ++++++++++++++++++- 1 file changed, 56 insertions(+), 2 deletions(-) diff --git a/EnvelopeGenerator.DependencyInjection/EnvelopeGenerator.DependencyInjection.csproj b/EnvelopeGenerator.DependencyInjection/EnvelopeGenerator.DependencyInjection.csproj index 0c0d35c2..313234b6 100644 --- a/EnvelopeGenerator.DependencyInjection/EnvelopeGenerator.DependencyInjection.csproj +++ b/EnvelopeGenerator.DependencyInjection/EnvelopeGenerator.DependencyInjection.csproj @@ -30,23 +30,77 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + @@ -61,7 +115,7 @@ - + <_DepDlls Include=" From 67e6f288ebfb65cb6fd8a1cae529a1394425555f Mon Sep 17 00:00:00 2001 From: TekH Date: Thu, 28 May 2026 22:52:40 +0200 Subject: [PATCH 10/13] Bump version to 1.1.1 Updated project version from 1.1.0 to 1.1.1 in `EnvelopeGenerator.DependencyInjection.csproj`. This includes changes to ``, ``, and `` properties. The update reflects minor improvements or bug fixes while maintaining backward compatibility. --- .../EnvelopeGenerator.DependencyInjection.csproj | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/EnvelopeGenerator.DependencyInjection/EnvelopeGenerator.DependencyInjection.csproj b/EnvelopeGenerator.DependencyInjection/EnvelopeGenerator.DependencyInjection.csproj index 313234b6..ed6a04dd 100644 --- a/EnvelopeGenerator.DependencyInjection/EnvelopeGenerator.DependencyInjection.csproj +++ b/EnvelopeGenerator.DependencyInjection/EnvelopeGenerator.DependencyInjection.csproj @@ -19,9 +19,9 @@ http://git.dd:3000/AppStd/EnvelopeGenerator.git digital data envelope generator di dependency injection false - 1.1.0 - 1.1.0 - 1.1.0 + 1.1.1 + 1.1.1 + 1.1.1 false From bfae72529c048b3cef0f24a3c121a5bfcb76dec6 Mon Sep 17 00:00:00 2001 From: TekH Date: Thu, 28 May 2026 23:46:31 +0200 Subject: [PATCH 11/13] Add query for sensitive envelope receiver data Introduced `ReadEnvelopeReceiverSecretQuery` to fetch sensitive fields (e.g., access code, phone number) for envelope receivers. Added extension methods for dispatching the query via `IMediator` and implemented `ReadEnvelopeReceiverSecretQueryHandler` to process the query using repositories and AutoMapper. Updated `EnvelopeController` with a new HTTP GET endpoint `EnvelopeReceiverWithSecretByMediatr` to expose the query functionality. This endpoint returns sensitive data as `EnvelopeReceiverSecretDto` or a 404 response if no match is found. These changes improve modularity, testability, and separation of concerns by leveraging MediatR and CQRS patterns. --- .../ReadEnvelopeReceiverSecretQuery.cs | 127 ++++++++++++++++++ .../Controllers/EnvelopeController.cs | 6 + 2 files changed, 133 insertions(+) create mode 100644 EnvelopeGenerator.Application/EnvelopeReceivers/Queries/ReadEnvelopeReceiverSecretQuery.cs diff --git a/EnvelopeGenerator.Application/EnvelopeReceivers/Queries/ReadEnvelopeReceiverSecretQuery.cs b/EnvelopeGenerator.Application/EnvelopeReceivers/Queries/ReadEnvelopeReceiverSecretQuery.cs new file mode 100644 index 00000000..e9fd1c20 --- /dev/null +++ b/EnvelopeGenerator.Application/EnvelopeReceivers/Queries/ReadEnvelopeReceiverSecretQuery.cs @@ -0,0 +1,127 @@ +using AutoMapper; +using DigitalData.Core.Abstraction.Application.Repository; +using EnvelopeGenerator.Application.Envelopes.Queries; +using EnvelopeGenerator.Application.Receivers.Queries; +using MediatR; +using EnvelopeGenerator.Domain.Entities; +using Microsoft.EntityFrameworkCore; +using EnvelopeGenerator.Application.Common.Dto.EnvelopeReceiver; +using EnvelopeGenerator.Application.Common.Query; +using EnvelopeGenerator.Application.Common.Extensions; + +namespace EnvelopeGenerator.Application.EnvelopeReceivers.Queries; + +/// +/// Represents a query for reading an envelope receiver including sensitive fields +/// (access code, phone number) that are excluded from the standard . +/// +/// +/// Returns a single matched by UUID and receiver signature. +/// Equivalent to the legacy ReadWithSecretByUuidSignatureAsync service method. +/// +public record ReadEnvelopeReceiverSecretQuery + : EnvelopeReceiverQueryBase, + IRequest; + +/// +/// Extension methods for dispatching via . +/// +public static class ReadEnvelopeReceiverSecretQueryExtensions +{ + /// + /// Sends a using the composite key (uuid::signature). + /// + /// The mediator instance. + /// Composite key in the format uuid::signature. + /// Cancellation token. + /// The matching , or null if not found. + public static Task ReadEnvelopeReceiverSecretAsync( + this IMediator mediator, + string key, + CancellationToken cancel = default) + => mediator.Send(new ReadEnvelopeReceiverSecretQuery { Key = key }, cancel); + + /// + /// Sends a using UUID and receiver signature. + /// + /// The mediator instance. + /// Envelope UUID. + /// Receiver signature. + /// Cancellation token. + /// The matching , or null if not found. + public static Task ReadEnvelopeReceiverSecretAsync( + this IMediator mediator, + string uuid, + string signature, + CancellationToken cancel = default) + { + var q = new ReadEnvelopeReceiverSecretQuery(); + q.Envelope.Uuid = uuid; + q.Receiver.Signature = signature; + return mediator.Send(q, cancel); + } + + /// + /// Handles and returns a + /// containing sensitive fields. + /// + public class ReadEnvelopeReceiverSecretQueryHandler + : IRequestHandler + { + private readonly IRepository _repo; + private readonly IRepository _rcvRepo; + private readonly IMapper _mapper; + + /// + /// Initializes a new instance of . + /// + /// Repository for . + /// Repository for . + /// AutoMapper instance. + public ReadEnvelopeReceiverSecretQueryHandler( + IRepository envelopeReceiver, + IRepository rcvRepo, + IMapper mapper) + { + _repo = envelopeReceiver; + _rcvRepo = rcvRepo; + _mapper = mapper; + } + + /// + /// Handles the query and returns the matching . + /// + /// The query containing filter criteria. + /// Cancellation token. + /// + /// The matched , or null if no record is found. + /// + public async Task Handle( + ReadEnvelopeReceiverSecretQuery request, + CancellationToken cancel) + { + var q = _repo.Query.Where(request, notnull: false); + + var envRcvs = await q + .Include(er => er.Envelope).ThenInclude(e => e!.Documents!).ThenInclude(d => d.Elements) + .Include(er => er.Envelope).ThenInclude(e => e!.Histories) + .Include(er => er.Envelope).ThenInclude(e => e!.User) + .Include(er => er.Receiver) + .ToListAsync(cancel); + + if (request.Receiver.HasAnyCriteria && envRcvs.Count != 0) + { + var receiver = await _rcvRepo.Query.Where(request.Receiver).FirstAsync(cancel); + + foreach (var item in envRcvs) + item.Envelope?.Documents?.FirstOrDefault()?.Elements?.RemoveAll(s => s.ReceiverId != receiver.Id); + } + + var envRcv = envRcvs.FirstOrDefault(); + if (envRcv is null) + return null; + + return _mapper.Map(envRcv); + } + } +} diff --git a/EnvelopeGenerator.Web/Controllers/EnvelopeController.cs b/EnvelopeGenerator.Web/Controllers/EnvelopeController.cs index e8068bd2..4fc4f10c 100644 --- a/EnvelopeGenerator.Web/Controllers/EnvelopeController.cs +++ b/EnvelopeGenerator.Web/Controllers/EnvelopeController.cs @@ -438,4 +438,10 @@ public class EnvelopeController : ViewControllerBase return this.ViewDocumentNotFound(); } } + + [HttpGet("EnvelopeReceiverWithSecretByMediatr")] + public async Task EnvelopeReceiverWithSecretByMediatr([FromQuery] ReadEnvelopeReceiverSecretQuery q, CancellationToken cancel) + { + return await _mediator.Send(q, cancel) is EnvelopeReceiverSecretDto dto ? Ok(dto) : NotFound(); + } } \ No newline at end of file From 32fbf782fa3c9da0e356dc0cbbf230828ce5e271 Mon Sep 17 00:00:00 2001 From: TekH Date: Thu, 28 May 2026 23:47:02 +0200 Subject: [PATCH 12/13] Update project version to 1.2.0 Bump the project version from 1.1.1 to 1.2.0 in the `EnvelopeGenerator.DependencyInjection.csproj` file. Updated the ``, ``, and `` properties to reflect the new version. --- .../EnvelopeGenerator.DependencyInjection.csproj | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/EnvelopeGenerator.DependencyInjection/EnvelopeGenerator.DependencyInjection.csproj b/EnvelopeGenerator.DependencyInjection/EnvelopeGenerator.DependencyInjection.csproj index ed6a04dd..6e02c254 100644 --- a/EnvelopeGenerator.DependencyInjection/EnvelopeGenerator.DependencyInjection.csproj +++ b/EnvelopeGenerator.DependencyInjection/EnvelopeGenerator.DependencyInjection.csproj @@ -19,9 +19,9 @@ http://git.dd:3000/AppStd/EnvelopeGenerator.git digital data envelope generator di dependency injection false - 1.1.1 - 1.1.1 - 1.1.1 + 1.2.0 + 1.2.0 + 1.2.0 false From a7ed9be1de36372021cfa44c35a1f0cf460be756 Mon Sep 17 00:00:00 2001 From: TekH Date: Fri, 29 May 2026 08:45:56 +0200 Subject: [PATCH 13/13] Update version and improve build process for packaging Updated project version to 1.2.0.3 in `EnvelopeGenerator.DependencyInjection.csproj`. Replaced line endings in `_DepDlls` for consistency. Added a new `RebuildDependenciesBeforePack` target to ensure all dependencies are rebuilt for `net7.0`, `net8.0`, and `net9.0` before packaging. Improved formatting in `BundleReferencedDlls` for better readability. --- ...velopeGenerator.DependencyInjection.csproj | 60 +++++++++++++++---- 1 file changed, 47 insertions(+), 13 deletions(-) diff --git a/EnvelopeGenerator.DependencyInjection/EnvelopeGenerator.DependencyInjection.csproj b/EnvelopeGenerator.DependencyInjection/EnvelopeGenerator.DependencyInjection.csproj index 6e02c254..a504ed13 100644 --- a/EnvelopeGenerator.DependencyInjection/EnvelopeGenerator.DependencyInjection.csproj +++ b/EnvelopeGenerator.DependencyInjection/EnvelopeGenerator.DependencyInjection.csproj @@ -19,9 +19,9 @@ http://git.dd:3000/AppStd/EnvelopeGenerator.git digital data envelope generator di dependency injection false - 1.2.0 - 1.2.0 - 1.2.0 + 1.2.0.3 + 1.2.0.3 + 1.2.0.3 false @@ -118,21 +118,55 @@ - <_DepDlls Include=" - ..\EnvelopeGenerator.Application\bin\$(Configuration)\%(ProjectReference.TargetFramework)\EnvelopeGenerator.Application.dll; - ..\EnvelopeGenerator.Domain\bin\$(Configuration)\%(ProjectReference.TargetFramework)\EnvelopeGenerator.Domain.dll; - ..\EnvelopeGenerator.Infrastructure\bin\$(Configuration)\%(ProjectReference.TargetFramework)\EnvelopeGenerator.Infrastructure.dll" /> + <_DepDlls Include=" ..\EnvelopeGenerator.Application\bin\$(Configuration)\%(ProjectReference.TargetFramework)\EnvelopeGenerator.Application.dll; ..\EnvelopeGenerator.Domain\bin\$(Configuration)\%(ProjectReference.TargetFramework)\EnvelopeGenerator.Domain.dll; ..\EnvelopeGenerator.Infrastructure\bin\$(Configuration)\%(ProjectReference.TargetFramework)\EnvelopeGenerator.Infrastructure.dll" /> + + + + + + + + + + + + + + + - - - - - - + + + + + +