Update to latest code and nugets packages

This commit is contained in:
2026-07-03 14:43:35 +02:00
parent 5530dc915e
commit 3a36978997
25 changed files with 339 additions and 116 deletions
+33 -25
View File
@@ -6,34 +6,42 @@
<ItemGroup>
</ItemGroup>
<ItemGroup>
<PackageVersion Include="AutoMapper" Version="16.0.0" />
<PackageVersion Include="AutoMapper" Version="16.1.1" />
<PackageVersion Include="FluentValidation" Version="12.1.1" />
<PackageVersion Include="GerstITS.Authentication.OpenId" Version="2026.2.4" />
<PackageVersion Include="GerstITS.Common" Version="2026.2.4" />
<PackageVersion Include="GerstITS.Data" Version="2026.2.4" />
<PackageVersion Include="GerstITS.Data.EntityFramework" Version="2026.2.4" />
<PackageVersion Include="GerstITS.Data.EntityFramework.PostgreSql" Version="2026.2.4" />
<PackageVersion Include="GerstITS.IoC" Version="2026.2.4" />
<PackageVersion Include="GerstITS.IoC.DotNetCore" Version="2026.2.4" />
<PackageVersion Include="GerstITS.Job" Version="2026.2.4" />
<PackageVersion Include="GerstITS.Job.Scheduling" Version="2026.2.4" />
<PackageVersion Include="GerstITS.Mapping.AutoMapper" Version="2026.2.4" />
<PackageVersion Include="GerstITS.Search" Version="2026.2.4" />
<PackageVersion Include="GerstITS.System" Version="2026.2.4" />
<PackageVersion Include="GerstITS.Validation" Version="2026.2.4" />
<PackageVersion Include="GerstITS.Web" Version="2026.2.4" />
<PackageVersion Include="GerstITS.Web.Api" Version="2026.2.4" />
<PackageVersion Include="GerstITS.Web.Api.Swagger" Version="2026.2.4" />
<PackageVersion Include="GerstITS.Web.Rest" Version="2026.2.4" />
<PackageVersion Include="GerstITS.Authentication.ApiKey" Version="2026.7.1" />
<PackageVersion Include="GerstITS.Authentication.OpenId" Version="2026.7.1" />
<PackageVersion Include="GerstITS.Common" Version="2026.7.1" />
<PackageVersion Include="GerstITS.Data" Version="2026.7.1" />
<PackageVersion Include="GerstITS.Data.EntityFramework" Version="2026.7.1" />
<PackageVersion Include="GerstITS.Data.EntityFramework.PostgreSql" Version="2026.6.8" />
<PackageVersion Include="GerstITS.Data.EntityFramework.SqlServer" Version="2026.6.3" />
<PackageVersion Include="GerstITS.IoC" Version="2026.7.1" />
<PackageVersion Include="GerstITS.IoC.DotNetCore" Version="2026.7.1" />
<PackageVersion Include="GerstITS.Job" Version="2026.6.2" />
<PackageVersion Include="GerstITS.Job.Scheduling" Version="2026.7.1" />
<PackageVersion Include="GerstITS.Mail" Version="2026.7.1" />
<PackageVersion Include="GerstITS.Mapping.AutoMapper" Version="2026.6.2" />
<PackageVersion Include="GerstITS.Search" Version="2026.7.1" />
<PackageVersion Include="GerstITS.System" Version="2026.6.8" />
<PackageVersion Include="GerstITS.TestFramework" Version="2026.7.2" />
<PackageVersion Include="GerstITS.Validation" Version="2026.7.1" />
<PackageVersion Include="GerstITS.Web" Version="2026.7.1" />
<PackageVersion Include="GerstITS.Web.Api" Version="2026.6.27" />
<PackageVersion Include="GerstITS.Web.Api.Swagger" Version="2026.7.3" />
<PackageVersion Include="GerstITS.Web.Rest" Version="2026.6.25" />
<PackageVersion Include="Hocon.Extensions.Configuration" Version="2.0.4" />
<PackageVersion Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="10.0.3" />
<PackageVersion Include="Microsoft.EntityFrameworkCore" Version="10.0.3" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Design" Version="10.0.1" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Tools" Version="10.0.3" />
<PackageVersion Include="Microsoft.Extensions.Configuration.FileExtensions" Version="10.0.3" />
<PackageVersion Include="Microsoft.Extensions.Configuration.Json" Version="10.0.3" />
<PackageVersion Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="10.0.9" />
<PackageVersion Include="Microsoft.EntityFrameworkCore" Version="10.0.9" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Design" Version="10.0.9" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Tools" Version="10.0.9" />
<PackageVersion Include="Microsoft.Extensions.Configuration.FileExtensions" Version="10.0.9" />
<PackageVersion Include="Microsoft.Extensions.Configuration.Json" Version="10.0.9" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="18.7.0" />
<PackageVersion Include="Microsoft.OpenApi" Version="2.9.0" />
<PackageVersion Include="Newtonsoft.Json" Version="13.0.4" />
<PackageVersion Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="10.0.0" />
<PackageVersion Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="10.0.2" />
<PackageVersion Include="Serilog.AspNetCore" Version="10.0.0" />
<PackageVersion Include="xunit" Version="2.9.3" />
<PackageVersion Include="xunit.runner.visualstudio" Version="3.1.5" />
</ItemGroup>
</Project>
@@ -1,4 +1,5 @@
using GerstITS.Authentication.OpenId;
using GerstITS.Authentication.ApiKey;
using GerstITS.Authentication.OpenId;
using GerstITS.Data.EntityFramework;
using GerstITS.System.Configurations;
using GerstITS.Web.Api.Builder;
@@ -11,6 +12,7 @@ internal sealed class WebApiConfiguration : GerstITS.System.Configurations.IConf
#region Properties
public IServerConfiguration Server { get; }
public IApiKeyConfiguration ApiKey { get; }
public IOpenIdConfiguration OpenId { get; }
public ISwaggerConfiguration Swagger { get; set; }
public IEntityFrameworkMigrationConfiguration EntityFrameworkMigration { get; set; }
@@ -24,7 +26,8 @@ internal sealed class WebApiConfiguration : GerstITS.System.Configurations.IConf
var prefix = this.ToConfigurationPrefix();
EntityFrameworkMigration = new EntityFrameworkMigrationConfiguration(prefix, configuration);
//OpenId = new OpenIdConfiguration(prefix, configuration);
ApiKey = new ApiKeyConfiguration(prefix, configuration);
OpenId = new OpenIdConfiguration(prefix, configuration);
Server = new ServerConfiguration(prefix, configuration);
Swagger = new SwaggerConfiguration(prefix, configuration);
}
@@ -7,14 +7,14 @@ namespace GerstITS.Examples.Api.StartupTasks;
internal class ExampleStartupTask : IStartupTask
{
#region Fields#
#region Fields
private readonly IExampleProvider _provider;
private readonly IJsonConvert _jsonConvert;
#endregion
#region Construtcors
#region Constructors
public ExampleStartupTask(IExampleProvider provider,
IJsonConvert jsonConvert)
@@ -6,7 +6,7 @@
<Copyright>© 2025 Gerst ITS</Copyright>
<Authors>Gerst ITS</Authors>
<Product>Gerst ITS Examples Web Api</Product>
<Description>Exapmle Web Api</Description>
<Description>Example Web Api</Description>
<Version>0.0.0.0</Version>
<AssemblyVersion>0.0.0.0</AssemblyVersion>
<AssemblyInformationalVersion>0.0.0.0</AssemblyInformationalVersion>
@@ -18,7 +18,7 @@
<CheckForOverflowUnderflow>true</CheckForOverflowUnderflow>
<WarningsAsErrors />
<NoWarn>1591</NoWarn>
<DocumentationFile>bin\Release\net8.0\GerstITS.Example.Api.xml</DocumentationFile>
<DocumentationFile>bin\Debug\net10.0\GerstITS.Examples.Api.xml</DocumentationFile>
<OutputPath></OutputPath>
</PropertyGroup>
@@ -27,18 +27,23 @@
<CheckForOverflowUnderflow>true</CheckForOverflowUnderflow>
<WarningsAsErrors />
<NoWarn>1591</NoWarn>
<DocumentationFile>bin\Release\net8.0\GerstITS.Example.Api.xml</DocumentationFile>
<DocumentationFile>bin\Release\net10.0\GerstITS.Examples.Api.xml</DocumentationFile>
<OutputPath></OutputPath>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="GerstITS.Authentication.ApiKey" />
<PackageReference Include="GerstITS.Authentication.OpenId" />
<PackageReference Include="GerstITS.Data.EntityFramework" />
<PackageReference Include="GerstITS.Mail" />
<PackageReference Include="GerstITS.System" />
<PackageReference Include="GerstITS.Web" />
<PackageReference Include="GerstITS.Web.Api.Swagger" />
<PackageReference Include="Serilog.AspNetCore" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\GerstITS.Examples.Data\GerstITS.Examples.Data.csproj" />
<ProjectReference Include="..\GerstITS.Examples.Logic\GerstITS.Examples.Logic.csproj" />
</ItemGroup>
@@ -11,6 +11,7 @@ public sealed partial class Module
container.AddSingleton<WebApiConfiguration>();
container.AddSingleton(c => c.GetService<WebApiConfiguration>().EntityFrameworkMigration);
container.AddSingleton(c => c.GetService<WebApiConfiguration>().ApiKey);
container.AddSingleton(c => c.GetService<WebApiConfiguration>().OpenId);
container.AddSingleton(c => c.GetService<WebApiConfiguration>().Server);
container.AddSingleton(c => c.GetService<WebApiConfiguration>().Swagger);
+1
View File
@@ -10,6 +10,7 @@ public sealed partial class Module : IIoCModule<IServiceCollection>
{
RegisterConfigurations(container);
RegisterExceptionHandling(container);
RegisterSession(container);
RegisterStartupTasks(container);
}
+1
View File
@@ -31,6 +31,7 @@ public class Program
.UseAuthentication()
.UseAuthorization()
.UseRouting()
.UseSession()
.UseEndpoints(endpoints => endpoints.MapControllers())
.UseRewriteUnknownPathsToIndexSite(ApplicationEnvironment.WebApi.BaseUrl)
.UseSystemIndependentStaticFiles()
+17 -1
View File
@@ -7,7 +7,23 @@
}
},
"AllowedHosts": "*",
"ConnectionStrings": {
"CustomerDbContext": "Host=localhost;Port=5432;Database=gerstits_examples;Username=postgres;Password=postgres"
},
"Mail": {
"SmtpServer": "smtp.example.com",
"SmtpPort": 587,
"SenderDisplayName": "Gerst ITS Examples",
"SenderAddress": "noreply@example.com",
"Username": "noreply@example.com",
"Password": "change-me",
"UseSsl": true
},
"WebApi": {
"ApiKey": {
"Header": "X-Api-Key",
"Key": "example-api-key"
},
"Swagger": {
"SupportEMail": "support@example.com",
"TermsOfService": "https://www.example.com/impressum/",
@@ -16,7 +32,7 @@
"Url": "https://opensource.org/licenses/MIT"
}
},
"EntityFrameworkmigration": {
"EntityFrameworkMigration": {
"AutoMigrate": true
},
"Server": {
@@ -16,7 +16,7 @@ public class SayHelloWorldJob : JobBase
#endregion
#region Cosntructors
#region Constructors
public SayHelloWorldJob(SayHelloWorldJobConfiguration configuration,
ISystemClock systemClock)
@@ -15,7 +15,7 @@ public class SayHelloWorldWithDefaultNameUsageJob : JobBase
#endregion
#region Cosntructors
#region Constructors
public SayHelloWorldWithDefaultNameUsageJob(SayHelloWorldWithDefaultNameUsageJobConfiguration configuration)
{
@@ -13,7 +13,8 @@ public sealed class Module : IIoCModule<IServiceCollection>
public void RegisterComponents(IServiceCollection container)
{
container.RegisterJob<SayHelloWorldJob, SayHelloWorldJobConfiguration>();
}
container.RegisterJob<SayHelloWorldWithDefaultNameUsageJob, SayHelloWorldWithDefaultNameUsageJobConfiguration>(IgnoreConditions.EntityFramework, IgnoreConditions.Swagger);
}
#endregion
}
@@ -4,7 +4,7 @@ namespace GerstITS.Examples.Logic.Example;
internal sealed class IntegerMapping : Profile
{
#region Construtcors
#region Constructors
public IntegerMapping()
{
@@ -31,9 +31,19 @@
<PackageReference Include="GerstITS.IoC" />
<PackageReference Include="GerstITS.Mapping.AutoMapper" />
<PackageReference Include="GerstITS.Search" />
<PackageReference Include="GerstITS.System" />
<PackageReference Include="GerstITS.Validation" />
<PackageReference Include="GerstITS.Web.Api" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\GerstITS.Examples.Data\GerstITS.Examples.Data.csproj" />
</ItemGroup>
<ItemGroup>
<InternalsVisibleTo Include="GerstITS.Examples.Tests" />
</ItemGroup>
<ItemGroup>
<ProjectCapability Include="ConfigurableFileNesting" />
<ProjectCapability Include="ConfigurableFileNestingFeatureEnabled" />
+2 -1
View File
@@ -9,9 +9,10 @@ public sealed partial class Module : IIoCModule<IServiceCollection>
public void RegisterComponents(IServiceCollection container)
{
RegisterCustomers(container);
RegisterExample(container);
RegisterShared(container);
}
}
#endregion
}
@@ -4,7 +4,7 @@ using GerstITS.Data;
namespace GerstITS.Examples.Logic.Shared;
internal static class ISearchEngineExtensions
internal static class IReadOnlyRepositoryExtensions
{
#region Methods
@@ -41,9 +41,10 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="GerstITS.Common" />
<PackageReference Include="GerstITS.System" />
<PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" />
</ItemGroup>
<ItemGroup>
@@ -12,6 +12,7 @@ public class Module : IIoCModule<IServiceCollection>
public void RegisterComponents(IServiceCollection container)
{
container.AddTransient<IApplicationStart, CommonFeaturesRunner>();
container.AddTransient<IApplicationStart, TestRunner>();
container.AddTransient<IConfiguration>(c => new ConfigurationBuilder().SetBasePath(AppDomain.CurrentDomain.BaseDirectory)
@@ -1,4 +1,4 @@
using GerstITS.Examples.WebClients.Examples.Api;
using GerstITS.Examples.WebClients.Examples.Api;
using GerstITS.IoC.DotNetCore;
using GerstITS.Web.WebClients;
@@ -12,37 +12,55 @@ internal sealed class TestRunner : IApplicationStart
#endregion
#region Construtors
#region Constructors
public TestRunner(IWebClient webClient)
{
_webClient = webClient;
}
}
#endregion
#region ITestRunner
#region IApplicationStart
public void Run()
{
var result1 = _webClient.Request<ICountry>()
.Execute(c => c.Search(new SearchCriteria
{ SortBy = nameof(Country.Name), SortDirection = SortingDirections.Descending, Skip = 5, Take = 5}));
var created = _webClient.Request<ICustomer>()
.Execute(c => c.Create(new Customer
{ FirstName = "Erika", LastName = $"Mustermann-{Guid.NewGuid():N}", EMail = "erika.mustermann@example.com" }));
var result2 = _webClient.Request<ICountry>()
.Execute(c => c.Get(result1.Value.Result.First().Id));
var loaded = _webClient.Request<ICustomer>()
.Execute(c => c.Get(created.Value.Id));
var test3 = _webClient.Request<ICountry>()
.Execute(c => c.Create(new Country {Name = $"Country-{Guid.NewGuid()}"}));
var searched = _webClient.Request<ICustomer>()
.Execute(c => c.Search(new CustomerSearchCriteria
{ Name = "Mustermann", SortBy = nameof(Customer.LastName), SortDirection = SortingDirections.Descending, Skip = 0, Take = 5 }));
test3.Value.Name += "_Renamed";
loaded.Value.FirstName = "Max";
var test4 = _webClient.Request<ICountry>()
.Execute(c => c.Update(test3.Value));
var updated = _webClient.Request<ICustomer>()
.Execute(c => c.Update(loaded.Value));
var note = _webClient.Request<ICustomer>()
.Execute(c => c.AddNote(updated.Value.Id, new CustomerNote { Text = "Created by the example web client." }));
var notes = _webClient.Request<ICustomer>()
.Execute(c => c.GetNotes(updated.Value.Id));
var deleted = _webClient.Request<ICustomer>()
.Execute(c => c.Delete(updated.Value.Id));
Print($"---> {nameof(TestRunner)}: Found {searched.Value.TotalCount} customer(s), added {notes.Value.Count()} note(s), deleted: {deleted.Value}");
}
var test5 = _webClient.Request<ICountry>()
.Execute(c => c.Delete(test3.Value.Id));
}
#endregion
}
#region Methods
private static void Print(string message)
{
global::System.Console.WriteLine(message);
}
#endregion
}
@@ -8,6 +8,6 @@
},
"AllowedHosts": "*",
"ExampleApiClient": {
"BaseUrl": "https://localhost:44350/api/v1.1/"
"BaseUrl": "https://localhost:44350/api/"
}
}
+72
View File
@@ -19,32 +19,104 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
Directory.Packages.props = Directory.Packages.props
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GerstITS.Examples.Data", "GerstITS.Examples.Data\GerstITS.Examples.Data.csproj", "{BE4FCB29-7B1E-4559-B6F0-F8F5A1BEBF44}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GerstITS.Examples.Tests", "GerstITS.Examples.Tests\GerstITS.Examples.Tests.csproj", "{1F71C429-A9B3-46C2-BDEE-8F8413765EB5}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{417B5C77-05BF-4562-9A1A-AEE0531B59C1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{417B5C77-05BF-4562-9A1A-AEE0531B59C1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{417B5C77-05BF-4562-9A1A-AEE0531B59C1}.Debug|x64.ActiveCfg = Debug|Any CPU
{417B5C77-05BF-4562-9A1A-AEE0531B59C1}.Debug|x64.Build.0 = Debug|Any CPU
{417B5C77-05BF-4562-9A1A-AEE0531B59C1}.Debug|x86.ActiveCfg = Debug|Any CPU
{417B5C77-05BF-4562-9A1A-AEE0531B59C1}.Debug|x86.Build.0 = Debug|Any CPU
{417B5C77-05BF-4562-9A1A-AEE0531B59C1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{417B5C77-05BF-4562-9A1A-AEE0531B59C1}.Release|Any CPU.Build.0 = Release|Any CPU
{417B5C77-05BF-4562-9A1A-AEE0531B59C1}.Release|x64.ActiveCfg = Release|Any CPU
{417B5C77-05BF-4562-9A1A-AEE0531B59C1}.Release|x64.Build.0 = Release|Any CPU
{417B5C77-05BF-4562-9A1A-AEE0531B59C1}.Release|x86.ActiveCfg = Release|Any CPU
{417B5C77-05BF-4562-9A1A-AEE0531B59C1}.Release|x86.Build.0 = Release|Any CPU
{A2E37A84-9331-48C7-8CCA-991528063087}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A2E37A84-9331-48C7-8CCA-991528063087}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A2E37A84-9331-48C7-8CCA-991528063087}.Debug|x64.ActiveCfg = Debug|Any CPU
{A2E37A84-9331-48C7-8CCA-991528063087}.Debug|x64.Build.0 = Debug|Any CPU
{A2E37A84-9331-48C7-8CCA-991528063087}.Debug|x86.ActiveCfg = Debug|Any CPU
{A2E37A84-9331-48C7-8CCA-991528063087}.Debug|x86.Build.0 = Debug|Any CPU
{A2E37A84-9331-48C7-8CCA-991528063087}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A2E37A84-9331-48C7-8CCA-991528063087}.Release|Any CPU.Build.0 = Release|Any CPU
{A2E37A84-9331-48C7-8CCA-991528063087}.Release|x64.ActiveCfg = Release|Any CPU
{A2E37A84-9331-48C7-8CCA-991528063087}.Release|x64.Build.0 = Release|Any CPU
{A2E37A84-9331-48C7-8CCA-991528063087}.Release|x86.ActiveCfg = Release|Any CPU
{A2E37A84-9331-48C7-8CCA-991528063087}.Release|x86.Build.0 = Release|Any CPU
{4A83DB6A-01BB-4B56-B38B-268444F22B1E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4A83DB6A-01BB-4B56-B38B-268444F22B1E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4A83DB6A-01BB-4B56-B38B-268444F22B1E}.Debug|x64.ActiveCfg = Debug|Any CPU
{4A83DB6A-01BB-4B56-B38B-268444F22B1E}.Debug|x64.Build.0 = Debug|Any CPU
{4A83DB6A-01BB-4B56-B38B-268444F22B1E}.Debug|x86.ActiveCfg = Debug|Any CPU
{4A83DB6A-01BB-4B56-B38B-268444F22B1E}.Debug|x86.Build.0 = Debug|Any CPU
{4A83DB6A-01BB-4B56-B38B-268444F22B1E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4A83DB6A-01BB-4B56-B38B-268444F22B1E}.Release|Any CPU.Build.0 = Release|Any CPU
{4A83DB6A-01BB-4B56-B38B-268444F22B1E}.Release|x64.ActiveCfg = Release|Any CPU
{4A83DB6A-01BB-4B56-B38B-268444F22B1E}.Release|x64.Build.0 = Release|Any CPU
{4A83DB6A-01BB-4B56-B38B-268444F22B1E}.Release|x86.ActiveCfg = Release|Any CPU
{4A83DB6A-01BB-4B56-B38B-268444F22B1E}.Release|x86.Build.0 = Release|Any CPU
{A7AD8A07-C9C0-480B-A96B-2D03ACD57060}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A7AD8A07-C9C0-480B-A96B-2D03ACD57060}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A7AD8A07-C9C0-480B-A96B-2D03ACD57060}.Debug|x64.ActiveCfg = Debug|Any CPU
{A7AD8A07-C9C0-480B-A96B-2D03ACD57060}.Debug|x64.Build.0 = Debug|Any CPU
{A7AD8A07-C9C0-480B-A96B-2D03ACD57060}.Debug|x86.ActiveCfg = Debug|Any CPU
{A7AD8A07-C9C0-480B-A96B-2D03ACD57060}.Debug|x86.Build.0 = Debug|Any CPU
{A7AD8A07-C9C0-480B-A96B-2D03ACD57060}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A7AD8A07-C9C0-480B-A96B-2D03ACD57060}.Release|Any CPU.Build.0 = Release|Any CPU
{A7AD8A07-C9C0-480B-A96B-2D03ACD57060}.Release|x64.ActiveCfg = Release|Any CPU
{A7AD8A07-C9C0-480B-A96B-2D03ACD57060}.Release|x64.Build.0 = Release|Any CPU
{A7AD8A07-C9C0-480B-A96B-2D03ACD57060}.Release|x86.ActiveCfg = Release|Any CPU
{A7AD8A07-C9C0-480B-A96B-2D03ACD57060}.Release|x86.Build.0 = Release|Any CPU
{34720C2D-09AD-41F4-B7CC-D703D9F24EDD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{34720C2D-09AD-41F4-B7CC-D703D9F24EDD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{34720C2D-09AD-41F4-B7CC-D703D9F24EDD}.Debug|x64.ActiveCfg = Debug|Any CPU
{34720C2D-09AD-41F4-B7CC-D703D9F24EDD}.Debug|x64.Build.0 = Debug|Any CPU
{34720C2D-09AD-41F4-B7CC-D703D9F24EDD}.Debug|x86.ActiveCfg = Debug|Any CPU
{34720C2D-09AD-41F4-B7CC-D703D9F24EDD}.Debug|x86.Build.0 = Debug|Any CPU
{34720C2D-09AD-41F4-B7CC-D703D9F24EDD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{34720C2D-09AD-41F4-B7CC-D703D9F24EDD}.Release|Any CPU.Build.0 = Release|Any CPU
{34720C2D-09AD-41F4-B7CC-D703D9F24EDD}.Release|x64.ActiveCfg = Release|Any CPU
{34720C2D-09AD-41F4-B7CC-D703D9F24EDD}.Release|x64.Build.0 = Release|Any CPU
{34720C2D-09AD-41F4-B7CC-D703D9F24EDD}.Release|x86.ActiveCfg = Release|Any CPU
{34720C2D-09AD-41F4-B7CC-D703D9F24EDD}.Release|x86.Build.0 = Release|Any CPU
{BE4FCB29-7B1E-4559-B6F0-F8F5A1BEBF44}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BE4FCB29-7B1E-4559-B6F0-F8F5A1BEBF44}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BE4FCB29-7B1E-4559-B6F0-F8F5A1BEBF44}.Debug|x64.ActiveCfg = Debug|Any CPU
{BE4FCB29-7B1E-4559-B6F0-F8F5A1BEBF44}.Debug|x64.Build.0 = Debug|Any CPU
{BE4FCB29-7B1E-4559-B6F0-F8F5A1BEBF44}.Debug|x86.ActiveCfg = Debug|Any CPU
{BE4FCB29-7B1E-4559-B6F0-F8F5A1BEBF44}.Debug|x86.Build.0 = Debug|Any CPU
{BE4FCB29-7B1E-4559-B6F0-F8F5A1BEBF44}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BE4FCB29-7B1E-4559-B6F0-F8F5A1BEBF44}.Release|Any CPU.Build.0 = Release|Any CPU
{BE4FCB29-7B1E-4559-B6F0-F8F5A1BEBF44}.Release|x64.ActiveCfg = Release|Any CPU
{BE4FCB29-7B1E-4559-B6F0-F8F5A1BEBF44}.Release|x64.Build.0 = Release|Any CPU
{BE4FCB29-7B1E-4559-B6F0-F8F5A1BEBF44}.Release|x86.ActiveCfg = Release|Any CPU
{BE4FCB29-7B1E-4559-B6F0-F8F5A1BEBF44}.Release|x86.Build.0 = Release|Any CPU
{1F71C429-A9B3-46C2-BDEE-8F8413765EB5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1F71C429-A9B3-46C2-BDEE-8F8413765EB5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1F71C429-A9B3-46C2-BDEE-8F8413765EB5}.Debug|x64.ActiveCfg = Debug|Any CPU
{1F71C429-A9B3-46C2-BDEE-8F8413765EB5}.Debug|x64.Build.0 = Debug|Any CPU
{1F71C429-A9B3-46C2-BDEE-8F8413765EB5}.Debug|x86.ActiveCfg = Debug|Any CPU
{1F71C429-A9B3-46C2-BDEE-8F8413765EB5}.Debug|x86.Build.0 = Debug|Any CPU
{1F71C429-A9B3-46C2-BDEE-8F8413765EB5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1F71C429-A9B3-46C2-BDEE-8F8413765EB5}.Release|Any CPU.Build.0 = Release|Any CPU
{1F71C429-A9B3-46C2-BDEE-8F8413765EB5}.Release|x64.ActiveCfg = Release|Any CPU
{1F71C429-A9B3-46C2-BDEE-8F8413765EB5}.Release|x64.Build.0 = Release|Any CPU
{1F71C429-A9B3-46C2-BDEE-8F8413765EB5}.Release|x86.ActiveCfg = Release|Any CPU
{1F71C429-A9B3-46C2-BDEE-8F8413765EB5}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -1,26 +0,0 @@
using GerstITS.Web.WebClients;
namespace GerstITS.Examples.WebClients.Examples.Api;
public interface ICountry : IWebService
{
[WebMethod(WebMethods.Get),
ResourceUrl("Country/{id}")]
Country Get(int id);
[WebMethod(WebMethods.Get),
ResourceUrl("Country/Search")]
SearchResult<Country> Search(SearchCriteria criteria);
[WebMethod(WebMethods.Post),
ResourceUrl("Country")]
Country Create(Country model);
[WebMethod(WebMethods.Put),
ResourceUrl("Country")]
void Update(Country model);
[WebMethod(WebMethods.Delete),
ResourceUrl("Country/{id}")]
void Delete(int id);
}
@@ -1,11 +0,0 @@
namespace GerstITS.Examples.WebClients.Examples.Api;
public class Country
{
#region Properties
public int Id { get; set; }
public string Name { get; set; }
#endregion
}
@@ -1,17 +0,0 @@
namespace GerstITS.Examples.WebClients.Examples.Api;
public class SearchCriteria
{
#region Properties
internal int Id { get; set; }
public string Name { get; set; }
public int? Skip { get; set; }
public int? Take { get; set; }
public string SortBy { get; set; }
public SortingDirections SortDirection { get; set; }
#endregion
}
@@ -7,7 +7,7 @@ internal sealed class ExampleApiClientCreatingRule : RestApiClientCreationRuleBa
{
#region Properties
protected override Type[] SupportedTypes => new[] { typeof(ICountry) };
protected override Type[] SupportedTypes => new[] { typeof(ICustomer) };
#endregion
+138
View File
@@ -0,0 +1,138 @@
# GerstITS Framework Examples
This solution demonstrates all features of the GerstITS framework packages in a small, coherent customer management domain.
## Solution layout
| Project | Purpose |
|---------|---------|
| `GerstITS.Examples.Api` | ASP.NET Core Web API host: fluent controllers, versioning, exception handling, Swagger, authentication, session cache, jobs and auto migration. |
| `GerstITS.Examples.Logic` | Business logic: providers, search engine integration, validation rules, customizations and AutoMapper profiles. |
| `GerstITS.Examples.Data` | Data access: entities with framework aspects, EF Core DbContext, entity mappings, database configurator and migrations. |
| `GerstITS.Examples.Jobs.SayHelloWorld` | Scheduled Quartz jobs with cron configuration. |
| `GerstITS.WebClients.Example.Api` | Typed REST client contract for the example API (`ICustomer`). |
| `GerstITS.Examples.WebClient.Console` | Console client consuming the API via `IWebClient` plus demos of the common/system utilities. |
| `GerstITS.Examples.Tests` | xUnit tests using the GerstITS test framework categories. |
## Feature matrix
### GerstITS.Common
| Feature | Example |
|---------|---------|
| String/object/enum/enumerable extensions | `WebClient.Console/Tests/CommonFeaturesRunner.cs` |
| Fluent exception handling (`Is(...).ThenThrows<...>().WithMessage(...)`) | `CommonFeaturesRunner.cs`, `Logic/Customers/CustomerProvider.cs` (`Import`) |
| `Range<T>` + `Intersects` | `CommonFeaturesRunner.cs` |
| AES cryptography extensions (`Encrypt`/`Decrypt`) | `CommonFeaturesRunner.cs` |
| `ApplicationEnvironment` detection | `Api/Program.cs` (`IsEfCoreActionStarted`) |
### GerstITS.System
| Feature | Example |
|---------|---------|
| `ISystemClock` | `MaintenanceController.Ping`, `SayHelloWorldJob` |
| `IJsonConvert` | `Api/Common/StartupTasks/ExampleStartupTask.cs`, `CommonFeaturesRunner.cs` |
| `IActivator` | `CommonFeaturesRunner.cs` |
| `ICache` (encrypted, session backed) | `Api/Controllers/1.1/CacheController.cs` |
| Customizations (`CustomizationBase<T>`, `ApplyCustomizations()`) | `Logic/Customers/Customizations/CustomerDisplayNameCustomization.cs` |
| Configuration prefix pattern (`ToConfigurationPrefix`) | `Api/Common/Configurations/WebApiConfiguration.*.cs` |
### GerstITS.IoC / GerstITS.IoC.DotNetCore
| Feature | Example |
|---------|---------|
| `IIoCModule<IServiceCollection>` modules (partial pattern) | `Module.cs` in every project |
| `DotNetCoreApplicationBootstrapper` + `IApplicationStart` | `WebClient.Console/Program.cs`, `Tests/TestRunner.cs`, `Tests/CommonFeaturesRunner.cs` |
| `IStartupTask` with priorities | `Api/Common/StartupTasks/ExampleStartupTask.cs` |
| Namespace based assembly scanning (`Register...Of<T>()`) | `Logic/Module.Customers.cs` |
### GerstITS.Data / GerstITS.Data.EntityFramework / GerstITS.Data.EntityFramework.PostgreSql
| Feature | Example |
|---------|---------|
| `EntityBase<TKey>` + aspects (`IActivatable`, `ICreatable`, `IModifiable`, `IVersionable`) | `Data/Entities/CustomerEntity.cs` |
| Historization (`IHistoricizable`) | `Data/Entities/CustomerNoteEntity.cs` |
| `EntityMappingBase<TEntity>` | `Data/Mappings/*.cs` |
| `EntityFrameworkDbContextBase` + `IDbContext` | `Data/CustomerDbContext.cs` |
| `PostgreSqlDatabaseConfiguratorBase<TDbContext>` | `Data/Migrations/CustomerDatabaseConfigurator.cs` |
| Design time factory + migrations | `Data/Migrations/DesignTime/CustomerDbContextDesignTimeFactory.cs`, `Data/Migrations/20260703*_InitialCreate.cs` |
| Registration (`AddMigration`, `AddEntityFrameworkSession`) | `Data/Module.cs` |
| Repository queries (active only by default, `includeInactive` opt-in) | `Logic/Customers/CustomerProvider.cs` (`GetById`) |
| Soft delete by default, `forceDelete` opt-in | `CustomerProvider.Delete` |
| Bulk operations (`BulkSave`) | `CustomerProvider.Import` |
| Query projection (`Project`) | `Logic/Customers/Search/CustomerSearchQueryBuilderRule.cs` |
| `ThrowsAnExceptionIfNotExisting` / `EntityNotFoundException` | `CustomerProvider.cs`, `Api/.../EntityNotFoundExceptionTransformation.cs` |
| Auto migration on startup (`WebApi:EntityFrameworkMigration:AutoMigrate`) | `Api/appsettings.json` |
> `GerstITS.Data.EntityFramework.SqlServer` works exactly like the PostgreSql package: derive from
> `SqlServerDatabaseConfiguratorBase<TDbContext>` instead. Note that only one `IDatabaseConfigurator`
> implementation is allowed per assembly.
### GerstITS.Search
| Feature | Example |
|---------|---------|
| `ISearchEngine` + `SearchResult<T>` | `Logic/Customers/CustomerProvider.cs` (`Search`) |
| `SearchFilterBase` (paging + sorting) | `Logic/Customers/Contracts/CustomerSearchFilter.cs` |
| `SearchQueryBuilderRuleBase<TItem, TFilter>` | `Logic/Customers/Search/CustomerSearchQueryBuilderRule.cs` |
| `InitializationRuleBase<T>` (filter defaults) | `Logic/Customers/Search/CustomerSearchFilterInitializationRule.cs` |
| `PagingValidationRuleBase<T>` | `Logic/Customers/Validation/CustomerSearchFilterValidationRule.cs` |
| Custom `ISortingProvider` | `Logic/Shared/Search/Sorting/SortingProvider.cs` |
### GerstITS.Validation
| Feature | Example |
|---------|---------|
| `ValidationRuleBase<T>` (FluentValidation) | `Logic/Customers/Validation/CustomerValidationRule.cs`, `Logic/Shared/Validation/IdValidationRule.cs` |
| `IsEMail()` rule builder extension | `CustomerValidationRule.cs` |
| Automatic validation in fluent controllers (`IValidator`) | All controllers via `FluentApiControllerBase` |
### GerstITS.Mapping.AutoMapper
| Feature | Example |
|---------|---------|
| Profiles + `RegisterMappingsOf<T>()` | `Logic/Customers/Mappings/CustomerMapping.cs`, `Logic/Example/Mappings/IntegerMapping.cs` |
### GerstITS.Web / GerstITS.Web.Api / GerstITS.Web.Api.Swagger / GerstITS.Web.Rest
| Feature | Example |
|---------|---------|
| `HostingStartup` fluent pipeline | `Api/Program.cs` |
| `FluentApiControllerBase` (`Api().Use(...).Get/Create/Update/Delete`) | `Api/Controllers/1.1/*.cs` |
| API versioning (side by side controllers) | `Api/Controllers/1.0` vs `Api/Controllers/1.1` |
| Global exception transformations | `Api/Common/ExceptionHandling/Transformations/*.cs` |
| Server configuration (CORS, HSTS, forwarded headers) | `Api/Common/Configurations/WebApiConfiguration.Server.*.cs` |
| Swagger configuration incl. security schemes | `Api/Common/Configurations/WebApiConfiguration.Swagger*.cs`, `WebApiConfiguration.OpenApiSecurityScheme.cs` |
| Session based cache storage (`AddHttpSession`) | `Api/Module.Session.cs`, `CacheController.cs` |
| Typed REST clients (`IWebService`, `WebMethod`, `ResourceUrl`, `HttpHeader`) | `GerstITS.WebClients.Example.Api/Contracts/ICustomer.cs` |
| `RestWebServiceConfigurationBase` + creation rules | `GerstITS.WebClients.Example.Api/Configurations`, `CreationRules` |
| `IWebClient.Request<T>().Execute(...)` | `WebClient.Console/Tests/TestRunner.cs` |
### GerstITS.Authentication.ApiKey / GerstITS.Authentication.OpenId
| Feature | Example |
|---------|---------|
| `[ApiKey]` attribute + `IApiKeyConfiguration` | `Api/Controllers/1.1/MaintenanceController.cs`, `WebApiConfiguration.ApiKey.cs` |
| JWT bearer via `IOpenIdConfiguration` + `[Authorize]` | `Api/Controllers/1.1/SecuredController.cs`, `WebApiConfiguration.OpenId*.cs` |
### GerstITS.Mail
| Feature | Example |
|---------|---------|
| `IMailProvider`, `MailNotification`, `ContactRequest` | `Api/Controllers/1.1/ContactController.cs` |
| SMTP configuration (`Mail` section) | `Api/appsettings.json` |
### GerstITS.Job / GerstITS.Job.Scheduling
| Feature | Example |
|---------|---------|
| `JobBase` + cron scheduling | `Jobs.SayHelloWorld/Jobs/*.cs` |
| `JobSchedulingConfigurationBase` (named + convention based) | `Jobs.SayHelloWorld/Configurations/*.cs`, `Api/appsettings.json` (`Jobs` section) |
| `RegisterJob<TJob, TConfig>()` + `IgnoreConditions` | `Jobs.SayHelloWorld/Module.cs` |
### GerstITS.TestFramework
| Feature | Example |
|---------|---------|
| `[TestCategory(TestCategories.Unit/Integration)]` traits | `GerstITS.Examples.Tests/**/*Test.cs` |
| Filtering: `dotnet test --filter "Category=Unit"` | see below |
## Running
1. **Database**: the API auto-migrates on startup (`AutoMigrate: true`). Adjust the `CustomerDbContext` connection string in `GerstITS.Examples.Api/appsettings.json` (PostgreSQL).
2. **API**: start `GerstITS.Examples.Api`. Swagger UI is available in development at `/api/swagger`.
3. **Console client**: start `GerstITS.Examples.WebClient.Console` while the API is running.
4. **Tests**: `dotnet test` (optionally `--filter "Category=Unit"`).
5. **Migrations**: `dotnet ef migrations add <Name>` inside `GerstITS.Examples.Data` (uses the design time factory and `appsettings.json` of that project).
### Api key protected endpoints
`GET /api/Maintenance/Ping` requires the header configured under `WebApi:ApiKey` (default: `X-Api-Key: example-api-key`).