From d10adbdbfab64b8178d0662903c8eaf821f0fb7a Mon Sep 17 00:00:00 2001 From: Damian Edwards Date: Fri, 2 Aug 2024 17:59:37 -0700 Subject: [PATCH] Update to Aspire 8.1, latest .NET, and update other packages (#41) * Update to 8.1 * Use 8.1 testing features * Update package versions * Update package deps in labs, etc. * Update package versions in markdown files --- README.md | 2 +- labs/1-Create-Catalog-API/README.md | 2 +- .../end/Catalog.API/Catalog.API.csproj | 4 +- .../Catalog.Data.Manager.csproj | 4 +- .../end/Catalog.Data/Catalog.Data.csproj | 2 +- .../end/eShop.AppHost/eShop.AppHost.csproj | 4 +- .../eShop.ServiceDefaults.csproj | 14 +- .../Catalog.Data.Manager.csproj | 4 +- .../src/Catalog.Data/Catalog.Data.csproj | 2 +- labs/2-Create-Blazor-Frontend/README.md | 2 +- .../Catalog.Data.Manager.csproj | 4 +- .../end/Catalog.Data/Catalog.Data.csproj | 2 +- .../end/WebApp/WebApp.csproj | 2 +- .../end/eShop.AppHost/eShop.AppHost.csproj | 4 +- .../eShop.ServiceDefaults.csproj | 18 +- .../Catalog.Data.Manager.csproj | 4 +- .../src/Catalog.Data/Catalog.Data.csproj | 2 +- .../src/eShop.AppHost/eShop.AppHost.csproj | 4 +- .../eShop.ServiceDefaults.csproj | 18 +- labs/3-Add-Identity/README.md | 2 +- .../Catalog.Data.Manager.csproj | 4 +- .../end/Catalog.Data/Catalog.Data.csproj | 2 +- labs/3-Add-Identity/end/WebApp/WebApp.csproj | 4 +- .../end/eShop.AppHost/eShop.AppHost.csproj | 4 +- .../eShop.ServiceDefaults.csproj | 20 +- .../Catalog.Data.Manager.csproj | 4 +- .../src/Catalog.Data/Catalog.Data.csproj | 2 +- labs/3-Add-Identity/src/WebApp/WebApp.csproj | 2 +- .../src/eShop.AppHost/eShop.AppHost.csproj | 4 +- .../eShop.ServiceDefaults.csproj | 20 +- labs/4-Add-Shopping-Basket/README.md | 8 +- .../end/Basket.API/Basket.API.csproj | 4 +- .../Catalog.Data.Manager.csproj | 4 +- .../end/Catalog.Data/Catalog.Data.csproj | 2 +- .../end/WebApp/WebApp.csproj | 8 +- .../end/eShop.AppHost/eShop.AppHost.csproj | 6 +- .../eShop.ServiceDefaults.csproj | 20 +- .../Catalog.Data.Manager.csproj | 4 +- .../src/Catalog.Data/Catalog.Data.csproj | 2 +- .../src/WebApp/WebApp.csproj | 4 +- .../src/eShop.AppHost/eShop.AppHost.csproj | 4 +- .../eShop.ServiceDefaults.csproj | 20 +- .../end/Basket.API/Basket.API.csproj | 4 +- .../Catalog.Data.Manager.csproj | 4 +- .../end/Catalog.Data/Catalog.Data.csproj | 2 +- .../end/Ordering.API/Ordering.API.csproj | 4 +- .../Ordering.Data.Manager.csproj | 4 +- .../end/Ordering.Data/Ordering.Data.csproj | 2 +- labs/5-Add-Checkout/end/WebApp/WebApp.csproj | 8 +- .../end/eShop.AppHost/eShop.AppHost.csproj | 6 +- .../eShop.ServiceDefaults.csproj | 20 +- .../src/Basket.API/Basket.API.csproj | 4 +- .../Catalog.Data.Manager.csproj | 4 +- .../src/Catalog.Data/Catalog.Data.csproj | 2 +- .../Ordering.Data.Manager.csproj | 4 +- .../src/Ordering.Data/Ordering.Data.csproj | 2 +- labs/5-Add-Checkout/src/WebApp/WebApp.csproj | 8 +- .../src/eShop.AppHost/eShop.AppHost.csproj | 6 +- .../eShop.ServiceDefaults.csproj | 20 +- .../src/Basket.API/Basket.API.csproj | 4 +- .../Catalog.Data.Manager.csproj | 4 +- .../src/Catalog.Data/Catalog.Data.csproj | 2 +- .../src/Ordering.API/Ordering.API.csproj | 2 +- .../Ordering.Data.Manager.csproj | 4 +- .../src/Ordering.Data/Ordering.Data.csproj | 2 +- .../6-Add-Resiliency/src/WebApp/WebApp.csproj | 8 +- .../src/eShop.AppHost/eShop.AppHost.csproj | 6 +- .../eShop.ServiceDefaults.csproj | 20 +- src/Basket.API/Basket.API.csproj | 4 +- .../Catalog.Data.Manager.csproj | 4 +- src/Catalog.Data/Catalog.Data.csproj | 2 +- .../DistributedApplicationExtensions.cs | 61 ----- .../Infrastructure/LoggerLogStore.cs | 38 --- .../Infrastructure/ResourceLogStore.cs | 75 ------ .../Infrastructure/ResourceWatcher.cs | 228 ------------------ .../Infrastructure/StoredLogsLogger.cs | 26 -- .../StoredLogsLoggerProvider.cs | 23 -- .../Infrastructure/XUnitExtensions.cs | 40 --- .../Infrastructure/XUnitLogger.cs | 57 ----- .../Infrastructure/XUnitLoggerProvider.cs | 24 -- .../Infrastructure/XUnitTextWriter.cs | 33 --- src/IntegrationTests/IntegrationTests.csproj | 17 +- src/IntegrationTests/WebAppTests.cs | 11 +- src/Ordering.API/Ordering.API.csproj | 2 +- .../Ordering.Data.Manager.csproj | 4 +- src/Ordering.Data/Ordering.Data.csproj | 2 +- src/WebApp/WebApp.csproj | 8 +- src/eShop.AppHost/eShop.AppHost.csproj | 6 +- .../eShop.ServiceDefaults.csproj | 20 +- 89 files changed, 251 insertions(+), 842 deletions(-) delete mode 100644 src/IntegrationTests/Infrastructure/LoggerLogStore.cs delete mode 100644 src/IntegrationTests/Infrastructure/ResourceLogStore.cs delete mode 100644 src/IntegrationTests/Infrastructure/ResourceWatcher.cs delete mode 100644 src/IntegrationTests/Infrastructure/StoredLogsLogger.cs delete mode 100644 src/IntegrationTests/Infrastructure/StoredLogsLoggerProvider.cs delete mode 100644 src/IntegrationTests/Infrastructure/XUnitExtensions.cs delete mode 100644 src/IntegrationTests/Infrastructure/XUnitLogger.cs delete mode 100644 src/IntegrationTests/Infrastructure/XUnitLoggerProvider.cs delete mode 100644 src/IntegrationTests/Infrastructure/XUnitTextWriter.cs diff --git a/README.md b/README.md index 3bdbf29..c1cbbfe 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ If you're using macOs or Linux, or on Windows but don't want to use Visual Studi ### Updating and installing the .NET SDK workload for Aspire -After installing Visual Studio Preview or the required .NET SDK, you will need to update and install the .NET SDK workload for Aspire. This workshop is using the latest version of .NET Aspire (8.0.1). For your convenience, scripts are provided in this repository to make this process easy: +After installing Visual Studio Preview or the required .NET SDK, you will need to update and install the .NET SDK workload for Aspire. This workshop is using the latest version of .NET Aspire (8.1). For your convenience, scripts are provided in this repository to make this process easy: 1. Clone [this repo](https://github.com/dotnet-presentations/eshop-app-workshop) to your machine. 1. In your terminal, navigate to the repo root and run the command `dotnet --version` to verify you are using version 8.0.100 or later of the .NET SDK: diff --git a/labs/1-Create-Catalog-API/README.md b/labs/1-Create-Catalog-API/README.md index 397e28b..fbad3ba 100644 --- a/labs/1-Create-Catalog-API/README.md +++ b/labs/1-Create-Catalog-API/README.md @@ -139,7 +139,7 @@ Containers are extremely useful for hosting service dependencies, but rather tha ``` ```xml - + ``` 1. Use the methods on the `builder` variable to create a PostgreSQL instance called `postgres` with pgAdmin enabled, and a database called `CatalogDB`. Ensure that the `catalog-db-mgr` project resource is configured with a reference to the `catalogDb`: diff --git a/labs/1-Create-Catalog-API/end/Catalog.API/Catalog.API.csproj b/labs/1-Create-Catalog-API/end/Catalog.API/Catalog.API.csproj index 2f86045..08d1c9f 100644 --- a/labs/1-Create-Catalog-API/end/Catalog.API/Catalog.API.csproj +++ b/labs/1-Create-Catalog-API/end/Catalog.API/Catalog.API.csproj @@ -9,8 +9,8 @@ - - + + diff --git a/labs/1-Create-Catalog-API/end/Catalog.Data.Manager/Catalog.Data.Manager.csproj b/labs/1-Create-Catalog-API/end/Catalog.Data.Manager/Catalog.Data.Manager.csproj index 9d8a4be..ab37312 100644 --- a/labs/1-Create-Catalog-API/end/Catalog.Data.Manager/Catalog.Data.Manager.csproj +++ b/labs/1-Create-Catalog-API/end/Catalog.Data.Manager/Catalog.Data.Manager.csproj @@ -14,8 +14,8 @@ - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/labs/1-Create-Catalog-API/end/Catalog.Data/Catalog.Data.csproj b/labs/1-Create-Catalog-API/end/Catalog.Data/Catalog.Data.csproj index ab16dee..4db6c99 100644 --- a/labs/1-Create-Catalog-API/end/Catalog.Data/Catalog.Data.csproj +++ b/labs/1-Create-Catalog-API/end/Catalog.Data/Catalog.Data.csproj @@ -8,7 +8,7 @@ - + diff --git a/labs/1-Create-Catalog-API/end/eShop.AppHost/eShop.AppHost.csproj b/labs/1-Create-Catalog-API/end/eShop.AppHost/eShop.AppHost.csproj index aaf4044..ee4b2b5 100644 --- a/labs/1-Create-Catalog-API/end/eShop.AppHost/eShop.AppHost.csproj +++ b/labs/1-Create-Catalog-API/end/eShop.AppHost/eShop.AppHost.csproj @@ -9,8 +9,8 @@ - - + + diff --git a/labs/1-Create-Catalog-API/end/eShop.ServiceDefaults/eShop.ServiceDefaults.csproj b/labs/1-Create-Catalog-API/end/eShop.ServiceDefaults/eShop.ServiceDefaults.csproj index 66101d4..5318fd8 100644 --- a/labs/1-Create-Catalog-API/end/eShop.ServiceDefaults/eShop.ServiceDefaults.csproj +++ b/labs/1-Create-Catalog-API/end/eShop.ServiceDefaults/eShop.ServiceDefaults.csproj @@ -11,14 +11,14 @@ - - - - - + + + + + - - + + diff --git a/labs/1-Create-Catalog-API/src/Catalog.Data.Manager/Catalog.Data.Manager.csproj b/labs/1-Create-Catalog-API/src/Catalog.Data.Manager/Catalog.Data.Manager.csproj index 38f0cb6..9920648 100644 --- a/labs/1-Create-Catalog-API/src/Catalog.Data.Manager/Catalog.Data.Manager.csproj +++ b/labs/1-Create-Catalog-API/src/Catalog.Data.Manager/Catalog.Data.Manager.csproj @@ -12,8 +12,8 @@ - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/labs/1-Create-Catalog-API/src/Catalog.Data/Catalog.Data.csproj b/labs/1-Create-Catalog-API/src/Catalog.Data/Catalog.Data.csproj index ab16dee..4db6c99 100644 --- a/labs/1-Create-Catalog-API/src/Catalog.Data/Catalog.Data.csproj +++ b/labs/1-Create-Catalog-API/src/Catalog.Data/Catalog.Data.csproj @@ -8,7 +8,7 @@ - + diff --git a/labs/2-Create-Blazor-Frontend/README.md b/labs/2-Create-Blazor-Frontend/README.md index ed2ed6f..6856ef3 100644 --- a/labs/2-Create-Blazor-Frontend/README.md +++ b/labs/2-Create-Blazor-Frontend/README.md @@ -166,7 +166,7 @@ Now that we have a service we can use to easily retrieve the catalog items from 1. [YARP](https://microsoft.github.io/reverse-proxy/) is a package for ASP.NET Core applications that provides highly customizable reverse proxying capabilities. We'll use YARP to proxy the product image requests to the frontend site on to the Catalog API. Add a reference to the `Microsoft.Extensions.ServiceDiscovery.Yarp` package, version `8.0.1`. You can use the [`dotnet` CLI](https://learn.microsoft.com/dotnet/core/tools/dotnet-add-package), or Visual Studio NuGet Package Manager, or edit the `WebApp.csproj` directly: ```xml - + ``` 1. To setup the proxying behavior, first add a line to the `AddApplicationServices` method in the `HostingExtensions.cs` file, to add the require services to the application's DI container: diff --git a/labs/2-Create-Blazor-Frontend/end/Catalog.Data.Manager/Catalog.Data.Manager.csproj b/labs/2-Create-Blazor-Frontend/end/Catalog.Data.Manager/Catalog.Data.Manager.csproj index 15801b7..046e3bc 100644 --- a/labs/2-Create-Blazor-Frontend/end/Catalog.Data.Manager/Catalog.Data.Manager.csproj +++ b/labs/2-Create-Blazor-Frontend/end/Catalog.Data.Manager/Catalog.Data.Manager.csproj @@ -13,8 +13,8 @@ - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/labs/2-Create-Blazor-Frontend/end/Catalog.Data/Catalog.Data.csproj b/labs/2-Create-Blazor-Frontend/end/Catalog.Data/Catalog.Data.csproj index ab16dee..4db6c99 100644 --- a/labs/2-Create-Blazor-Frontend/end/Catalog.Data/Catalog.Data.csproj +++ b/labs/2-Create-Blazor-Frontend/end/Catalog.Data/Catalog.Data.csproj @@ -8,7 +8,7 @@ - + diff --git a/labs/2-Create-Blazor-Frontend/end/WebApp/WebApp.csproj b/labs/2-Create-Blazor-Frontend/end/WebApp/WebApp.csproj index dc8d410..a35612d 100644 --- a/labs/2-Create-Blazor-Frontend/end/WebApp/WebApp.csproj +++ b/labs/2-Create-Blazor-Frontend/end/WebApp/WebApp.csproj @@ -11,7 +11,7 @@ - + diff --git a/labs/2-Create-Blazor-Frontend/end/eShop.AppHost/eShop.AppHost.csproj b/labs/2-Create-Blazor-Frontend/end/eShop.AppHost/eShop.AppHost.csproj index 7dc9edc..e8a4cc3 100644 --- a/labs/2-Create-Blazor-Frontend/end/eShop.AppHost/eShop.AppHost.csproj +++ b/labs/2-Create-Blazor-Frontend/end/eShop.AppHost/eShop.AppHost.csproj @@ -9,8 +9,8 @@ - - + + diff --git a/labs/2-Create-Blazor-Frontend/end/eShop.ServiceDefaults/eShop.ServiceDefaults.csproj b/labs/2-Create-Blazor-Frontend/end/eShop.ServiceDefaults/eShop.ServiceDefaults.csproj index 8215c6f..f7a6d65 100644 --- a/labs/2-Create-Blazor-Frontend/end/eShop.ServiceDefaults/eShop.ServiceDefaults.csproj +++ b/labs/2-Create-Blazor-Frontend/end/eShop.ServiceDefaults/eShop.ServiceDefaults.csproj @@ -13,15 +13,15 @@ - - - - - - - + + + + + + + - - + + diff --git a/labs/2-Create-Blazor-Frontend/src/Catalog.Data.Manager/Catalog.Data.Manager.csproj b/labs/2-Create-Blazor-Frontend/src/Catalog.Data.Manager/Catalog.Data.Manager.csproj index 15801b7..046e3bc 100644 --- a/labs/2-Create-Blazor-Frontend/src/Catalog.Data.Manager/Catalog.Data.Manager.csproj +++ b/labs/2-Create-Blazor-Frontend/src/Catalog.Data.Manager/Catalog.Data.Manager.csproj @@ -13,8 +13,8 @@ - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/labs/2-Create-Blazor-Frontend/src/Catalog.Data/Catalog.Data.csproj b/labs/2-Create-Blazor-Frontend/src/Catalog.Data/Catalog.Data.csproj index ab16dee..4db6c99 100644 --- a/labs/2-Create-Blazor-Frontend/src/Catalog.Data/Catalog.Data.csproj +++ b/labs/2-Create-Blazor-Frontend/src/Catalog.Data/Catalog.Data.csproj @@ -8,7 +8,7 @@ - + diff --git a/labs/2-Create-Blazor-Frontend/src/eShop.AppHost/eShop.AppHost.csproj b/labs/2-Create-Blazor-Frontend/src/eShop.AppHost/eShop.AppHost.csproj index b787a4d..2049762 100644 --- a/labs/2-Create-Blazor-Frontend/src/eShop.AppHost/eShop.AppHost.csproj +++ b/labs/2-Create-Blazor-Frontend/src/eShop.AppHost/eShop.AppHost.csproj @@ -9,8 +9,8 @@ - - + + diff --git a/labs/2-Create-Blazor-Frontend/src/eShop.ServiceDefaults/eShop.ServiceDefaults.csproj b/labs/2-Create-Blazor-Frontend/src/eShop.ServiceDefaults/eShop.ServiceDefaults.csproj index 8215c6f..f7a6d65 100644 --- a/labs/2-Create-Blazor-Frontend/src/eShop.ServiceDefaults/eShop.ServiceDefaults.csproj +++ b/labs/2-Create-Blazor-Frontend/src/eShop.ServiceDefaults/eShop.ServiceDefaults.csproj @@ -13,15 +13,15 @@ - - - - - - - + + + + + + + - - + + diff --git a/labs/3-Add-Identity/README.md b/labs/3-Add-Identity/README.md index b8aa742..b87245b 100644 --- a/labs/3-Add-Identity/README.md +++ b/labs/3-Add-Identity/README.md @@ -109,7 +109,7 @@ Now that our Keycloak instance is setup as an IdP, we can configure the web site 1. Open the `WebApp` project and add a reference to the `Microsoft.AspNetCore.Authentication.OpenIdConnect` NuGet package, version `8.0.1`. You can use the `dotnet` CLI, Visual Studio NuGet Package Manager, or just edit the .csproj file manually: ```xml - + ``` 1. In the `WebApp` project, open the `HostingExtensions.cs` file and add a new field to define a name for the `HttpClient` instance the OIDC code will use: diff --git a/labs/3-Add-Identity/end/Catalog.Data.Manager/Catalog.Data.Manager.csproj b/labs/3-Add-Identity/end/Catalog.Data.Manager/Catalog.Data.Manager.csproj index 15801b7..046e3bc 100644 --- a/labs/3-Add-Identity/end/Catalog.Data.Manager/Catalog.Data.Manager.csproj +++ b/labs/3-Add-Identity/end/Catalog.Data.Manager/Catalog.Data.Manager.csproj @@ -13,8 +13,8 @@ - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/labs/3-Add-Identity/end/Catalog.Data/Catalog.Data.csproj b/labs/3-Add-Identity/end/Catalog.Data/Catalog.Data.csproj index ab16dee..4db6c99 100644 --- a/labs/3-Add-Identity/end/Catalog.Data/Catalog.Data.csproj +++ b/labs/3-Add-Identity/end/Catalog.Data/Catalog.Data.csproj @@ -8,7 +8,7 @@ - + diff --git a/labs/3-Add-Identity/end/WebApp/WebApp.csproj b/labs/3-Add-Identity/end/WebApp/WebApp.csproj index 30ae4b3..e613833 100644 --- a/labs/3-Add-Identity/end/WebApp/WebApp.csproj +++ b/labs/3-Add-Identity/end/WebApp/WebApp.csproj @@ -11,8 +11,8 @@ - - + + diff --git a/labs/3-Add-Identity/end/eShop.AppHost/eShop.AppHost.csproj b/labs/3-Add-Identity/end/eShop.AppHost/eShop.AppHost.csproj index 7dc9edc..e8a4cc3 100644 --- a/labs/3-Add-Identity/end/eShop.AppHost/eShop.AppHost.csproj +++ b/labs/3-Add-Identity/end/eShop.AppHost/eShop.AppHost.csproj @@ -9,8 +9,8 @@ - - + + diff --git a/labs/3-Add-Identity/end/eShop.ServiceDefaults/eShop.ServiceDefaults.csproj b/labs/3-Add-Identity/end/eShop.ServiceDefaults/eShop.ServiceDefaults.csproj index 4c89643..bb4d68f 100644 --- a/labs/3-Add-Identity/end/eShop.ServiceDefaults/eShop.ServiceDefaults.csproj +++ b/labs/3-Add-Identity/end/eShop.ServiceDefaults/eShop.ServiceDefaults.csproj @@ -13,16 +13,16 @@ - - - - - - - - + + + + + + + + - - + + diff --git a/labs/3-Add-Identity/src/Catalog.Data.Manager/Catalog.Data.Manager.csproj b/labs/3-Add-Identity/src/Catalog.Data.Manager/Catalog.Data.Manager.csproj index 15801b7..046e3bc 100644 --- a/labs/3-Add-Identity/src/Catalog.Data.Manager/Catalog.Data.Manager.csproj +++ b/labs/3-Add-Identity/src/Catalog.Data.Manager/Catalog.Data.Manager.csproj @@ -13,8 +13,8 @@ - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/labs/3-Add-Identity/src/Catalog.Data/Catalog.Data.csproj b/labs/3-Add-Identity/src/Catalog.Data/Catalog.Data.csproj index ab16dee..4db6c99 100644 --- a/labs/3-Add-Identity/src/Catalog.Data/Catalog.Data.csproj +++ b/labs/3-Add-Identity/src/Catalog.Data/Catalog.Data.csproj @@ -8,7 +8,7 @@ - + diff --git a/labs/3-Add-Identity/src/WebApp/WebApp.csproj b/labs/3-Add-Identity/src/WebApp/WebApp.csproj index 3de4157..94e3619 100644 --- a/labs/3-Add-Identity/src/WebApp/WebApp.csproj +++ b/labs/3-Add-Identity/src/WebApp/WebApp.csproj @@ -11,7 +11,7 @@ - + diff --git a/labs/3-Add-Identity/src/eShop.AppHost/eShop.AppHost.csproj b/labs/3-Add-Identity/src/eShop.AppHost/eShop.AppHost.csproj index 7dc9edc..e8a4cc3 100644 --- a/labs/3-Add-Identity/src/eShop.AppHost/eShop.AppHost.csproj +++ b/labs/3-Add-Identity/src/eShop.AppHost/eShop.AppHost.csproj @@ -9,8 +9,8 @@ - - + + diff --git a/labs/3-Add-Identity/src/eShop.ServiceDefaults/eShop.ServiceDefaults.csproj b/labs/3-Add-Identity/src/eShop.ServiceDefaults/eShop.ServiceDefaults.csproj index 4c89643..bb4d68f 100644 --- a/labs/3-Add-Identity/src/eShop.ServiceDefaults/eShop.ServiceDefaults.csproj +++ b/labs/3-Add-Identity/src/eShop.ServiceDefaults/eShop.ServiceDefaults.csproj @@ -13,16 +13,16 @@ - - - - - - - - + + + + + + + + - - + + diff --git a/labs/4-Add-Shopping-Basket/README.md b/labs/4-Add-Shopping-Basket/README.md index 9081283..a858608 100644 --- a/labs/4-Add-Shopping-Basket/README.md +++ b/labs/4-Add-Shopping-Basket/README.md @@ -78,7 +78,7 @@ In the .NET CLI, we need to do a few steps manually to configure .NET Aspire orc ``` ```xml - + ``` 1. Open the `Program.cs` file in the `eShop.AppHost` project and add a line to create a new Redis resource named `"BasketStore"` and configure it to host a [Redis Commander](https://joeferner.github.io/redis-commander/) instance too (this will make it easier to inspect the Redis database during development). Capture the resource in a `basketStore` variable: @@ -143,7 +143,7 @@ In the .NET CLI, we need to do a few steps manually to configure .NET Aspire orc Add the `Aspire.StackExchange.Redis` component NuGet package to the `Basket.API` project. You can use the **Add > .NET Aspire Compoenent...** project menu item in Visual Studio, the `dotnet add package` command at the command line, or by editing the `Basket.API.csproj` file directly: ```xml - + ``` 1. In the `AddApplicationServices` method in `HostingExtensions.cs`, add a call to `AddRedis` to configure the Redis client in the application's DI container. Pass the name `"BasketStore"` to the method to indicate that the client should be configured to connect to the Redis resource with that name in the AppHost: @@ -513,8 +513,8 @@ The starting point for this lab already includes updates to the web site to prov - `Grpc.Tools` ```xml - - + + ``` 1. In the `WebApp.csproj` project file, add the `basket.proto` file from the `Basket.API` project as a `Protobuf` item in the project and set the `GrpcServices` metadata to `"Client"` to indicate that it should be used to generate client-side code for the gRPC service: diff --git a/labs/4-Add-Shopping-Basket/end/Basket.API/Basket.API.csproj b/labs/4-Add-Shopping-Basket/end/Basket.API/Basket.API.csproj index e144819..6cbd156 100644 --- a/labs/4-Add-Shopping-Basket/end/Basket.API/Basket.API.csproj +++ b/labs/4-Add-Shopping-Basket/end/Basket.API/Basket.API.csproj @@ -8,8 +8,8 @@ - - + + diff --git a/labs/4-Add-Shopping-Basket/end/Catalog.Data.Manager/Catalog.Data.Manager.csproj b/labs/4-Add-Shopping-Basket/end/Catalog.Data.Manager/Catalog.Data.Manager.csproj index 15801b7..046e3bc 100644 --- a/labs/4-Add-Shopping-Basket/end/Catalog.Data.Manager/Catalog.Data.Manager.csproj +++ b/labs/4-Add-Shopping-Basket/end/Catalog.Data.Manager/Catalog.Data.Manager.csproj @@ -13,8 +13,8 @@ - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/labs/4-Add-Shopping-Basket/end/Catalog.Data/Catalog.Data.csproj b/labs/4-Add-Shopping-Basket/end/Catalog.Data/Catalog.Data.csproj index ab16dee..4db6c99 100644 --- a/labs/4-Add-Shopping-Basket/end/Catalog.Data/Catalog.Data.csproj +++ b/labs/4-Add-Shopping-Basket/end/Catalog.Data/Catalog.Data.csproj @@ -8,7 +8,7 @@ - + diff --git a/labs/4-Add-Shopping-Basket/end/WebApp/WebApp.csproj b/labs/4-Add-Shopping-Basket/end/WebApp/WebApp.csproj index 2ffaf7c..0c16cc3 100644 --- a/labs/4-Add-Shopping-Basket/end/WebApp/WebApp.csproj +++ b/labs/4-Add-Shopping-Basket/end/WebApp/WebApp.csproj @@ -11,10 +11,10 @@ - - - - + + + + diff --git a/labs/4-Add-Shopping-Basket/end/eShop.AppHost/eShop.AppHost.csproj b/labs/4-Add-Shopping-Basket/end/eShop.AppHost/eShop.AppHost.csproj index 699f9a3..ef150fd 100644 --- a/labs/4-Add-Shopping-Basket/end/eShop.AppHost/eShop.AppHost.csproj +++ b/labs/4-Add-Shopping-Basket/end/eShop.AppHost/eShop.AppHost.csproj @@ -9,9 +9,9 @@ - - - + + + diff --git a/labs/4-Add-Shopping-Basket/end/eShop.ServiceDefaults/eShop.ServiceDefaults.csproj b/labs/4-Add-Shopping-Basket/end/eShop.ServiceDefaults/eShop.ServiceDefaults.csproj index 4c89643..bb4d68f 100644 --- a/labs/4-Add-Shopping-Basket/end/eShop.ServiceDefaults/eShop.ServiceDefaults.csproj +++ b/labs/4-Add-Shopping-Basket/end/eShop.ServiceDefaults/eShop.ServiceDefaults.csproj @@ -13,16 +13,16 @@ - - - - - - - - + + + + + + + + - - + + diff --git a/labs/4-Add-Shopping-Basket/src/Catalog.Data.Manager/Catalog.Data.Manager.csproj b/labs/4-Add-Shopping-Basket/src/Catalog.Data.Manager/Catalog.Data.Manager.csproj index 15801b7..046e3bc 100644 --- a/labs/4-Add-Shopping-Basket/src/Catalog.Data.Manager/Catalog.Data.Manager.csproj +++ b/labs/4-Add-Shopping-Basket/src/Catalog.Data.Manager/Catalog.Data.Manager.csproj @@ -13,8 +13,8 @@ - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/labs/4-Add-Shopping-Basket/src/Catalog.Data/Catalog.Data.csproj b/labs/4-Add-Shopping-Basket/src/Catalog.Data/Catalog.Data.csproj index ab16dee..4db6c99 100644 --- a/labs/4-Add-Shopping-Basket/src/Catalog.Data/Catalog.Data.csproj +++ b/labs/4-Add-Shopping-Basket/src/Catalog.Data/Catalog.Data.csproj @@ -8,7 +8,7 @@ - + diff --git a/labs/4-Add-Shopping-Basket/src/WebApp/WebApp.csproj b/labs/4-Add-Shopping-Basket/src/WebApp/WebApp.csproj index 30ae4b3..e613833 100644 --- a/labs/4-Add-Shopping-Basket/src/WebApp/WebApp.csproj +++ b/labs/4-Add-Shopping-Basket/src/WebApp/WebApp.csproj @@ -11,8 +11,8 @@ - - + + diff --git a/labs/4-Add-Shopping-Basket/src/eShop.AppHost/eShop.AppHost.csproj b/labs/4-Add-Shopping-Basket/src/eShop.AppHost/eShop.AppHost.csproj index 7dc9edc..e8a4cc3 100644 --- a/labs/4-Add-Shopping-Basket/src/eShop.AppHost/eShop.AppHost.csproj +++ b/labs/4-Add-Shopping-Basket/src/eShop.AppHost/eShop.AppHost.csproj @@ -9,8 +9,8 @@ - - + + diff --git a/labs/4-Add-Shopping-Basket/src/eShop.ServiceDefaults/eShop.ServiceDefaults.csproj b/labs/4-Add-Shopping-Basket/src/eShop.ServiceDefaults/eShop.ServiceDefaults.csproj index 4c89643..bb4d68f 100644 --- a/labs/4-Add-Shopping-Basket/src/eShop.ServiceDefaults/eShop.ServiceDefaults.csproj +++ b/labs/4-Add-Shopping-Basket/src/eShop.ServiceDefaults/eShop.ServiceDefaults.csproj @@ -13,16 +13,16 @@ - - - - - - - - + + + + + + + + - - + + diff --git a/labs/5-Add-Checkout/end/Basket.API/Basket.API.csproj b/labs/5-Add-Checkout/end/Basket.API/Basket.API.csproj index 6f26a2d..ecba322 100644 --- a/labs/5-Add-Checkout/end/Basket.API/Basket.API.csproj +++ b/labs/5-Add-Checkout/end/Basket.API/Basket.API.csproj @@ -8,8 +8,8 @@ - - + + diff --git a/labs/5-Add-Checkout/end/Catalog.Data.Manager/Catalog.Data.Manager.csproj b/labs/5-Add-Checkout/end/Catalog.Data.Manager/Catalog.Data.Manager.csproj index 15801b7..046e3bc 100644 --- a/labs/5-Add-Checkout/end/Catalog.Data.Manager/Catalog.Data.Manager.csproj +++ b/labs/5-Add-Checkout/end/Catalog.Data.Manager/Catalog.Data.Manager.csproj @@ -13,8 +13,8 @@ - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/labs/5-Add-Checkout/end/Catalog.Data/Catalog.Data.csproj b/labs/5-Add-Checkout/end/Catalog.Data/Catalog.Data.csproj index ab16dee..4db6c99 100644 --- a/labs/5-Add-Checkout/end/Catalog.Data/Catalog.Data.csproj +++ b/labs/5-Add-Checkout/end/Catalog.Data/Catalog.Data.csproj @@ -8,7 +8,7 @@ - + diff --git a/labs/5-Add-Checkout/end/Ordering.API/Ordering.API.csproj b/labs/5-Add-Checkout/end/Ordering.API/Ordering.API.csproj index 55b7b4b..45630fc 100644 --- a/labs/5-Add-Checkout/end/Ordering.API/Ordering.API.csproj +++ b/labs/5-Add-Checkout/end/Ordering.API/Ordering.API.csproj @@ -8,8 +8,8 @@ - - + + diff --git a/labs/5-Add-Checkout/end/Ordering.Data.Manager/Ordering.Data.Manager.csproj b/labs/5-Add-Checkout/end/Ordering.Data.Manager/Ordering.Data.Manager.csproj index 0bcd4af..8978236 100644 --- a/labs/5-Add-Checkout/end/Ordering.Data.Manager/Ordering.Data.Manager.csproj +++ b/labs/5-Add-Checkout/end/Ordering.Data.Manager/Ordering.Data.Manager.csproj @@ -13,8 +13,8 @@ - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/labs/5-Add-Checkout/end/Ordering.Data/Ordering.Data.csproj b/labs/5-Add-Checkout/end/Ordering.Data/Ordering.Data.csproj index a26c594..d031682 100644 --- a/labs/5-Add-Checkout/end/Ordering.Data/Ordering.Data.csproj +++ b/labs/5-Add-Checkout/end/Ordering.Data/Ordering.Data.csproj @@ -8,6 +8,6 @@ - + diff --git a/labs/5-Add-Checkout/end/WebApp/WebApp.csproj b/labs/5-Add-Checkout/end/WebApp/WebApp.csproj index 09265da..26aea62 100644 --- a/labs/5-Add-Checkout/end/WebApp/WebApp.csproj +++ b/labs/5-Add-Checkout/end/WebApp/WebApp.csproj @@ -11,10 +11,10 @@ - - - - + + + + diff --git a/labs/5-Add-Checkout/end/eShop.AppHost/eShop.AppHost.csproj b/labs/5-Add-Checkout/end/eShop.AppHost/eShop.AppHost.csproj index cd618b5..7bc5782 100644 --- a/labs/5-Add-Checkout/end/eShop.AppHost/eShop.AppHost.csproj +++ b/labs/5-Add-Checkout/end/eShop.AppHost/eShop.AppHost.csproj @@ -9,9 +9,9 @@ - - - + + + diff --git a/labs/5-Add-Checkout/end/eShop.ServiceDefaults/eShop.ServiceDefaults.csproj b/labs/5-Add-Checkout/end/eShop.ServiceDefaults/eShop.ServiceDefaults.csproj index 4c89643..bb4d68f 100644 --- a/labs/5-Add-Checkout/end/eShop.ServiceDefaults/eShop.ServiceDefaults.csproj +++ b/labs/5-Add-Checkout/end/eShop.ServiceDefaults/eShop.ServiceDefaults.csproj @@ -13,16 +13,16 @@ - - - - - - - - + + + + + + + + - - + + diff --git a/labs/5-Add-Checkout/src/Basket.API/Basket.API.csproj b/labs/5-Add-Checkout/src/Basket.API/Basket.API.csproj index 6f26a2d..ecba322 100644 --- a/labs/5-Add-Checkout/src/Basket.API/Basket.API.csproj +++ b/labs/5-Add-Checkout/src/Basket.API/Basket.API.csproj @@ -8,8 +8,8 @@ - - + + diff --git a/labs/5-Add-Checkout/src/Catalog.Data.Manager/Catalog.Data.Manager.csproj b/labs/5-Add-Checkout/src/Catalog.Data.Manager/Catalog.Data.Manager.csproj index 15801b7..046e3bc 100644 --- a/labs/5-Add-Checkout/src/Catalog.Data.Manager/Catalog.Data.Manager.csproj +++ b/labs/5-Add-Checkout/src/Catalog.Data.Manager/Catalog.Data.Manager.csproj @@ -13,8 +13,8 @@ - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/labs/5-Add-Checkout/src/Catalog.Data/Catalog.Data.csproj b/labs/5-Add-Checkout/src/Catalog.Data/Catalog.Data.csproj index ab16dee..4db6c99 100644 --- a/labs/5-Add-Checkout/src/Catalog.Data/Catalog.Data.csproj +++ b/labs/5-Add-Checkout/src/Catalog.Data/Catalog.Data.csproj @@ -8,7 +8,7 @@ - + diff --git a/labs/5-Add-Checkout/src/Ordering.Data.Manager/Ordering.Data.Manager.csproj b/labs/5-Add-Checkout/src/Ordering.Data.Manager/Ordering.Data.Manager.csproj index 0bcd4af..8978236 100644 --- a/labs/5-Add-Checkout/src/Ordering.Data.Manager/Ordering.Data.Manager.csproj +++ b/labs/5-Add-Checkout/src/Ordering.Data.Manager/Ordering.Data.Manager.csproj @@ -13,8 +13,8 @@ - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/labs/5-Add-Checkout/src/Ordering.Data/Ordering.Data.csproj b/labs/5-Add-Checkout/src/Ordering.Data/Ordering.Data.csproj index a26c594..d031682 100644 --- a/labs/5-Add-Checkout/src/Ordering.Data/Ordering.Data.csproj +++ b/labs/5-Add-Checkout/src/Ordering.Data/Ordering.Data.csproj @@ -8,6 +8,6 @@ - + diff --git a/labs/5-Add-Checkout/src/WebApp/WebApp.csproj b/labs/5-Add-Checkout/src/WebApp/WebApp.csproj index 09265da..26aea62 100644 --- a/labs/5-Add-Checkout/src/WebApp/WebApp.csproj +++ b/labs/5-Add-Checkout/src/WebApp/WebApp.csproj @@ -11,10 +11,10 @@ - - - - + + + + diff --git a/labs/5-Add-Checkout/src/eShop.AppHost/eShop.AppHost.csproj b/labs/5-Add-Checkout/src/eShop.AppHost/eShop.AppHost.csproj index a5117b4..2ae9428 100644 --- a/labs/5-Add-Checkout/src/eShop.AppHost/eShop.AppHost.csproj +++ b/labs/5-Add-Checkout/src/eShop.AppHost/eShop.AppHost.csproj @@ -9,9 +9,9 @@ - - - + + + diff --git a/labs/5-Add-Checkout/src/eShop.ServiceDefaults/eShop.ServiceDefaults.csproj b/labs/5-Add-Checkout/src/eShop.ServiceDefaults/eShop.ServiceDefaults.csproj index 4c89643..bb4d68f 100644 --- a/labs/5-Add-Checkout/src/eShop.ServiceDefaults/eShop.ServiceDefaults.csproj +++ b/labs/5-Add-Checkout/src/eShop.ServiceDefaults/eShop.ServiceDefaults.csproj @@ -13,16 +13,16 @@ - - - - - - - - + + + + + + + + - - + + diff --git a/labs/6-Add-Resiliency/src/Basket.API/Basket.API.csproj b/labs/6-Add-Resiliency/src/Basket.API/Basket.API.csproj index a54346c..b257037 100644 --- a/labs/6-Add-Resiliency/src/Basket.API/Basket.API.csproj +++ b/labs/6-Add-Resiliency/src/Basket.API/Basket.API.csproj @@ -6,8 +6,8 @@ - - + + diff --git a/labs/6-Add-Resiliency/src/Catalog.Data.Manager/Catalog.Data.Manager.csproj b/labs/6-Add-Resiliency/src/Catalog.Data.Manager/Catalog.Data.Manager.csproj index 15801b7..046e3bc 100644 --- a/labs/6-Add-Resiliency/src/Catalog.Data.Manager/Catalog.Data.Manager.csproj +++ b/labs/6-Add-Resiliency/src/Catalog.Data.Manager/Catalog.Data.Manager.csproj @@ -13,8 +13,8 @@ - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/labs/6-Add-Resiliency/src/Catalog.Data/Catalog.Data.csproj b/labs/6-Add-Resiliency/src/Catalog.Data/Catalog.Data.csproj index ab16dee..4db6c99 100644 --- a/labs/6-Add-Resiliency/src/Catalog.Data/Catalog.Data.csproj +++ b/labs/6-Add-Resiliency/src/Catalog.Data/Catalog.Data.csproj @@ -8,7 +8,7 @@ - + diff --git a/labs/6-Add-Resiliency/src/Ordering.API/Ordering.API.csproj b/labs/6-Add-Resiliency/src/Ordering.API/Ordering.API.csproj index bba5fdf..602bc5b 100644 --- a/labs/6-Add-Resiliency/src/Ordering.API/Ordering.API.csproj +++ b/labs/6-Add-Resiliency/src/Ordering.API/Ordering.API.csproj @@ -15,7 +15,7 @@ - + \ No newline at end of file diff --git a/labs/6-Add-Resiliency/src/Ordering.Data.Manager/Ordering.Data.Manager.csproj b/labs/6-Add-Resiliency/src/Ordering.Data.Manager/Ordering.Data.Manager.csproj index 0bcd4af..8978236 100644 --- a/labs/6-Add-Resiliency/src/Ordering.Data.Manager/Ordering.Data.Manager.csproj +++ b/labs/6-Add-Resiliency/src/Ordering.Data.Manager/Ordering.Data.Manager.csproj @@ -13,8 +13,8 @@ - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/labs/6-Add-Resiliency/src/Ordering.Data/Ordering.Data.csproj b/labs/6-Add-Resiliency/src/Ordering.Data/Ordering.Data.csproj index 8c7bde6..102bf09 100644 --- a/labs/6-Add-Resiliency/src/Ordering.Data/Ordering.Data.csproj +++ b/labs/6-Add-Resiliency/src/Ordering.Data/Ordering.Data.csproj @@ -8,6 +8,6 @@ - + diff --git a/labs/6-Add-Resiliency/src/WebApp/WebApp.csproj b/labs/6-Add-Resiliency/src/WebApp/WebApp.csproj index 09265da..26aea62 100644 --- a/labs/6-Add-Resiliency/src/WebApp/WebApp.csproj +++ b/labs/6-Add-Resiliency/src/WebApp/WebApp.csproj @@ -11,10 +11,10 @@ - - - - + + + + diff --git a/labs/6-Add-Resiliency/src/eShop.AppHost/eShop.AppHost.csproj b/labs/6-Add-Resiliency/src/eShop.AppHost/eShop.AppHost.csproj index cd618b5..7bc5782 100644 --- a/labs/6-Add-Resiliency/src/eShop.AppHost/eShop.AppHost.csproj +++ b/labs/6-Add-Resiliency/src/eShop.AppHost/eShop.AppHost.csproj @@ -9,9 +9,9 @@ - - - + + + diff --git a/labs/6-Add-Resiliency/src/eShop.ServiceDefaults/eShop.ServiceDefaults.csproj b/labs/6-Add-Resiliency/src/eShop.ServiceDefaults/eShop.ServiceDefaults.csproj index 4c89643..bb4d68f 100644 --- a/labs/6-Add-Resiliency/src/eShop.ServiceDefaults/eShop.ServiceDefaults.csproj +++ b/labs/6-Add-Resiliency/src/eShop.ServiceDefaults/eShop.ServiceDefaults.csproj @@ -13,16 +13,16 @@ - - - - - - - - + + + + + + + + - - + + diff --git a/src/Basket.API/Basket.API.csproj b/src/Basket.API/Basket.API.csproj index 6250bf7..17f13ac 100644 --- a/src/Basket.API/Basket.API.csproj +++ b/src/Basket.API/Basket.API.csproj @@ -7,8 +7,8 @@ - - + + diff --git a/src/Catalog.Data.Manager/Catalog.Data.Manager.csproj b/src/Catalog.Data.Manager/Catalog.Data.Manager.csproj index 15801b7..046e3bc 100644 --- a/src/Catalog.Data.Manager/Catalog.Data.Manager.csproj +++ b/src/Catalog.Data.Manager/Catalog.Data.Manager.csproj @@ -13,8 +13,8 @@ - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/Catalog.Data/Catalog.Data.csproj b/src/Catalog.Data/Catalog.Data.csproj index ab16dee..4db6c99 100644 --- a/src/Catalog.Data/Catalog.Data.csproj +++ b/src/Catalog.Data/Catalog.Data.csproj @@ -8,7 +8,7 @@ - + diff --git a/src/IntegrationTests/Infrastructure/DistributedApplicationExtensions.cs b/src/IntegrationTests/Infrastructure/DistributedApplicationExtensions.cs index a885404..2765d9b 100644 --- a/src/IntegrationTests/Infrastructure/DistributedApplicationExtensions.cs +++ b/src/IntegrationTests/Infrastructure/DistributedApplicationExtensions.cs @@ -7,46 +7,12 @@ using System.Security.Cryptography; using IntegrationTests.Infrastructure; using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; namespace IntegrationTests.Infrastructure; public static partial class DistributedApplicationExtensions { - internal const string OutputWriterKey = $"{nameof(DistributedApplicationExtensions)}.OutputWriter"; - - /// - /// Adds a background service to watch resource status changes and optionally logs. - /// - public static IServiceCollection AddResourceWatching(this IServiceCollection services) - { - // Add background service to watch resource status changes and optionally logs - services.AddSingleton(); - services.AddHostedService(sp => sp.GetRequiredService()); - - return services; - } - - /// - /// Configures the builder to write logs to the supplied and store for optional assertion later. - /// - public static TBuilder WriteOutputTo(this TBuilder builder, TextWriter outputWriter) - where TBuilder : IDistributedApplicationTestingBuilder - { - builder.Services.AddResourceWatching(); - - // Add a resource log store to capture logs from resources - builder.Services.AddSingleton(); - - // Configure the builder's logger to redirect it output & store for assertion later - builder.Services.AddKeyedSingleton(OutputWriterKey, outputWriter); - builder.Services.AddSingleton(); - builder.Services.AddSingleton(); - - return builder; - } - /// /// Ensures all parameters in the application configuration have values set. /// @@ -149,33 +115,6 @@ public static HttpClient CreateHttpClient(this DistributedApplication app, strin return httpClient; } - /// - public static async Task StartAsync(this DistributedApplication app, bool waitForResourcesToStart, CancellationToken cancellationToken = default) - { - var resourceWatcher = app.Services.GetRequiredService(); - var resourcesStartingTask = waitForResourcesToStart ? resourceWatcher.WaitForResourcesToStart() : Task.CompletedTask; - - await app.StartAsync(cancellationToken); - await resourcesStartingTask; - } - - public static LoggerLogStore GetAppHostLogs(this DistributedApplication app) - { - var logStore = app.Services.GetService() - ?? throw new InvalidOperationException($"Log store service was not registered. Ensure the '{nameof(WriteOutputTo)}' method is called before attempting to get AppHost logs."); - return logStore; - } - - /// - /// Gets the logs for all resources in the application. - /// - public static ResourceLogStore GetResourceLogs(this DistributedApplication app) - { - var logStore = app.Services.GetService() - ?? throw new InvalidOperationException($"Log store service was not registered. Ensure the '{nameof(WriteOutputTo)}' method is called before attempting to get resource logs."); ; - return logStore; - } - /// /// Attempts to apply EF migrations for the specified project by sending a request to the migrations endpoint /ApplyDatabaseMigrations. /// diff --git a/src/IntegrationTests/Infrastructure/LoggerLogStore.cs b/src/IntegrationTests/Infrastructure/LoggerLogStore.cs deleted file mode 100644 index 3d850dc..0000000 --- a/src/IntegrationTests/Infrastructure/LoggerLogStore.cs +++ /dev/null @@ -1,38 +0,0 @@ -using System.Collections.Concurrent; -using Microsoft.Extensions.Hosting; -using Microsoft.Extensions.Logging; - -namespace IntegrationTests.Infrastructure; - -/// -/// Stores logs from instances created from . -/// -public class LoggerLogStore(IHostEnvironment hostEnvironment) -{ - private readonly ConcurrentDictionary> _store = []; - - public void AddLog(string category, LogLevel level, string message, Exception? exception) - { - _store.GetOrAdd(category, _ => []).Add((DateTimeOffset.Now, category, level, message, exception)); - } - - public IReadOnlyDictionary> GetLogs() - { - return _store.ToDictionary(entry => entry.Key, entry => (IList<(DateTimeOffset, string, LogLevel, string, Exception?)>)entry.Value); - } - - public void EnsureNoErrors() - { - var logs = GetLogs(); - - var errors = logs.SelectMany(kvp => kvp.Value).Where(log => log.Level == LogLevel.Error || log.Level == LogLevel.Critical).ToList(); - //Where(category => category.Value.Any(log => log.Level == LogLevel.Error || log.Level == LogLevel.Critical)).ToList(); - if (errors.Count > 0) - { - var appName = hostEnvironment.ApplicationName; - throw new InvalidOperationException( - $"AppHost '{appName}' logged errors: {Environment.NewLine}" + - string.Join(Environment.NewLine, errors.Select(log => $"[{log.Category}] {log.Message}"))); - } - } -} diff --git a/src/IntegrationTests/Infrastructure/ResourceLogStore.cs b/src/IntegrationTests/Infrastructure/ResourceLogStore.cs deleted file mode 100644 index 14b3ba8..0000000 --- a/src/IntegrationTests/Infrastructure/ResourceLogStore.cs +++ /dev/null @@ -1,75 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System.Collections.Concurrent; - -namespace IntegrationTests.Infrastructure; - -public class ResourceLogStore -{ - private readonly ConcurrentDictionary> _logs = []; - - internal void Add(IResource resource, IEnumerable logs) - { - _logs.GetOrAdd(resource, _ => []).AddRange(logs); - } - - /// - /// Gets a snapshot of the logs for all resources. - /// - public IReadOnlyDictionary> GetLogs() => - _logs.ToDictionary(entry => entry.Key, entry => (IReadOnlyList)entry.Value); - - /// - /// Gets the logs for the specified resource in the application. - /// - public IReadOnlyList GetLogs(string resourceName) - { - var resource = _logs.Keys.FirstOrDefault(k => string.Equals(k.Name, resourceName, StringComparison.OrdinalIgnoreCase)); - if (resource is not null && _logs.TryGetValue(resource, out var logs)) - { - return logs; - } - return []; - } - - /// - /// Ensures no errors were logged for the specified resource. - /// - public void EnsureNoErrors(string resourceName) - { - EnsureNoErrors(r => string.Equals(r.Name, resourceName, StringComparison.OrdinalIgnoreCase)); - } - - /// - /// Ensures no errors were logged for the specified resources. - /// - public void EnsureNoErrors(Func? resourcePredicate = null, bool throwIfNoResourcesMatch = false) - { - var logStore = GetLogs(); - - var resourcesMatched = 0; - foreach (var (resource, logs) in logStore) - { - if (resourcePredicate is null || resourcePredicate(resource)) - { - EnsureNoErrors(resource, logs); - resourcesMatched++; - } - } - - if (throwIfNoResourcesMatch && resourcesMatched == 0 && resourcePredicate is not null) - { - throw new ArgumentException("No resources matched the predicate.", nameof(resourcePredicate)); - } - - static void EnsureNoErrors(IResource resource, IEnumerable logs) - { - var errors = logs.Where(l => l.IsErrorMessage).ToList(); - if (errors.Count > 0) - { - throw new InvalidOperationException($"Resource '{resource.Name}' logged errors: {Environment.NewLine}{string.Join(Environment.NewLine, errors.Select(e => e.Content))}"); - } - } - } -} diff --git a/src/IntegrationTests/Infrastructure/ResourceWatcher.cs b/src/IntegrationTests/Infrastructure/ResourceWatcher.cs deleted file mode 100644 index 10472a8..0000000 --- a/src/IntegrationTests/Infrastructure/ResourceWatcher.cs +++ /dev/null @@ -1,228 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Hosting; -using Microsoft.Extensions.Logging; - -namespace IntegrationTests.Infrastructure; - -/// -/// A background service that watches for resource start/stop notifications and logs resource state changes. -/// -internal sealed class ResourceWatcher( - DistributedApplicationModel appModel, - ResourceNotificationService resourceNotification, - ResourceLoggerService resourceLoggerService, - IServiceProvider serviceProvider, - ILogger logger) - : BackgroundService -{ - private readonly HashSet _waitingToStartResources = new(StringComparer.OrdinalIgnoreCase); - private readonly HashSet _startedResources = new(StringComparer.OrdinalIgnoreCase); - private readonly HashSet _waitingToStopResources = new(StringComparer.OrdinalIgnoreCase); - private readonly HashSet _stoppedResources = new(StringComparer.OrdinalIgnoreCase); - private readonly Dictionary _resourceState = []; - private readonly TaskCompletionSource _resourcesStartedTcs = new(); - private readonly TaskCompletionSource _resourcesStoppedTcs = new(); - - protected override async Task ExecuteAsync(CancellationToken stoppingToken) - { - logger.LogInformation("Resource watcher started"); - - var statusWatchableResources = GetStatusWatchableResources().ToList(); - statusWatchableResources.ForEach(r => - { - _waitingToStartResources.Add(r.Name); - _waitingToStopResources.Add(r.Name); - }); - logger.LogInformation("Watching {resourceCount} resources for start/stop changes", statusWatchableResources.Count); - - // We need to pass the stopping token in here because the ResourceNotificationService doesn't stop on host shutdown in preview.5 - await WatchNotifications(stoppingToken); - - logger.LogInformation("Resource watcher stopped"); - } - - public override void Dispose() - { - _resourcesStartedTcs.TrySetException(new DistributedApplicationException("Resource watcher was disposed while waiting for resources to start, likely due to a timeout")); - _resourcesStoppedTcs.TrySetException(new DistributedApplicationException("Resource watcher was disposed while waiting for resources to stop, likely due to a timeout")); - } - - public Task WaitForResourcesToStart() => _resourcesStartedTcs.Task; - - public Task WaitForResourcesToStop() => _resourcesStoppedTcs.Task; - - private async Task WatchNotifications(CancellationToken cancellationToken) - { - var logStore = serviceProvider.GetService(); - var outputWriter = serviceProvider.GetKeyedService(DistributedApplicationExtensions.OutputWriterKey); - var watchingLogs = logStore is not null || outputWriter is not null; - var loggingResourceIds = new HashSet(); - var logWatchTasks = new List(); - - logger.LogInformation("Waiting on {resourcesToStartCount} resources to start", _waitingToStartResources.Count); - - await foreach (var resourceEvent in resourceNotification.WatchAsync().WithCancellation(cancellationToken)) - { - var resourceName = resourceEvent.Resource.Name; - var resourceId = resourceEvent.ResourceId; - - if (watchingLogs && loggingResourceIds.Add(resourceId)) - { - // Start watching the logs for this resource ID - logWatchTasks.Add(WatchResourceLogs(logStore, outputWriter, resourceEvent.Resource, resourceId, cancellationToken)); - } - - _resourceState.TryGetValue(resourceName, out var prevState); - _resourceState[resourceName] = (resourceEvent.Snapshot.State, resourceEvent.Snapshot.ExitCode); - - if (resourceEvent.Snapshot.ExitCode is null && resourceEvent.Snapshot.State is { } newState && !string.IsNullOrEmpty(newState.Text)) - { - if (!string.Equals(prevState.Snapshot?.Text, newState.Text, StringComparison.OrdinalIgnoreCase)) - { - // Log resource state change - logger.LogInformation("Resource '{resourceName}' of type '{resourceType}' changed state: {oldState} -> {newState}", resourceId, resourceEvent.Resource.GetType().Name, prevState.Snapshot?.Text ?? "[null]", newState.Text); - - if (newState.Text.Contains("running", StringComparison.OrdinalIgnoreCase)) - { - // Resource started - HandleResourceStarted(resourceEvent.Resource); - } - else if (newState.Text.Contains("failedtostart", StringComparison.OrdinalIgnoreCase)) - { - // Resource failed to start - HandleResourceStartError(resourceName, $"Resource '{resourceName}' failed to start: {newState.Text}"); - } - else if (newState.Text.Contains("exited", StringComparison.OrdinalIgnoreCase)) - { - if (_waitingToStartResources.Contains(resourceEvent.Resource.Name)) - { - // Resource went straight to exited state - HandleResourceStartError(resourceName, $"Resource '{resourceName}' exited without first running: {newState.Text}"); - } - - // Resource stopped - HandleResourceStopped(resourceEvent.Resource); - } - else if (newState.Text.Contains("starting", StringComparison.OrdinalIgnoreCase) - || newState.Text.Contains("hidden", StringComparison.OrdinalIgnoreCase)) - { - // Resource is still starting - } - else if (!string.IsNullOrEmpty(newState.Text)) - { - logger.LogWarning("Unknown resource state encountered: {state}", newState.Text); - } - } - } - else if (resourceEvent.Snapshot.ExitCode is { } exitCode) - { - if (exitCode != 0) - { - if (_waitingToStartResources.Remove(resourceName)) - { - // Error starting resource - HandleResourceStartError(resourceName, $"Resource '{resourceName}' exited with exit code {exitCode}"); - } - HandleResourceStopError(resourceName, $"Resource '{resourceName}' exited with exit code {exitCode}"); - } - else - { - // Resource exited cleanly - HandleResourceStarted(resourceEvent.Resource, " (exited with code 0)"); - HandleResourceStopped(resourceEvent.Resource, " (exited with code 0)"); - } - } - - if (_waitingToStartResources.Count == 0) - { - logger.LogInformation("All resources started"); - _resourcesStartedTcs.TrySetResult(); - } - - if (_waitingToStopResources.Count == 0) - { - logger.LogInformation("All resources stopped"); - _resourcesStoppedTcs.TrySetResult(); - } - } - - void HandleResourceStartError(string resourceName, string message) - { - if (_waitingToStartResources.Remove(resourceName)) - { - _resourcesStartedTcs.TrySetException(new DistributedApplicationException(message)); - } - _waitingToStopResources.Remove(resourceName); - _stoppedResources.Add(resourceName); - } - - void HandleResourceStopError(string resourceName, string message) - { - _waitingToStartResources.Remove(resourceName); - if (_waitingToStopResources.Remove(resourceName)) - { - _resourcesStoppedTcs.TrySetException(new DistributedApplicationException(message)); - } - _stoppedResources.Add(resourceName); - } - - void HandleResourceStarted(IResource resource, string? suffix = null) - { - if (_waitingToStartResources.Remove(resource.Name) && _startedResources.Add(resource.Name)) - { -#pragma warning disable CA2254 // Template should be a static expression: suffix is not log data - logger.LogInformation($"Resource '{{resourceName}}' started{suffix}", resource.Name); -#pragma warning restore CA2254 - } - - if (_waitingToStartResources.Count > 0) - { - var resourceNames = string.Join(", ", _waitingToStartResources.Select(r => r)); - logger.LogInformation("Still waiting on {resourcesToStartCount} resources to start: {resourcesToStart}", _waitingToStartResources.Count, resourceNames); - } - } - - void HandleResourceStopped(IResource resource, string? suffix = null) - { - if (_waitingToStopResources.Remove(resource.Name) && _stoppedResources.Add(resource.Name)) - { -#pragma warning disable CA2254 // Template should be a static expression: suffix is not log data - logger.LogInformation($"Resource '{{resourceName}}' stopped{suffix}", resource.Name); -#pragma warning restore CA2254 - } - - if (_waitingToStopResources.Count > 0) - { - var resourceNames = string.Join(", ", _waitingToStopResources.Select(r => r)); - logger.LogInformation("Still waiting on {resourcesToStartCount} resources to stop: {resourcesToStart}", _waitingToStopResources.Count, resourceNames); - } - } - - await Task.WhenAll(logWatchTasks); - } - - private async Task WatchResourceLogs(ResourceLogStore? logStore, TextWriter? outputWriter, IResource resource, string resourceId, CancellationToken cancellationToken) - { - if (logStore is not null || outputWriter is not null) - { - await foreach (var logEvent in resourceLoggerService.WatchAsync(resourceId).WithCancellation(cancellationToken)) - { - logStore?.Add(resource, logEvent); - - foreach (var line in logEvent) - { - var kind = line.IsErrorMessage ? "error" : "log"; - outputWriter?.WriteLine("{0} Resource '{1}' {2}: {3}", DateTime.Now.ToString("O"), resource.Name, kind, line.Content); - } - } - } - } - - private IEnumerable GetStatusWatchableResources() - { - return appModel.Resources.Where(r => r is ContainerResource || r is ExecutableResource || r is ProjectResource); - } -} diff --git a/src/IntegrationTests/Infrastructure/StoredLogsLogger.cs b/src/IntegrationTests/Infrastructure/StoredLogsLogger.cs deleted file mode 100644 index a513c8b..0000000 --- a/src/IntegrationTests/Infrastructure/StoredLogsLogger.cs +++ /dev/null @@ -1,26 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using Microsoft.Extensions.Logging; - -namespace IntegrationTests.Infrastructure; - -/// -/// A logger that stores logs in a . -/// -/// -/// -/// -internal class StoredLogsLogger(LoggerLogStore logStore, LoggerExternalScopeProvider scopeProvider, string categoryName) : ILogger -{ - public string CategoryName { get; } = categoryName; - - public IDisposable? BeginScope(TState state) where TState : notnull => scopeProvider.Push(state); - - public bool IsEnabled(LogLevel logLevel) => logLevel != LogLevel.None; - - public void Log(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func formatter) - { - logStore.AddLog(CategoryName, logLevel, formatter(state, exception), exception); - } -} diff --git a/src/IntegrationTests/Infrastructure/StoredLogsLoggerProvider.cs b/src/IntegrationTests/Infrastructure/StoredLogsLoggerProvider.cs deleted file mode 100644 index 0b4c796..0000000 --- a/src/IntegrationTests/Infrastructure/StoredLogsLoggerProvider.cs +++ /dev/null @@ -1,23 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using Microsoft.Extensions.Logging; - -namespace IntegrationTests.Infrastructure; - -/// -/// A logger provider that stores logs in an . -/// -internal class StoredLogsLoggerProvider(LoggerLogStore logStore) : ILoggerProvider -{ - private readonly LoggerExternalScopeProvider _scopeProvider = new(); - - public ILogger CreateLogger(string categoryName) - { - return new StoredLogsLogger(logStore, _scopeProvider, categoryName); - } - - public void Dispose() - { - } -} diff --git a/src/IntegrationTests/Infrastructure/XUnitExtensions.cs b/src/IntegrationTests/Infrastructure/XUnitExtensions.cs deleted file mode 100644 index 29d9f0c..0000000 --- a/src/IntegrationTests/Infrastructure/XUnitExtensions.cs +++ /dev/null @@ -1,40 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; -using Xunit.Abstractions; - -namespace IntegrationTests.Infrastructure; - -internal static partial class DistributedApplicationTestFactory -{ - ///// - ///// Creates an for the specified app host assembly and outputs logs to the provided . - ///// - //public static async Task CreateAsync(string appHostAssemblyPath, ITestOutputHelper testOutputHelper) - //{ - // var builder = await CreateAsync(appHostAssemblyPath, new XUnitTextWriter(testOutputHelper)); - // builder.Services.AddSingleton(); - // builder.Services.AddSingleton(testOutputHelper); - // return builder; - //} - - /// - /// Writes messages and resource logs to the provided . - /// - /// The builder. - /// The output. - /// The builder. - public static IDistributedApplicationTestingBuilder WriteOutputTo(this IDistributedApplicationTestingBuilder builder, ITestOutputHelper testOutputHelper) - { - // Enable the core ILogger and resource output capturing - builder.WriteOutputTo(new XUnitTextWriter(testOutputHelper)); - - // Enable ILogger going to xUnit output - builder.Services.AddSingleton(testOutputHelper); - builder.Services.AddSingleton(); - - return builder; - } -} diff --git a/src/IntegrationTests/Infrastructure/XUnitLogger.cs b/src/IntegrationTests/Infrastructure/XUnitLogger.cs deleted file mode 100644 index ab5b1ea..0000000 --- a/src/IntegrationTests/Infrastructure/XUnitLogger.cs +++ /dev/null @@ -1,57 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System.Text; -using Microsoft.Extensions.Logging; -using Xunit.Abstractions; - -namespace IntegrationTests.Infrastructure; - -/// -/// An that writes log messages to an . -/// -internal class XUnitLogger(ITestOutputHelper testOutputHelper, LoggerExternalScopeProvider scopeProvider, string categoryName) : ILogger -{ - public bool IsEnabled(LogLevel logLevel) => logLevel != LogLevel.None; - - public IDisposable? BeginScope(TState state) where TState : notnull => scopeProvider.Push(state); - - public void Log(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func formatter) - { - var sb = new StringBuilder(); - - sb.Append(DateTime.Now.ToString("O")).Append(' ') - .Append(GetLogLevelString(logLevel)) - .Append(" [").Append(categoryName).Append("] ") - .Append(formatter(state, exception)); - - if (exception is not null) - { - sb.AppendLine().Append(exception); - } - - // Append scopes - scopeProvider.ForEachScope((scope, state) => - { - state.AppendLine(); - state.Append(" => "); - state.Append(scope); - }, sb); - - testOutputHelper.WriteLine(sb.ToString()); - } - - private static string GetLogLevelString(LogLevel logLevel) - { - return logLevel switch - { - LogLevel.Trace => "trce", - LogLevel.Debug => "dbug", - LogLevel.Information => "info", - LogLevel.Warning => "warn", - LogLevel.Error => "fail", - LogLevel.Critical => "crit", - _ => throw new ArgumentOutOfRangeException(nameof(logLevel)) - }; - } -} diff --git a/src/IntegrationTests/Infrastructure/XUnitLoggerProvider.cs b/src/IntegrationTests/Infrastructure/XUnitLoggerProvider.cs deleted file mode 100644 index 235f351..0000000 --- a/src/IntegrationTests/Infrastructure/XUnitLoggerProvider.cs +++ /dev/null @@ -1,24 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using Microsoft.Extensions.Logging; -using Xunit.Abstractions; - -namespace IntegrationTests.Infrastructure; - -/// -/// An that creates instances that output to the supplied . -/// -internal class XUnitLoggerProvider(ITestOutputHelper testOutputHelper) : ILoggerProvider -{ - private readonly LoggerExternalScopeProvider _scopeProvider = new(); - - public ILogger CreateLogger(string categoryName) - { - return new XUnitLogger(testOutputHelper, _scopeProvider, categoryName); - } - - public void Dispose() - { - } -} diff --git a/src/IntegrationTests/Infrastructure/XUnitTextWriter.cs b/src/IntegrationTests/Infrastructure/XUnitTextWriter.cs deleted file mode 100644 index 31a3046..0000000 --- a/src/IntegrationTests/Infrastructure/XUnitTextWriter.cs +++ /dev/null @@ -1,33 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System.Text; -using Xunit.Abstractions; - -namespace IntegrationTests.Infrastructure; - -/// -/// A that writes to an . -/// -internal class XUnitTextWriter(ITestOutputHelper output) : TextWriter -{ - private readonly StringBuilder _sb = new(); - - public override Encoding Encoding => Encoding.Unicode; - - public override void Write(char value) - { - if (value == '\r' || value == '\n') - { - if (_sb.Length > 0) - { - output.WriteLine(_sb.ToString()); - _sb.Clear(); - } - } - else - { - _sb.Append(value); - } - } -} diff --git a/src/IntegrationTests/IntegrationTests.csproj b/src/IntegrationTests/IntegrationTests.csproj index 5fabb33..c211edd 100644 --- a/src/IntegrationTests/IntegrationTests.csproj +++ b/src/IntegrationTests/IntegrationTests.csproj @@ -9,12 +9,19 @@ - + - - - - + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + diff --git a/src/IntegrationTests/WebAppTests.cs b/src/IntegrationTests/WebAppTests.cs index f4089a7..a676f7a 100644 --- a/src/IntegrationTests/WebAppTests.cs +++ b/src/IntegrationTests/WebAppTests.cs @@ -1,6 +1,7 @@ using System.Net; using IntegrationTests.Infrastructure; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; using Xunit.Abstractions; namespace IntegrationTests; @@ -11,7 +12,9 @@ public class WebAppTests(ITestOutputHelper outputHelper) public async Task GetWebAppUrlsReturnsOkStatusCode() { var appHostBuilder = await DistributedApplicationTestingBuilder.CreateAsync(); - appHostBuilder.WriteOutputTo(outputHelper); + + appHostBuilder.Services.AddLogging(logging => logging.AddXUnit(outputHelper)); + appHostBuilder.WithRandomParameterValues(); appHostBuilder.WithRandomVolumeNames(); @@ -30,7 +33,11 @@ public async Task GetWebAppUrlsReturnsOkStatusCode() }); await using var app = await appHostBuilder.BuildAsync(); - await app.StartAsync(waitForResourcesToStart: true); + + var notificationService = app.Services.GetRequiredService(); + await notificationService.WaitForResourceAsync("webapp").WaitAsync(TimeSpan.FromSeconds(30)); + + await app.StartAsync(); var httpClient = app.CreateHttpClient("webapp"); diff --git a/src/Ordering.API/Ordering.API.csproj b/src/Ordering.API/Ordering.API.csproj index bba5fdf..602bc5b 100644 --- a/src/Ordering.API/Ordering.API.csproj +++ b/src/Ordering.API/Ordering.API.csproj @@ -15,7 +15,7 @@ - + \ No newline at end of file diff --git a/src/Ordering.Data.Manager/Ordering.Data.Manager.csproj b/src/Ordering.Data.Manager/Ordering.Data.Manager.csproj index 0bcd4af..8978236 100644 --- a/src/Ordering.Data.Manager/Ordering.Data.Manager.csproj +++ b/src/Ordering.Data.Manager/Ordering.Data.Manager.csproj @@ -13,8 +13,8 @@ - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/Ordering.Data/Ordering.Data.csproj b/src/Ordering.Data/Ordering.Data.csproj index 8c7bde6..102bf09 100644 --- a/src/Ordering.Data/Ordering.Data.csproj +++ b/src/Ordering.Data/Ordering.Data.csproj @@ -8,6 +8,6 @@ - + diff --git a/src/WebApp/WebApp.csproj b/src/WebApp/WebApp.csproj index 09265da..55b3ba9 100644 --- a/src/WebApp/WebApp.csproj +++ b/src/WebApp/WebApp.csproj @@ -11,10 +11,10 @@ - - - - + + + + diff --git a/src/eShop.AppHost/eShop.AppHost.csproj b/src/eShop.AppHost/eShop.AppHost.csproj index cd618b5..7bc5782 100644 --- a/src/eShop.AppHost/eShop.AppHost.csproj +++ b/src/eShop.AppHost/eShop.AppHost.csproj @@ -9,9 +9,9 @@ - - - + + + diff --git a/src/eShop.ServiceDefaults/eShop.ServiceDefaults.csproj b/src/eShop.ServiceDefaults/eShop.ServiceDefaults.csproj index 4c89643..bb4d68f 100644 --- a/src/eShop.ServiceDefaults/eShop.ServiceDefaults.csproj +++ b/src/eShop.ServiceDefaults/eShop.ServiceDefaults.csproj @@ -13,16 +13,16 @@ - - - - - - - - + + + + + + + + - - + +