Skip to content

Commit

Permalink
Merge branch 'main' into dependabot/nuget/ReportGenerator-5.4.1
Browse files Browse the repository at this point in the history
  • Loading branch information
ardalis authored Nov 20, 2024
2 parents b74bfa1 + f621bf2 commit 5619d43
Show file tree
Hide file tree
Showing 17 changed files with 284 additions and 17 deletions.
2 changes: 1 addition & 1 deletion Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<PackageVersion Include="Ardalis.Result" Version="10.1.0" />
<PackageVersion Include="Ardalis.Result.AspNetCore" Version="10.1.0" />
<PackageVersion Include="Ardalis.SharedKernel" Version="2.1.1" />
<PackageVersion Include="Ardalis.SmartEnum" Version="8.1.0" />
<PackageVersion Include="Ardalis.SmartEnum" Version="8.2.0" />
<PackageVersion Include="Ardalis.Specification" Version="8.0.0" />
<PackageVersion Include="Ardalis.Specification.EntityFrameworkCore" Version="8.0.0" />
<PackageVersion Include="Azure.Identity" Version="1.13.1" />
Expand Down
12 changes: 8 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,6 @@ This architecture is used in the [DDD Fundamentals course](https://www.pluralsig

[Learn about how to implement Clean Architecture](https://academy.nimblepros.com/p/intro-to-clean-architecture) from [NimblePros](https://nimblepros.com) trainers [Sarah "sadukie" Dutkiewicz](https://blog.nimblepros.com/author/sadukie/) and [Steve "ardalis" Smith](https://blog.nimblepros.com/author/ardalis/).

## Troubleshooting Chrome Errors

By default the site uses HTTPS and expects you to have a self-signed developer certificate for localhost use. If you get an error with Chrome [see this answer](https://stackoverflow.com/a/31900210/13729) for mitigation instructions.

## Table Of Contents

- [Clean Architecture](#clean-architecture)
Expand Down Expand Up @@ -62,6 +58,14 @@ If you like or are using this project to learn or start your solution, please gi

Or if you're feeling really generous, we now support GitHub sponsorships - see the button above.

## Sponsors

I'm please to announce that [Amazon AWS's FOSS fund](https://github.com/aws/dotnet-foss) has chosen to award a 12-month sponsorship to this project. Thank you, and thanks to all of my other past and current sponsors!

## Troubleshooting Chrome Errors

By default the site uses HTTPS and expects you to have a self-signed developer certificate for localhost use. If you get an error with Chrome [see this answer](https://stackoverflow.com/a/31900210/13729) for mitigation instructions.

## Versions

The main branch is now using **.NET 9**. This corresponds with NuGet package version 10.x. Previous versions are available - see our [Releases](https://github.com/ardalis/CleanArchitecture/releases).
Expand Down
2 changes: 1 addition & 1 deletion docs/architecture-decisions/adr-001-dotnet-di-adoption.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,5 @@ Based on community feedback and a review of our project's requirements, we have
- **Standardization**: Adopting .NET's built-in DI promotes consistency with other .NET projects, making it easier for developers familiar with the framework to contribute effectively.

## References
- [Issue #649: Why is this repo using Autofac instead of .NET's own DI infrastructure?](https://github.com/your-repo/issues/649) - Discussion that led to this decision.
- [Issue #649: Why is this repo using Autofac instead of .NET's own DI infrastructure?](https://github.com/ardalis/CleanArchitecture/issues/649) - Discussion that led to this decision.
- [Getting Started with Architecture Decision Records](https://ardalis.com/getting-started-with-architecture-decision-records/) - Resource on ADR best practices.
22 changes: 18 additions & 4 deletions sample/Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -5,26 +5,31 @@
<PackageVersion Include="Ardalis.ListStartupServices" Version="1.1.4" />
<PackageVersion Include="Ardalis.Result" Version="10.1.0" />
<PackageVersion Include="Ardalis.Result.AspNetCore" Version="10.1.0" />
<PackageVersion Include="Ardalis.SharedKernel" Version="2.1.1" />
<PackageVersion Include="Ardalis.SmartEnum" Version="8.1.0" />
<PackageVersion Include="Ardalis.Specification" Version="8.0.0" />
<PackageVersion Include="Ardalis.Specification.EntityFrameworkCore" Version="8.0.0" />
<PackageVersion Include="Azure.Identity" Version="1.13.1" />
<PackageVersion Include="coverlet.collector" Version="6.0.2" />
<PackageVersion Include="FastEndpoints" Version="5.31.0" />
<PackageVersion Include="FastEndpoints.ApiExplorer" Version="2.3.0" />
<PackageVersion Include="FastEndpoints.ApiExplorer" Version="2.2.0" />
<PackageVersion Include="FastEndpoints.Swagger" Version="5.31.0" />
<PackageVersion Include="FastEndpoints.Swagger.Swashbuckle" Version="2.3.0" />
<PackageVersion Include="FastEndpoints.Swagger.Swashbuckle" Version="2.2.0" />
<PackageVersion Include="FluentAssertions" Version="6.12.2" />
<PackageVersion Include="MailKit" Version="4.8.0" />
<PackageVersion Include="MediatR" Version="12.4.1" />
<PackageVersion Include="MediatR.Extensions.Autofac.DependencyInjection" Version="12.2.0" />
<PackageVersion Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="9.0.0" />
<PackageVersion Include="Microsoft.AspNetCore.Mvc.Testing" Version="9.0.0" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.InMemory" Version="9.0.0" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Relational" Version="9.0.0" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Design" Version="9.0.0" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Tools" Version="9.0.0" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Sqlite" Version="9.0.0" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.SqlServer" Version="9.0.0" />
<PackageVersion Include="Microsoft.Extensions.Configuration" Version="9.0.0" />
<PackageVersion Include="Microsoft.Extensions.Logging" Version="9.0.0" />
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="9.0.0" />
<PackageVersion Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="9.0.0" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.11.1" />
<PackageVersion Include="Newtonsoft.Json" Version="13.0.3" />
<PackageVersion Include="NimblePros.SharedKernel" Version="2.1.1" />
Expand All @@ -38,6 +43,15 @@
<PackageVersion Include="Testcontainers" Version="4.0.0" />
<PackageVersion Include="Vogen" Version="5.0.3" />
<PackageVersion Include="xunit" Version="2.9.2" />
<PackageVersion Include="xunit.runner.visualstudio" Version="2.8.2" />
<PackageVersion Include="xunit.runner.visualstudio" Version="3.0.0-pre.49" />
<PackageVersion Include="Aspire.Hosting.AppHost" Version="9.0.0" />
<PackageVersion Include="Microsoft.Extensions.Http.Resilience" Version="9.0.0" />
<PackageVersion Include="Microsoft.Extensions.ServiceDiscovery" Version="9.0.0" />
<PackageVersion Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" Version="1.10.0" />
<PackageVersion Include="OpenTelemetry.Extensions.Hosting" Version="1.10.0" />
<PackageVersion Include="OpenTelemetry.Instrumentation.AspNetCore" Version="1.9.0" />
<PackageVersion Include="OpenTelemetry.Instrumentation.Http" Version="1.9.0" />
<PackageVersion Include="OpenTelemetry.Instrumentation.Runtime" Version="1.9.0" />
<PackageVersion Include="Aspire.Hosting.Testing" Version="9.0.0" />
</ItemGroup>
</Project>
30 changes: 30 additions & 0 deletions sample/NimblePros.SampleToDo.sln
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NimblePros.SampleToDo.UnitT
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NimblePros.SampleToDo.UseCases", "src\NimblePros.SampleToDo.UseCases\NimblePros.SampleToDo.UseCases.csproj", "{B74A78FF-B79E-4C38-A9C7-084A90990CAD}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NimblePros.SampleToDo.AspireHost", "src\NimblePros.SampleToDo.AspireHost\NimblePros.SampleToDo.AspireHost.csproj", "{A386838E-3D47-0E25-E489-902B7426F983}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NimblePros.SampleToDo.ServiceDefaults", "src\NimblePros.SampleToDo.ServiceDefaults\NimblePros.SampleToDo.ServiceDefaults.csproj", "{6EFB0B52-15DF-2406-DA11-569E9010FD25}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -129,6 +133,30 @@ Global
{B74A78FF-B79E-4C38-A9C7-084A90990CAD}.Release|x64.Build.0 = Release|Any CPU
{B74A78FF-B79E-4C38-A9C7-084A90990CAD}.Release|x86.ActiveCfg = Release|Any CPU
{B74A78FF-B79E-4C38-A9C7-084A90990CAD}.Release|x86.Build.0 = Release|Any CPU
{A386838E-3D47-0E25-E489-902B7426F983}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A386838E-3D47-0E25-E489-902B7426F983}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A386838E-3D47-0E25-E489-902B7426F983}.Debug|x64.ActiveCfg = Debug|Any CPU
{A386838E-3D47-0E25-E489-902B7426F983}.Debug|x64.Build.0 = Debug|Any CPU
{A386838E-3D47-0E25-E489-902B7426F983}.Debug|x86.ActiveCfg = Debug|Any CPU
{A386838E-3D47-0E25-E489-902B7426F983}.Debug|x86.Build.0 = Debug|Any CPU
{A386838E-3D47-0E25-E489-902B7426F983}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A386838E-3D47-0E25-E489-902B7426F983}.Release|Any CPU.Build.0 = Release|Any CPU
{A386838E-3D47-0E25-E489-902B7426F983}.Release|x64.ActiveCfg = Release|Any CPU
{A386838E-3D47-0E25-E489-902B7426F983}.Release|x64.Build.0 = Release|Any CPU
{A386838E-3D47-0E25-E489-902B7426F983}.Release|x86.ActiveCfg = Release|Any CPU
{A386838E-3D47-0E25-E489-902B7426F983}.Release|x86.Build.0 = Release|Any CPU
{6EFB0B52-15DF-2406-DA11-569E9010FD25}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6EFB0B52-15DF-2406-DA11-569E9010FD25}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6EFB0B52-15DF-2406-DA11-569E9010FD25}.Debug|x64.ActiveCfg = Debug|Any CPU
{6EFB0B52-15DF-2406-DA11-569E9010FD25}.Debug|x64.Build.0 = Debug|Any CPU
{6EFB0B52-15DF-2406-DA11-569E9010FD25}.Debug|x86.ActiveCfg = Debug|Any CPU
{6EFB0B52-15DF-2406-DA11-569E9010FD25}.Debug|x86.Build.0 = Debug|Any CPU
{6EFB0B52-15DF-2406-DA11-569E9010FD25}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6EFB0B52-15DF-2406-DA11-569E9010FD25}.Release|Any CPU.Build.0 = Release|Any CPU
{6EFB0B52-15DF-2406-DA11-569E9010FD25}.Release|x64.ActiveCfg = Release|Any CPU
{6EFB0B52-15DF-2406-DA11-569E9010FD25}.Release|x64.Build.0 = Release|Any CPU
{6EFB0B52-15DF-2406-DA11-569E9010FD25}.Release|x86.ActiveCfg = Release|Any CPU
{6EFB0B52-15DF-2406-DA11-569E9010FD25}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand All @@ -141,6 +169,8 @@ Global
{0776DC14-9000-47A4-A3F4-ECBCF8CEBC17} = {B31B4797-1D9F-4288-808C-BE9A31A98C7D}
{1DC7F5A0-DDF7-4975-84EB-05F4FC1B6AB5} = {B31B4797-1D9F-4288-808C-BE9A31A98C7D}
{B74A78FF-B79E-4C38-A9C7-084A90990CAD} = {106AE906-5075-410A-B941-912F811848EE}
{A386838E-3D47-0E25-E489-902B7426F983} = {106AE906-5075-410A-B941-912F811848EE}
{6EFB0B52-15DF-2406-DA11-569E9010FD25} = {106AE906-5075-410A-B941-912F811848EE}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {B0F19343-8185-4A9F-9165-0EA8544BC925}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<Project Sdk="Microsoft.NET.Sdk">

<Sdk Name="Aspire.AppHost.Sdk" Version="9.0.0" />

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsAspireHost>true</IsAspireHost>
<UserSecretsId>c540eeb6-e06b-4456-a539-be58dd8b88c7</UserSecretsId>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Aspire.Hosting.AppHost" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\NimblePros.SampleToDo.Web\NimblePros.SampleToDo.Web.csproj" />
</ItemGroup>
<ItemGroup>
<!-- The IsAspireProjectResource attribute tells .NET Aspire to treat this
reference as a standard project reference and not attempt to generate
a metadata file -->
<ProjectReference Include="..\NimblePros.SampleToDo.ServiceDefaults\NimblePros.SampleToDo.ServiceDefaults.csproj"
IsAspireProjectResource="false" />
</ItemGroup>

</Project>
5 changes: 5 additions & 0 deletions sample/src/NimblePros.SampleToDo.AspireHost/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
var builder = DistributedApplication.CreateBuilder(args);

builder.AddProject<Projects.NimblePros_SampleToDo_Web>("web");

builder.Build().Run();
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
"$schema": "https://json.schemastore.org/launchsettings.json",
"profiles": {
"https": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"applicationUrl": "https://localhost:17143;http://localhost:15258",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development",
"DOTNET_ENVIRONMENT": "Development",
"DOTNET_DASHBOARD_OTLP_ENDPOINT_URL": "https://localhost:21007",
"DOTNET_RESOURCE_SERVICE_ENDPOINT_URL": "https://localhost:22245"
}
},
"http": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"applicationUrl": "http://localhost:15258",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development",
"DOTNET_ENVIRONMENT": "Development",
"DOTNET_DASHBOARD_OTLP_ENDPOINT_URL": "http://localhost:19187",
"DOTNET_RESOURCE_SERVICE_ENDPOINT_URL": "http://localhost:20134"
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
}
9 changes: 9 additions & 0 deletions sample/src/NimblePros.SampleToDo.AspireHost/appsettings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning",
"Aspire.Hosting.Dcp": "Warning"
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using NimblePros.SampleToDo.Core.ProjectAggregate.Events;
using Ardalis.SharedKernel;

namespace NimblePros.SampleToDo.Core.ProjectAggregate;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,9 @@ private static void RegisterDevelopmentOnlyDependencies(IServiceCollection servi
{
AddDbContextWithSqlite(services, configuration);
services.AddScoped<IEmailSender, SmtpEmailSender>();
services.AddScoped<IListContributorsQueryService, FakeListContributorsQueryService>();
services.AddScoped<IListIncompleteItemsQueryService, FakeListIncompleteItemsQueryService>();
services.AddScoped<IListProjectsShallowQueryService, FakeListProjectsShallowQueryService>();
services.AddScoped<IListContributorsQueryService, ListContributorsQueryService>();
services.AddScoped<IListIncompleteItemsQueryService, ListIncompleteItemsQueryService>();
services.AddScoped<IListProjectsShallowQueryService, ListProjectsShallowQueryService>();
}

private static void RegisterTestingOnlyDependencies(IServiceCollection services)
Expand Down
118 changes: 118 additions & 0 deletions sample/src/NimblePros.SampleToDo.ServiceDefaults/Extensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Diagnostics.HealthChecks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Diagnostics.HealthChecks;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.ServiceDiscovery;
using OpenTelemetry;
using OpenTelemetry.Metrics;
using OpenTelemetry.Trace;

namespace Microsoft.Extensions.Hosting;

// Adds common .NET Aspire services: service discovery, resilience, health checks, and OpenTelemetry.
// This project should be referenced by each service project in your solution.
// To learn more about using this project, see https://aka.ms/dotnet/aspire/service-defaults
public static class Extensions
{
public static TBuilder AddServiceDefaults<TBuilder>(this TBuilder builder) where TBuilder : IHostApplicationBuilder
{
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();
});

// Uncomment the following to restrict the allowed schemes for service discovery.
// builder.Services.Configure<ServiceDiscoveryOptions>(options =>
// {
// options.AllowedSchemes = ["https"];
// });

return builder;
}

public static TBuilder ConfigureOpenTelemetry<TBuilder>(this TBuilder builder) where TBuilder : IHostApplicationBuilder
{
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 TBuilder AddOpenTelemetryExporters<TBuilder>(this TBuilder builder) where TBuilder : IHostApplicationBuilder
{
var useOtlpExporter = !string.IsNullOrWhiteSpace(builder.Configuration["OTEL_EXPORTER_OTLP_ENDPOINT"]);

if (useOtlpExporter)
{
builder.Services.AddOpenTelemetry().UseOtlpExporter();
}

// 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 TBuilder AddDefaultHealthChecks<TBuilder>(this TBuilder builder) where TBuilder : IHostApplicationBuilder
{
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")
});
}

return app;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsAspireSharedProject>true</IsAspireSharedProject>
</PropertyGroup>

<ItemGroup>
<FrameworkReference Include="Microsoft.AspNetCore.App" />

<PackageReference Include="Microsoft.Extensions.Http.Resilience" />
<PackageReference Include="Microsoft.Extensions.ServiceDiscovery" />
<PackageReference Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" />
<PackageReference Include="OpenTelemetry.Extensions.Hosting" />
<PackageReference Include="OpenTelemetry.Instrumentation.AspNetCore" />
<PackageReference Include="OpenTelemetry.Instrumentation.Http" />
<PackageReference Include="OpenTelemetry.Instrumentation.Runtime" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
<ItemGroup>
<PackageReference Include="Ardalis.Result" />
<PackageReference Include="MediatR" />
<PackageReference Include="MediatR.Extensions.Autofac.DependencyInjection" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" />
<PackageReference Include="NimblePros.SharedKernel" />
</ItemGroup>
Expand Down
Loading

0 comments on commit 5619d43

Please sign in to comment.