From a0ffa07069eb3d6311c8393574760cecdbdf496b Mon Sep 17 00:00:00 2001 From: Fredi Machado Date: Thu, 16 May 2024 22:58:11 +1000 Subject: [PATCH] =?UTF-8?q?Add=20.NET=20Aspire=20support=20=E2=99=A5?= =?UTF-8?q?=EF=B8=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Directory.Packages.props | 10 ++ NCafe.sln | 23 ++++ .../NCafe.Admin.Api/NCafe.Admin.Api.csproj | 1 + src/Admin/NCafe.Admin.Api/Program.cs | 4 + .../Aspire.Hosting.EventStore.csproj | 13 ++ .../EventStoreBuilderExtensions.cs | 43 +++++++ .../EventStoreContainerImageTags.cs | 8 ++ .../EventStoreResource.cs | 27 ++++ src/Aspire/NCafe.AppHost/NCafe.AppHost.csproj | 24 ++++ src/Aspire/NCafe.AppHost/Program.cs | 20 +++ .../Properties/launchSettings.json | 29 +++++ .../appsettings.Development.json | 8 ++ src/Aspire/NCafe.AppHost/appsettings.json | 9 ++ .../NCafe.ServiceDefaults/Extensions.cs | 115 ++++++++++++++++++ .../NCafe.ServiceDefaults.csproj | 21 ++++ .../NCafe.Barista.Api.csproj | 1 + src/Barista/NCafe.Barista.Api/Program.cs | 4 + .../NCafe.Cashier.Api.csproj | 1 + src/Cashier/NCafe.Cashier.Api/Program.cs | 4 + 19 files changed, 365 insertions(+) create mode 100644 src/Aspire/Aspire.Hosting.EventStore/Aspire.Hosting.EventStore.csproj create mode 100644 src/Aspire/Aspire.Hosting.EventStore/EventStoreBuilderExtensions.cs create mode 100644 src/Aspire/Aspire.Hosting.EventStore/EventStoreContainerImageTags.cs create mode 100644 src/Aspire/Aspire.Hosting.EventStore/EventStoreResource.cs create mode 100644 src/Aspire/NCafe.AppHost/NCafe.AppHost.csproj create mode 100644 src/Aspire/NCafe.AppHost/Program.cs create mode 100644 src/Aspire/NCafe.AppHost/Properties/launchSettings.json create mode 100644 src/Aspire/NCafe.AppHost/appsettings.Development.json create mode 100644 src/Aspire/NCafe.AppHost/appsettings.json create mode 100644 src/Aspire/NCafe.ServiceDefaults/Extensions.cs create mode 100644 src/Aspire/NCafe.ServiceDefaults/NCafe.ServiceDefaults.csproj diff --git a/Directory.Packages.props b/Directory.Packages.props index e7100ea..560facf 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -4,6 +4,16 @@ true + + + + + + + + + + diff --git a/NCafe.sln b/NCafe.sln index d93e5de..bc65c79 100644 --- a/NCafe.sln +++ b/NCafe.sln @@ -77,6 +77,14 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{49528FFA EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NCafe.Common.Tests", "src\Common\NCafe.Common.Tests\NCafe.Common.Tests.csproj", "{0203B146-09CB-4350-8375-9759F132BDC2}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NCafe.AppHost", "src\Aspire\NCafe.AppHost\NCafe.AppHost.csproj", "{ED16805D-2DEA-4F88-8BCD-E3460AE89CAF}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NCafe.ServiceDefaults", "src\Aspire\NCafe.ServiceDefaults\NCafe.ServiceDefaults.csproj", "{A7B56906-8702-48CD-9CB0-2274802E54B2}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Aspire", "Aspire", "{81ABD551-6547-47EF-8F01-160466F018D2}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Aspire.Hosting.EventStore", "src\Aspire\Aspire.Hosting.EventStore\Aspire.Hosting.EventStore.csproj", "{1F5E7F20-3972-4E73-86A9-83F20F6EE8C7}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -139,6 +147,18 @@ Global {0203B146-09CB-4350-8375-9759F132BDC2}.Debug|Any CPU.Build.0 = Debug|Any CPU {0203B146-09CB-4350-8375-9759F132BDC2}.Release|Any CPU.ActiveCfg = Release|Any CPU {0203B146-09CB-4350-8375-9759F132BDC2}.Release|Any CPU.Build.0 = Release|Any CPU + {ED16805D-2DEA-4F88-8BCD-E3460AE89CAF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {ED16805D-2DEA-4F88-8BCD-E3460AE89CAF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {ED16805D-2DEA-4F88-8BCD-E3460AE89CAF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {ED16805D-2DEA-4F88-8BCD-E3460AE89CAF}.Release|Any CPU.Build.0 = Release|Any CPU + {A7B56906-8702-48CD-9CB0-2274802E54B2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A7B56906-8702-48CD-9CB0-2274802E54B2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A7B56906-8702-48CD-9CB0-2274802E54B2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A7B56906-8702-48CD-9CB0-2274802E54B2}.Release|Any CPU.Build.0 = Release|Any CPU + {1F5E7F20-3972-4E73-86A9-83F20F6EE8C7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1F5E7F20-3972-4E73-86A9-83F20F6EE8C7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1F5E7F20-3972-4E73-86A9-83F20F6EE8C7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1F5E7F20-3972-4E73-86A9-83F20F6EE8C7}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -164,6 +184,9 @@ Global {98734B27-556B-40FB-8E1F-86FDCC4DA1A1} = {728C5CE5-C0F8-45B9-B9ED-E6AA7C219095} {49528FFA-842E-4853-9B8F-77BCE9970D11} = {728C5CE5-C0F8-45B9-B9ED-E6AA7C219095} {0203B146-09CB-4350-8375-9759F132BDC2} = {49528FFA-842E-4853-9B8F-77BCE9970D11} + {ED16805D-2DEA-4F88-8BCD-E3460AE89CAF} = {81ABD551-6547-47EF-8F01-160466F018D2} + {A7B56906-8702-48CD-9CB0-2274802E54B2} = {81ABD551-6547-47EF-8F01-160466F018D2} + {1F5E7F20-3972-4E73-86A9-83F20F6EE8C7} = {81ABD551-6547-47EF-8F01-160466F018D2} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {F0136BF1-D5F3-4E83-8D23-E3F43534FBB5} diff --git a/src/Admin/NCafe.Admin.Api/NCafe.Admin.Api.csproj b/src/Admin/NCafe.Admin.Api/NCafe.Admin.Api.csproj index 377579b..1609cb9 100644 --- a/src/Admin/NCafe.Admin.Api/NCafe.Admin.Api.csproj +++ b/src/Admin/NCafe.Admin.Api/NCafe.Admin.Api.csproj @@ -9,6 +9,7 @@ + diff --git a/src/Admin/NCafe.Admin.Api/Program.cs b/src/Admin/NCafe.Admin.Api/Program.cs index d39d9d5..95d7699 100644 --- a/src/Admin/NCafe.Admin.Api/Program.cs +++ b/src/Admin/NCafe.Admin.Api/Program.cs @@ -8,6 +8,8 @@ var builder = WebApplication.CreateBuilder(args); +builder.AddServiceDefaults(); + // Add services to the container. builder.Services.AddEventStoreRepository(builder.Configuration) .AddCommandHandlers() @@ -35,6 +37,8 @@ var app = builder.Build(); +app.MapDefaultEndpoints(); + // Configure the HTTP request pipeline. if (app.Environment.IsDevelopment()) { diff --git a/src/Aspire/Aspire.Hosting.EventStore/Aspire.Hosting.EventStore.csproj b/src/Aspire/Aspire.Hosting.EventStore/Aspire.Hosting.EventStore.csproj new file mode 100644 index 0000000..f923a3a --- /dev/null +++ b/src/Aspire/Aspire.Hosting.EventStore/Aspire.Hosting.EventStore.csproj @@ -0,0 +1,13 @@ + + + + enable + enable + EventStore support for .NET Aspire. + + + + + + + diff --git a/src/Aspire/Aspire.Hosting.EventStore/EventStoreBuilderExtensions.cs b/src/Aspire/Aspire.Hosting.EventStore/EventStoreBuilderExtensions.cs new file mode 100644 index 0000000..02bd19c --- /dev/null +++ b/src/Aspire/Aspire.Hosting.EventStore/EventStoreBuilderExtensions.cs @@ -0,0 +1,43 @@ +using Aspire.Hosting.ApplicationModel; +using Aspire.Hosting.EventStore; + +namespace Aspire.Hosting; + +public static class EventStoreBuilderExtensions +{ + /// + /// Adds an EventStore resource to the application model. A container is used for local development. + /// This package defaults to the 20.10.0-buster-slim tag of the eventstore container image. + /// + /// The . + /// The name of the resource. This name will be used as the connection string name when referenced in a dependency. + /// The port on which the EventStore HTTP endpoint will be exposed. + /// The port on which the EventStore TCP endpoint will be exposed. + /// A reference to the . + public static IResourceBuilder AddEventStore( + this IDistributedApplicationBuilder builder, string name, int? httpPort = null, int? tcpPort = null) + { + var eventStoreContainer = new EventStoreResource(name); + + return builder + .AddResource(eventStoreContainer) + .WithEndpoint(port: tcpPort, targetPort: EventStoreResource.DefaultTcpPort, name: EventStoreResource.TcpEndpointName) + .WithHttpEndpoint(port: httpPort, targetPort: EventStoreResource.DefaultHttpPort, name: EventStoreResource.HttpEndpointName) + .WithImage(EventStoreContainerImageTags.Image, EventStoreContainerImageTags.Tag) + .WithImageRegistry(EventStoreContainerImageTags.Registry) + .WithEnvironment(context => ConfigureEventStoreContainer(context, eventStoreContainer)); + } + + private static void ConfigureEventStoreContainer(EnvironmentCallbackContext context, EventStoreResource resource) + { + context.EnvironmentVariables.Add("EVENTSTORE_CLUSTER_SIZE", "1"); + context.EnvironmentVariables.Add("EVENTSTORE_RUN_PROJECTIONS", "All"); + context.EnvironmentVariables.Add("EVENTSTORE_START_STANDARD_PROJECTIONS", "true"); + context.EnvironmentVariables.Add("EVENTSTORE_EXT_TCP_PORT", EventStoreResource.DefaultTcpPort.ToString()); + context.EnvironmentVariables.Add("EVENTSTORE_HTTP_PORT", EventStoreResource.DefaultHttpPort.ToString()); + context.EnvironmentVariables.Add("EVENTSTORE_INSECURE", "true"); + context.EnvironmentVariables.Add("EVENTSTORE_DEV", "true"); + context.EnvironmentVariables.Add("EVENTSTORE_ENABLE_ATOM_PUB_OVER_HTTP", "true"); + context.EnvironmentVariables.Add("EVENTSTORE_ENABLE_EXTERNAL_TCP", "true"); + } +} diff --git a/src/Aspire/Aspire.Hosting.EventStore/EventStoreContainerImageTags.cs b/src/Aspire/Aspire.Hosting.EventStore/EventStoreContainerImageTags.cs new file mode 100644 index 0000000..f4749fb --- /dev/null +++ b/src/Aspire/Aspire.Hosting.EventStore/EventStoreContainerImageTags.cs @@ -0,0 +1,8 @@ +namespace Aspire.Hosting.EventStore; + +internal static class EventStoreContainerImageTags +{ + public const string Registry = "docker.io"; + public const string Image = "eventstore/eventstore"; + public const string Tag = "20.10.0-buster-slim"; +} diff --git a/src/Aspire/Aspire.Hosting.EventStore/EventStoreResource.cs b/src/Aspire/Aspire.Hosting.EventStore/EventStoreResource.cs new file mode 100644 index 0000000..fa21447 --- /dev/null +++ b/src/Aspire/Aspire.Hosting.EventStore/EventStoreResource.cs @@ -0,0 +1,27 @@ +namespace Aspire.Hosting.ApplicationModel; + +/// +/// A resource that represents an EventStore container. +/// +/// The name of the resource. +public class EventStoreResource(string name) : ContainerResource(name), IResourceWithConnectionString +{ + internal const string HttpEndpointName = "http"; + internal const string TcpEndpointName = "tcp"; + internal const int DefaultHttpPort = 2113; + internal const int DefaultTcpPort = 1113; + + private EndpointReference? _primaryEndpoint; + + /// + /// Gets the primary endpoint for the EventStore server. + /// + public EndpointReference PrimaryEndpoint => _primaryEndpoint ??= new(this, HttpEndpointName); + + /// + /// Gets the connection string for the EventStore server. + /// + public ReferenceExpression ConnectionStringExpression => + ReferenceExpression.Create( + $"esdb://{PrimaryEndpoint.Property(EndpointProperty.Host)}:{PrimaryEndpoint.Property(EndpointProperty.Port)}?tls=false"); +} diff --git a/src/Aspire/NCafe.AppHost/NCafe.AppHost.csproj b/src/Aspire/NCafe.AppHost/NCafe.AppHost.csproj new file mode 100644 index 0000000..4285a88 --- /dev/null +++ b/src/Aspire/NCafe.AppHost/NCafe.AppHost.csproj @@ -0,0 +1,24 @@ + + + + Exe + enable + enable + true + 6e4e7f77-0985-41fb-8ac7-7a26000ea41d + + + + + + + + + + + + + + + + diff --git a/src/Aspire/NCafe.AppHost/Program.cs b/src/Aspire/NCafe.AppHost/Program.cs new file mode 100644 index 0000000..fe8f072 --- /dev/null +++ b/src/Aspire/NCafe.AppHost/Program.cs @@ -0,0 +1,20 @@ +var builder = DistributedApplication.CreateBuilder(args); + +var eventStore = builder.AddEventStore("eventstore"); +var rabbitMq = builder.AddRabbitMQ("rabbitmq"); + +var adminProject = builder.AddProject("admin-api") + .WithReference(eventStore); + +var baristaProject = builder.AddProject("barista-api") + .WithReference(eventStore) + .WithReference(rabbitMq); + +var cashierProject = builder.AddProject("cashier-api") + .WithReference(eventStore) + .WithReference(rabbitMq); + +var webUiProject = builder.AddProject("web-ui") + .WithExternalHttpEndpoints(); + +builder.Build().Run(); diff --git a/src/Aspire/NCafe.AppHost/Properties/launchSettings.json b/src/Aspire/NCafe.AppHost/Properties/launchSettings.json new file mode 100644 index 0000000..2279c68 --- /dev/null +++ b/src/Aspire/NCafe.AppHost/Properties/launchSettings.json @@ -0,0 +1,29 @@ +{ + "$schema": "https://json.schemastore.org/launchsettings.json", + "profiles": { + "https": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "applicationUrl": "https://localhost:17129;http://localhost:15064", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development", + "DOTNET_ENVIRONMENT": "Development", + "DOTNET_DASHBOARD_OTLP_ENDPOINT_URL": "https://localhost:21182", + "DOTNET_RESOURCE_SERVICE_ENDPOINT_URL": "https://localhost:22264" + } + }, + "http": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "applicationUrl": "http://localhost:15064", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development", + "DOTNET_ENVIRONMENT": "Development", + "DOTNET_DASHBOARD_OTLP_ENDPOINT_URL": "http://localhost:19224", + "DOTNET_RESOURCE_SERVICE_ENDPOINT_URL": "http://localhost:20043" + } + } + } +} diff --git a/src/Aspire/NCafe.AppHost/appsettings.Development.json b/src/Aspire/NCafe.AppHost/appsettings.Development.json new file mode 100644 index 0000000..0c208ae --- /dev/null +++ b/src/Aspire/NCafe.AppHost/appsettings.Development.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + } +} diff --git a/src/Aspire/NCafe.AppHost/appsettings.json b/src/Aspire/NCafe.AppHost/appsettings.json new file mode 100644 index 0000000..31c092a --- /dev/null +++ b/src/Aspire/NCafe.AppHost/appsettings.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning", + "Aspire.Hosting.Dcp": "Warning" + } + } +} diff --git a/src/Aspire/NCafe.ServiceDefaults/Extensions.cs b/src/Aspire/NCafe.ServiceDefaults/Extensions.cs new file mode 100644 index 0000000..b6e8000 --- /dev/null +++ b/src/Aspire/NCafe.ServiceDefaults/Extensions.cs @@ -0,0 +1,115 @@ +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Diagnostics.HealthChecks; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Diagnostics.HealthChecks; +using Microsoft.Extensions.Logging; +using OpenTelemetry; +using OpenTelemetry.Metrics; +using OpenTelemetry.Trace; + +namespace Microsoft.Extensions.Hosting; + +public static class Extensions +{ + public static IHostApplicationBuilder AddServiceDefaults(this IHostApplicationBuilder builder) + { + builder.ConfigureOpenTelemetry(); + + builder.AddDefaultHealthChecks(); + + builder.Services.AddServiceDiscovery(); + + builder.Services.ConfigureHttpClientDefaults(http => + { + // Turn on resilience by default + http.AddStandardResilienceHandler(); + + // Turn on service discovery by default + http.AddServiceDiscovery(); + }); + + return builder; + } + + public static IHostApplicationBuilder ConfigureOpenTelemetry(this IHostApplicationBuilder builder) + { + builder.Logging.AddOpenTelemetry(logging => + { + logging.IncludeFormattedMessage = true; + logging.IncludeScopes = true; + }); + + builder.Services.AddOpenTelemetry() + .WithMetrics(metrics => + { + metrics.AddAspNetCoreInstrumentation() + .AddHttpClientInstrumentation() + .AddRuntimeInstrumentation(); + }) + .WithTracing(tracing => + { + tracing.AddAspNetCoreInstrumentation() + // Uncomment the following line to enable gRPC instrumentation (requires the OpenTelemetry.Instrumentation.GrpcNetClient package) + //.AddGrpcClientInstrumentation() + .AddHttpClientInstrumentation(); + }); + + builder.AddOpenTelemetryExporters(); + + return builder; + } + + private static IHostApplicationBuilder AddOpenTelemetryExporters(this IHostApplicationBuilder builder) + { + var useOtlpExporter = !string.IsNullOrWhiteSpace(builder.Configuration["OTEL_EXPORTER_OTLP_ENDPOINT"]); + + if (useOtlpExporter) + { + builder.Services.AddOpenTelemetry().UseOtlpExporter(); + } + + // Uncomment the following lines to enable the Prometheus exporter (requires the OpenTelemetry.Exporter.Prometheus.AspNetCore package) + // builder.Services.AddOpenTelemetry() + // .WithMetrics(metrics => metrics.AddPrometheusExporter()); + + // Uncomment the following lines to enable the Azure Monitor exporter (requires the Azure.Monitor.OpenTelemetry.AspNetCore package) + //if (!string.IsNullOrEmpty(builder.Configuration["APPLICATIONINSIGHTS_CONNECTION_STRING"])) + //{ + // builder.Services.AddOpenTelemetry() + // .UseAzureMonitor(); + //} + + return builder; + } + + public static IHostApplicationBuilder AddDefaultHealthChecks(this IHostApplicationBuilder builder) + { + builder.Services.AddHealthChecks() + // Add a default liveness check to ensure app is responsive + .AddCheck("self", () => HealthCheckResult.Healthy(), ["live"]); + + return builder; + } + + public static WebApplication MapDefaultEndpoints(this WebApplication app) + { + // Adding health checks endpoints to applications in non-development environments has security implications. + // See https://aka.ms/dotnet/aspire/healthchecks for details before enabling these endpoints in non-development environments. + if (app.Environment.IsDevelopment()) + { + // All health checks must pass for app to be considered ready to accept traffic after starting + app.MapHealthChecks("/health"); + + // 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") + }); + + // Uncomment the following line to enable the Prometheus endpoint (requires the OpenTelemetry.Exporter.Prometheus.AspNetCore package) + // app.MapPrometheusScrapingEndpoint(); + } + + return app; + } +} diff --git a/src/Aspire/NCafe.ServiceDefaults/NCafe.ServiceDefaults.csproj b/src/Aspire/NCafe.ServiceDefaults/NCafe.ServiceDefaults.csproj new file mode 100644 index 0000000..caa6344 --- /dev/null +++ b/src/Aspire/NCafe.ServiceDefaults/NCafe.ServiceDefaults.csproj @@ -0,0 +1,21 @@ + + + + enable + enable + true + + + + + + + + + + + + + + + diff --git a/src/Barista/NCafe.Barista.Api/NCafe.Barista.Api.csproj b/src/Barista/NCafe.Barista.Api/NCafe.Barista.Api.csproj index 5775119..62a419c 100644 --- a/src/Barista/NCafe.Barista.Api/NCafe.Barista.Api.csproj +++ b/src/Barista/NCafe.Barista.Api/NCafe.Barista.Api.csproj @@ -9,6 +9,7 @@ + diff --git a/src/Barista/NCafe.Barista.Api/Program.cs b/src/Barista/NCafe.Barista.Api/Program.cs index d1b91a5..173a666 100644 --- a/src/Barista/NCafe.Barista.Api/Program.cs +++ b/src/Barista/NCafe.Barista.Api/Program.cs @@ -11,6 +11,8 @@ var builder = WebApplication.CreateBuilder(args); +builder.AddServiceDefaults(); + // Add services to the container. builder.Services.AddEventStoreRepository(builder.Configuration) .AddCommandHandlers() @@ -47,6 +49,8 @@ var app = builder.Build(); +app.MapDefaultEndpoints(); + app.UseResponseCompression(); // Configure the HTTP request pipeline. diff --git a/src/Cashier/NCafe.Cashier.Api/NCafe.Cashier.Api.csproj b/src/Cashier/NCafe.Cashier.Api/NCafe.Cashier.Api.csproj index d799beb..341f9a1 100644 --- a/src/Cashier/NCafe.Cashier.Api/NCafe.Cashier.Api.csproj +++ b/src/Cashier/NCafe.Cashier.Api/NCafe.Cashier.Api.csproj @@ -9,6 +9,7 @@ + diff --git a/src/Cashier/NCafe.Cashier.Api/Program.cs b/src/Cashier/NCafe.Cashier.Api/Program.cs index f8f79e7..9f88ead 100644 --- a/src/Cashier/NCafe.Cashier.Api/Program.cs +++ b/src/Cashier/NCafe.Cashier.Api/Program.cs @@ -8,6 +8,8 @@ var builder = WebApplication.CreateBuilder(args); +builder.AddServiceDefaults(); + // Add services to the container. builder.Services.AddEventStoreRepository(builder.Configuration) .AddCommandHandlers() @@ -37,6 +39,8 @@ var app = builder.Build(); +app.MapDefaultEndpoints(); + // Configure the HTTP request pipeline. if (app.Environment.IsDevelopment()) {