diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Filters/AuthorizeCheckOperationFilter.cs b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Filters/AuthorizeCheckOperationFilter.cs index e6a0bf56b..11473d1c1 100644 --- a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Filters/AuthorizeCheckOperationFilter.cs +++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Filters/AuthorizeCheckOperationFilter.cs @@ -22,7 +22,7 @@ operation.Security = new List { - new OpenApiSecurityRequirement + new() { [ oAuthScheme ] = new [] { "Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator" } } diff --git a/src/ApiGateways/Web.Bff.Shopping/aggregator/Filters/AuthorizeCheckOperationFilter.cs b/src/ApiGateways/Web.Bff.Shopping/aggregator/Filters/AuthorizeCheckOperationFilter.cs index a0aed7b5d..99bf07048 100644 --- a/src/ApiGateways/Web.Bff.Shopping/aggregator/Filters/AuthorizeCheckOperationFilter.cs +++ b/src/ApiGateways/Web.Bff.Shopping/aggregator/Filters/AuthorizeCheckOperationFilter.cs @@ -22,7 +22,7 @@ operation.Security = new List { - new OpenApiSecurityRequirement + new() { [ oAuthScheme ] = new[] { "Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator" } } diff --git a/src/BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.cs b/src/BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.cs index 9b45eb996..31f85a339 100644 --- a/src/BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.cs +++ b/src/BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.cs @@ -34,17 +34,15 @@ public class EventBusRabbitMQ : IEventBus, IDisposable _persistentConnection.TryConnect(); } - using (var channel = _persistentConnection.CreateModel()) - { - channel.QueueUnbind(queue: _queueName, - exchange: BROKER_NAME, - routingKey: eventName); + using var channel = _persistentConnection.CreateModel(); + channel.QueueUnbind(queue: _queueName, + exchange: BROKER_NAME, + routingKey: eventName); - if (_subsManager.IsEmpty) - { - _queueName = string.Empty; - _consumerChannel.Close(); - } + if (_subsManager.IsEmpty) + { + _queueName = string.Empty; + _consumerChannel.Close(); } } @@ -66,32 +64,30 @@ public class EventBusRabbitMQ : IEventBus, IDisposable _logger.LogTrace("Creating RabbitMQ channel to publish event: {EventId} ({EventName})", @event.Id, eventName); - using (var channel = _persistentConnection.CreateModel()) - { - _logger.LogTrace("Declaring RabbitMQ exchange to publish event: {EventId}", @event.Id); + using var channel = _persistentConnection.CreateModel(); + _logger.LogTrace("Declaring RabbitMQ exchange to publish event: {EventId}", @event.Id); - channel.ExchangeDeclare(exchange: BROKER_NAME, type: "direct"); - - var body = JsonSerializer.SerializeToUtf8Bytes(@event, @event.GetType(), new JsonSerializerOptions - { - WriteIndented = true - }); + channel.ExchangeDeclare(exchange: BROKER_NAME, type: "direct"); - policy.Execute(() => - { - var properties = channel.CreateBasicProperties(); - properties.DeliveryMode = 2; // persistent + var body = JsonSerializer.SerializeToUtf8Bytes(@event, @event.GetType(), new JsonSerializerOptions + { + WriteIndented = true + }); + + policy.Execute(() => + { + var properties = channel.CreateBasicProperties(); + properties.DeliveryMode = 2; // persistent _logger.LogTrace("Publishing event to RabbitMQ: {EventId}", @event.Id); - channel.BasicPublish( - exchange: BROKER_NAME, - routingKey: eventName, - mandatory: true, - basicProperties: properties, - body: body); - }); - } + channel.BasicPublish( + exchange: BROKER_NAME, + routingKey: eventName, + mandatory: true, + basicProperties: properties, + body: body); + }); } public void SubscribeDynamic(string eventName) @@ -244,30 +240,27 @@ public class EventBusRabbitMQ : IEventBus, IDisposable if (_subsManager.HasSubscriptionsForEvent(eventName)) { - using (var scope = _autofac.BeginLifetimeScope(AUTOFAC_SCOPE_NAME)) + using var scope = _autofac.BeginLifetimeScope(AUTOFAC_SCOPE_NAME); + var subscriptions = _subsManager.GetHandlersForEvent(eventName); + foreach (var subscription in subscriptions) { - var subscriptions = _subsManager.GetHandlersForEvent(eventName); - foreach (var subscription in subscriptions) + if (subscription.IsDynamic) + { + if (scope.ResolveOptional(subscription.HandlerType) is not IDynamicIntegrationEventHandler handler) continue; + using dynamic eventData = JsonDocument.Parse(message); + await Task.Yield(); + await handler.Handle(eventData); + } + else { - if (subscription.IsDynamic) - { - var handler = scope.ResolveOptional(subscription.HandlerType) as IDynamicIntegrationEventHandler; - if (handler == null) continue; - using dynamic eventData = JsonDocument.Parse(message); - await Task.Yield(); - await handler.Handle(eventData); - } - else - { - var handler = scope.ResolveOptional(subscription.HandlerType); - if (handler == null) continue; - var eventType = _subsManager.GetEventTypeByName(eventName); - var integrationEvent = JsonSerializer.Deserialize(message, eventType, new JsonSerializerOptions() { PropertyNameCaseInsensitive= true}); - var concreteType = typeof(IIntegrationEventHandler<>).MakeGenericType(eventType); - - await Task.Yield(); - await (Task)concreteType.GetMethod("Handle").Invoke(handler, new object[] { integrationEvent }); - } + var handler = scope.ResolveOptional(subscription.HandlerType); + if (handler == null) continue; + var eventType = _subsManager.GetEventTypeByName(eventName); + var integrationEvent = JsonSerializer.Deserialize(message, eventType, new JsonSerializerOptions() { PropertyNameCaseInsensitive = true }); + var concreteType = typeof(IIntegrationEventHandler<>).MakeGenericType(eventType); + + await Task.Yield(); + await (Task)concreteType.GetMethod("Handle").Invoke(handler, new object[] { integrationEvent }); } } } diff --git a/src/BuildingBlocks/EventBus/EventBusServiceBus/EventBusServiceBus.cs b/src/BuildingBlocks/EventBus/EventBusServiceBus/EventBusServiceBus.cs index c53c56b98..52c5f50e4 100644 --- a/src/BuildingBlocks/EventBus/EventBusServiceBus/EventBusServiceBus.cs +++ b/src/BuildingBlocks/EventBus/EventBusServiceBus/EventBusServiceBus.cs @@ -155,32 +155,29 @@ public class EventBusServiceBus : IEventBus, IDisposable var processed = false; if (_subsManager.HasSubscriptionsForEvent(eventName)) { - using (var scope = _autofac.BeginLifetimeScope(AUTOFAC_SCOPE_NAME)) + var scope = _autofac.BeginLifetimeScope(AUTOFAC_SCOPE_NAME); + var subscriptions = _subsManager.GetHandlersForEvent(eventName); + foreach (var subscription in subscriptions) { - var subscriptions = _subsManager.GetHandlersForEvent(eventName); - foreach (var subscription in subscriptions) + if (subscription.IsDynamic) { - if (subscription.IsDynamic) - { - var handler = scope.ResolveOptional(subscription.HandlerType) as IDynamicIntegrationEventHandler; - if (handler == null) continue; - - using dynamic eventData = JsonDocument.Parse(message); - await handler.Handle(eventData); - } - else - { - var handler = scope.ResolveOptional(subscription.HandlerType); - if (handler == null) continue; - var eventType = _subsManager.GetEventTypeByName(eventName); - var integrationEvent = JsonSerializer.Deserialize(message, eventType); - var concreteType = typeof(IIntegrationEventHandler<>).MakeGenericType(eventType); - await (Task)concreteType.GetMethod("Handle").Invoke(handler, new object[] { integrationEvent }); - } + if (scope.ResolveOptional(subscription.HandlerType) is not IDynamicIntegrationEventHandler handler) continue; + + using dynamic eventData = JsonDocument.Parse(message); + await handler.Handle(eventData); + } + else + { + var handler = scope.ResolveOptional(subscription.HandlerType); + if (handler == null) continue; + var eventType = _subsManager.GetEventTypeByName(eventName); + var integrationEvent = JsonSerializer.Deserialize(message, eventType); + var concreteType = typeof(IIntegrationEventHandler<>).MakeGenericType(eventType); + await (Task)concreteType.GetMethod("Handle").Invoke(handler, new object[] { integrationEvent }); } } - processed = true; } + processed = true; return processed; } diff --git a/src/BuildingBlocks/EventBus/IntegrationEventLogEF/Utilities/ResilientTransaction.cs b/src/BuildingBlocks/EventBus/IntegrationEventLogEF/Utilities/ResilientTransaction.cs index 23022729b..5ba8093b2 100644 --- a/src/BuildingBlocks/EventBus/IntegrationEventLogEF/Utilities/ResilientTransaction.cs +++ b/src/BuildingBlocks/EventBus/IntegrationEventLogEF/Utilities/ResilientTransaction.cs @@ -15,11 +15,9 @@ public class ResilientTransaction var strategy = _context.Database.CreateExecutionStrategy(); await strategy.ExecuteAsync(async () => { - using (var transaction = _context.Database.BeginTransaction()) - { - await action(); - transaction.Commit(); - } + using var transaction = _context.Database.BeginTransaction(); + await action(); + transaction.Commit(); }); } } diff --git a/src/BuildingBlocks/WebHostCustomization/WebHost.Customization/WebHostExtensions.cs b/src/BuildingBlocks/WebHostCustomization/WebHost.Customization/WebHostExtensions.cs index 6316ae59d..3c7fc105a 100644 --- a/src/BuildingBlocks/WebHostCustomization/WebHost.Customization/WebHostExtensions.cs +++ b/src/BuildingBlocks/WebHostCustomization/WebHost.Customization/WebHostExtensions.cs @@ -21,48 +21,46 @@ namespace Microsoft.AspNetCore.Hosting { var underK8s = webHost.IsInKubernetes(); - using (var scope = webHost.Services.CreateScope()) + using var scope = webHost.Services.CreateScope(); + var services = scope.ServiceProvider; + var logger = services.GetRequiredService>(); + var context = services.GetService(); + + try { - var services = scope.ServiceProvider; - var logger = services.GetRequiredService>(); - var context = services.GetService(); + logger.LogInformation("Migrating database associated with context {DbContextName}", typeof(TContext).Name); - try + if (underK8s) { - logger.LogInformation("Migrating database associated with context {DbContextName}", typeof(TContext).Name); - - if (underK8s) - { - InvokeSeeder(seeder, context, services); - } - else - { - var retries = 10; - var retry = Policy.Handle() - .WaitAndRetry( - retryCount: retries, - sleepDurationProvider: retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)), - onRetry: (exception, timeSpan, retry, ctx) => - { - logger.LogWarning(exception, "[{prefix}] Exception {ExceptionType} with message {Message} detected on attempt {retry} of {retries}", nameof(TContext), exception.GetType().Name, exception.Message, retry, retries); - }); - - //if the sql server container is not created on run docker compose this - //migration can't fail for network related exception. The retry options for DbContext only - //apply to transient exceptions - // Note that this is NOT applied when running some orchestrators (let the orchestrator to recreate the failing service) - retry.Execute(() => InvokeSeeder(seeder, context, services)); - } + InvokeSeeder(seeder, context, services); + } + else + { + var retries = 10; + var retry = Policy.Handle() + .WaitAndRetry( + retryCount: retries, + sleepDurationProvider: retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)), + onRetry: (exception, timeSpan, retry, ctx) => + { + logger.LogWarning(exception, "[{prefix}] Exception {ExceptionType} with message {Message} detected on attempt {retry} of {retries}", nameof(TContext), exception.GetType().Name, exception.Message, retry, retries); + }); - logger.LogInformation("Migrated database associated with context {DbContextName}", typeof(TContext).Name); + //if the sql server container is not created on run docker compose this + //migration can't fail for network related exception. The retry options for DbContext only + //apply to transient exceptions + // Note that this is NOT applied when running some orchestrators (let the orchestrator to recreate the failing service) + retry.Execute(() => InvokeSeeder(seeder, context, services)); } - catch (Exception ex) + + logger.LogInformation("Migrated database associated with context {DbContextName}", typeof(TContext).Name); + } + catch (Exception ex) + { + logger.LogError(ex, "An error occurred while migrating the database used on context {DbContextName}", typeof(TContext).Name); + if (underK8s) { - logger.LogError(ex, "An error occurred while migrating the database used on context {DbContextName}", typeof(TContext).Name); - if (underK8s) - { - throw; // Rethrow under k8s because we rely on k8s to re-run the pod - } + throw; // Rethrow under k8s because we rely on k8s to re-run the pod } } diff --git a/src/Services/Basket/Basket.API/Infrastructure/Middlewares/AuthorizeCheckOperationFilter.cs b/src/Services/Basket/Basket.API/Infrastructure/Middlewares/AuthorizeCheckOperationFilter.cs index 0957614f9..9608ec0a7 100644 --- a/src/Services/Basket/Basket.API/Infrastructure/Middlewares/AuthorizeCheckOperationFilter.cs +++ b/src/Services/Basket/Basket.API/Infrastructure/Middlewares/AuthorizeCheckOperationFilter.cs @@ -20,7 +20,7 @@ public class AuthorizeCheckOperationFilter : IOperationFilter operation.Security = new List { - new OpenApiSecurityRequirement + new() { [ oAuthScheme ] = new [] { "basketapi" } } diff --git a/src/Services/Basket/Basket.FunctionalTests/BasketScenarios.cs b/src/Services/Basket/Basket.FunctionalTests/BasketScenarios.cs index 7032dcbe2..f727b999e 100644 --- a/src/Services/Basket/Basket.FunctionalTests/BasketScenarios.cs +++ b/src/Services/Basket/Basket.FunctionalTests/BasketScenarios.cs @@ -6,45 +6,39 @@ public class BasketScenarios [Fact] public async Task Post_basket_and_response_ok_status_code() { - using (var server = CreateServer()) - { - var content = new StringContent(BuildBasket(), UTF8Encoding.UTF8, "application/json"); - var response = await server.CreateClient() - .PostAsync(Post.Basket, content); + using var server = CreateServer(); + var content = new StringContent(BuildBasket(), UTF8Encoding.UTF8, "application/json"); + var response = await server.CreateClient() + .PostAsync(Post.Basket, content); - response.EnsureSuccessStatusCode(); - } + response.EnsureSuccessStatusCode(); } [Fact] public async Task Get_basket_and_response_ok_status_code() { - using (var server = CreateServer()) - { - var response = await server.CreateClient() - .GetAsync(Get.GetBasket(1)); + using var server = CreateServer(); + var response = await server.CreateClient() + .GetAsync(Get.GetBasket(1)); - response.EnsureSuccessStatusCode(); - } + response.EnsureSuccessStatusCode(); } [Fact] public async Task Send_Checkout_basket_and_response_ok_status_code() { - using (var server = CreateServer()) - { - var contentBasket = new StringContent(BuildBasket(), UTF8Encoding.UTF8, "application/json"); + using var server = CreateServer(); + var contentBasket = new StringContent(BuildBasket(), UTF8Encoding.UTF8, "application/json"); - await server.CreateClient() - .PostAsync(Post.Basket, contentBasket); + await server.CreateClient() + .PostAsync(Post.Basket, contentBasket); - var contentCheckout = new StringContent(BuildCheckout(), UTF8Encoding.UTF8, "application/json"); + var contentCheckout = new StringContent(BuildCheckout(), UTF8Encoding.UTF8, "application/json"); - var response = await server.CreateIdempotentClient() - .PostAsync(Post.CheckoutOrder, contentCheckout); + var response = await server.CreateIdempotentClient() + .PostAsync(Post.CheckoutOrder, contentCheckout); - response.EnsureSuccessStatusCode(); - } + response.EnsureSuccessStatusCode(); } string BuildBasket() diff --git a/src/Services/Basket/Basket.FunctionalTests/RedisBasketRepositoryTests.cs b/src/Services/Basket/Basket.FunctionalTests/RedisBasketRepositoryTests.cs index e5d79c1e4..0a0cb11fa 100644 --- a/src/Services/Basket/Basket.FunctionalTests/RedisBasketRepositoryTests.cs +++ b/src/Services/Basket/Basket.FunctionalTests/RedisBasketRepositoryTests.cs @@ -9,21 +9,19 @@ namespace Basket.FunctionalTests [Fact] public async Task UpdateBasket_return_and_add_basket() { - using (var server = CreateServer()) - { - var redis = server.Host.Services.GetRequiredService(); + using var server = CreateServer(); + var redis = server.Host.Services.GetRequiredService(); - var redisBasketRepository = BuildBasketRepository(redis); + var redisBasketRepository = BuildBasketRepository(redis); - var basket = await redisBasketRepository.UpdateBasketAsync(new CustomerBasket("customerId") - { - BuyerId = "buyerId", - Items = BuildBasketItems() - }); + var basket = await redisBasketRepository.UpdateBasketAsync(new CustomerBasket("customerId") + { + BuyerId = "buyerId", + Items = BuildBasketItems() + }); - Assert.NotNull(basket); - Assert.Single(basket.Items); - } + Assert.NotNull(basket); + Assert.Single(basket.Items); } @@ -32,25 +30,23 @@ namespace Basket.FunctionalTests public async Task Delete_Basket_return_null() { - using (var server = CreateServer()) - { - var redis = server.Host.Services.GetRequiredService(); + using var server = CreateServer(); + var redis = server.Host.Services.GetRequiredService(); - var redisBasketRepository = BuildBasketRepository(redis); + var redisBasketRepository = BuildBasketRepository(redis); - var basket = await redisBasketRepository.UpdateBasketAsync(new CustomerBasket("customerId") - { - BuyerId = "buyerId", - Items = BuildBasketItems() - }); + var basket = await redisBasketRepository.UpdateBasketAsync(new CustomerBasket("customerId") + { + BuyerId = "buyerId", + Items = BuildBasketItems() + }); - var deleteResult = await redisBasketRepository.DeleteBasketAsync("buyerId"); + var deleteResult = await redisBasketRepository.DeleteBasketAsync("buyerId"); - var result = await redisBasketRepository.GetBasketAsync(basket.BuyerId); + var result = await redisBasketRepository.GetBasketAsync(basket.BuyerId); - Assert.True(deleteResult); - Assert.Null(result); - } + Assert.True(deleteResult); + Assert.Null(result); } RedisBasketRepository BuildBasketRepository(ConnectionMultiplexer connMux) diff --git a/src/Services/Catalog/Catalog.API/Controllers/PicController.cs b/src/Services/Catalog/Catalog.API/Controllers/PicController.cs index 51ea6a7e4..dfb6f0d03 100644 --- a/src/Services/Catalog/Catalog.API/Controllers/PicController.cs +++ b/src/Services/Catalog/Catalog.API/Controllers/PicController.cs @@ -47,40 +47,18 @@ public class PicController : ControllerBase private string GetImageMimeTypeFromImageFileExtension(string extension) { - string mimetype; - - switch (extension) + string mimetype = extension switch { - case ".png": - mimetype = "image/png"; - break; - case ".gif": - mimetype = "image/gif"; - break; - case ".jpg": - case ".jpeg": - mimetype = "image/jpeg"; - break; - case ".bmp": - mimetype = "image/bmp"; - break; - case ".tiff": - mimetype = "image/tiff"; - break; - case ".wmf": - mimetype = "image/wmf"; - break; - case ".jp2": - mimetype = "image/jp2"; - break; - case ".svg": - mimetype = "image/svg+xml"; - break; - default: - mimetype = "application/octet-stream"; - break; - } - + ".png" => "image/png", + ".gif" => "image/gif", + ".jpg" or ".jpeg" => "image/jpeg", + ".bmp" => "image/bmp", + ".tiff" => "image/tiff", + ".wmf" => "image/wmf", + ".jp2" => "image/jp2", + ".svg" => "image/svg+xml", + _ => "application/octet-stream", + }; return mimetype; } } diff --git a/src/Services/Catalog/Catalog.API/Extensions/HostExtensions.cs b/src/Services/Catalog/Catalog.API/Extensions/HostExtensions.cs deleted file mode 100644 index 8720fa809..000000000 --- a/src/Services/Catalog/Catalog.API/Extensions/HostExtensions.cs +++ /dev/null @@ -1,122 +0,0 @@ -namespace Catalog.API.Extensions; - -public static class HostExtensions -{ - public static bool IsInKubernetes(this IHost host) - { - var cfg = host.Services.GetService(); - var orchestratorType = cfg.GetValue("OrchestratorType"); - return orchestratorType?.ToUpper() == "K8S"; - } - - public static IHost MigrateDbContext(this IHost host, Action seeder) where TContext : DbContext - { - var underK8s = host.IsInKubernetes(); - - using (var scope = host.Services.CreateScope()) - { - var services = scope.ServiceProvider; - - var logger = services.GetRequiredService>(); - - var context = services.GetService(); - - try - { - logger.LogInformation("Migrating database associated with context {DbContextName}", typeof(TContext).Name); - - if (underK8s) - { - InvokeSeeder(seeder, context, services); - } - else - { - var retry = Policy.Handle() - .WaitAndRetry(new TimeSpan[] - { - TimeSpan.FromSeconds(3), - TimeSpan.FromSeconds(5), - TimeSpan.FromSeconds(8), - }); - - //if the sql server container is not created on run docker compose this - //migration can't fail for network related exception. The retry options for DbContext only - //apply to transient exceptions - // Note that this is NOT applied when running some orchestrators (let the orchestrator to recreate the failing service) - retry.Execute(() => InvokeSeeder(seeder, context, services)); - } - - logger.LogInformation("Migrated database associated with context {DbContextName}", typeof(TContext).Name); - } - catch (Exception ex) - { - logger.LogError(ex, "An error occurred while migrating the database used on context {DbContextName}", typeof(TContext).Name); - if (underK8s) - { - throw; // Rethrow under k8s because we rely on k8s to re-run the pod - } - } - } - - return host; - } - - public static IWebHost MigrateDbContext(this IWebHost host, Action seeder) where TContext : DbContext - { - var underK8s = host.IsInKubernetes(); - - using (var scope = host.Services.CreateScope()) - { - var services = scope.ServiceProvider; - - var logger = services.GetRequiredService>(); - - var context = services.GetService(); - - try - { - logger.LogInformation("Migrating database associated with context {DbContextName}", typeof(TContext).Name); - - if (underK8s) - { - InvokeSeeder(seeder, context, services); - } - else - { - var retry = Policy.Handle() - .WaitAndRetry(new TimeSpan[] - { - TimeSpan.FromSeconds(3), - TimeSpan.FromSeconds(5), - TimeSpan.FromSeconds(8), - }); - - //if the sql server container is not created on run docker compose this - //migration can't fail for network related exception. The retry options for DbContext only - //apply to transient exceptions - // Note that this is NOT applied when running some orchestrators (let the orchestrator to recreate the failing service) - retry.Execute(() => InvokeSeeder(seeder, context, services)); - } - - logger.LogInformation("Migrated database associated with context {DbContextName}", typeof(TContext).Name); - } - catch (Exception ex) - { - logger.LogError(ex, "An error occurred while migrating the database used on context {DbContextName}", typeof(TContext).Name); - if (underK8s) - { - throw; // Rethrow under k8s because we rely on k8s to re-run the pod - } - } - } - - return host; - } - - private static void InvokeSeeder(Action seeder, TContext context, IServiceProvider services) - where TContext : DbContext - { - context.Database.Migrate(); - seeder(context, services); - } -} diff --git a/src/Services/Catalog/Catalog.API/Extensions/WebHostExtensions.cs b/src/Services/Catalog/Catalog.API/Extensions/WebHostExtensions.cs index b3ac16968..588ca7a35 100644 --- a/src/Services/Catalog/Catalog.API/Extensions/WebHostExtensions.cs +++ b/src/Services/Catalog/Catalog.API/Extensions/WebHostExtensions.cs @@ -13,48 +13,46 @@ public static class WebHostExtensions { var underK8s = host.IsInKubernetes(); - using (var scope = host.Services.CreateScope()) - { - var services = scope.ServiceProvider; - - var logger = services.GetRequiredService>(); + using var scope = host.Services.CreateScope(); + var services = scope.ServiceProvider; - var context = services.GetService(); + var logger = services.GetRequiredService>(); - try - { - logger.LogInformation("Migrating database associated with context {DbContextName}", typeof(TContext).Name); + var context = services.GetService(); - if (underK8s) - { - InvokeSeeder(seeder, context, services); - } - else - { - var retry = Policy.Handle() - .WaitAndRetry(new TimeSpan[] - { - TimeSpan.FromSeconds(3), - TimeSpan.FromSeconds(5), - TimeSpan.FromSeconds(8), - }); + try + { + logger.LogInformation("Migrating database associated with context {DbContextName}", typeof(TContext).Name); - //if the sql server container is not created on run docker compose this - //migration can't fail for network related exception. The retry options for DbContext only - //apply to transient exceptions - // Note that this is NOT applied when running some orchestrators (let the orchestrator to recreate the failing service) - retry.Execute(() => InvokeSeeder(seeder, context, services)); - } + if (underK8s) + { + InvokeSeeder(seeder, context, services); + } + else + { + var retry = Policy.Handle() + .WaitAndRetry(new TimeSpan[] + { + TimeSpan.FromSeconds(3), + TimeSpan.FromSeconds(5), + TimeSpan.FromSeconds(8), + }); - logger.LogInformation("Migrated database associated with context {DbContextName}", typeof(TContext).Name); + //if the sql server container is not created on run docker compose this + //migration can't fail for network related exception. The retry options for DbContext only + //apply to transient exceptions + // Note that this is NOT applied when running some orchestrators (let the orchestrator to recreate the failing service) + retry.Execute(() => InvokeSeeder(seeder, context, services)); } - catch (Exception ex) + + logger.LogInformation("Migrated database associated with context {DbContextName}", typeof(TContext).Name); + } + catch (Exception ex) + { + logger.LogError(ex, "An error occurred while migrating the database used on context {DbContextName}", typeof(TContext).Name); + if (underK8s) { - logger.LogError(ex, "An error occurred while migrating the database used on context {DbContextName}", typeof(TContext).Name); - if (underK8s) - { - throw; // Rethrow under k8s because we rely on k8s to re-run the pod - } + throw; // Rethrow under k8s because we rely on k8s to re-run the pod } } diff --git a/src/Services/Catalog/Catalog.API/Infrastructure/CatalogContextSeed.cs b/src/Services/Catalog/Catalog.API/Infrastructure/CatalogContextSeed.cs index 0028813e0..4e3a0f6e0 100644 --- a/src/Services/Catalog/Catalog.API/Infrastructure/CatalogContextSeed.cs +++ b/src/Services/Catalog/Catalog.API/Infrastructure/CatalogContextSeed.cs @@ -92,11 +92,11 @@ public class CatalogContextSeed { return new List() { - new CatalogBrand() { Brand = "Azure"}, - new CatalogBrand() { Brand = ".NET" }, - new CatalogBrand() { Brand = "Visual Studio" }, - new CatalogBrand() { Brand = "SQL Server" }, - new CatalogBrand() { Brand = "Other" } + new() { Brand = "Azure"}, + new() { Brand = ".NET" }, + new() { Brand = "Visual Studio" }, + new() { Brand = "SQL Server" }, + new() { Brand = "Other" } }; } @@ -147,10 +147,10 @@ public class CatalogContextSeed { return new List() { - new CatalogType() { Type = "Mug"}, - new CatalogType() { Type = "T-Shirt" }, - new CatalogType() { Type = "Sheet" }, - new CatalogType() { Type = "USB Memory Stick" } + new() { Type = "Mug"}, + new() { Type = "T-Shirt" }, + new() { Type = "Sheet" }, + new() { Type = "USB Memory Stick" } }; } @@ -297,18 +297,18 @@ public class CatalogContextSeed { return new List() { - new CatalogItem { CatalogTypeId = 2, CatalogBrandId = 2, AvailableStock = 100, Description = ".NET Bot Black Hoodie", Name = ".NET Bot Black Hoodie", Price = 19.5M, PictureFileName = "1.png" }, - new CatalogItem { CatalogTypeId = 1, CatalogBrandId = 2, AvailableStock = 100, Description = ".NET Black & White Mug", Name = ".NET Black & White Mug", Price= 8.50M, PictureFileName = "2.png" }, - new CatalogItem { CatalogTypeId = 2, CatalogBrandId = 5, AvailableStock = 100, Description = "Prism White T-Shirt", Name = "Prism White T-Shirt", Price = 12, PictureFileName = "3.png" }, - new CatalogItem { CatalogTypeId = 2, CatalogBrandId = 2, AvailableStock = 100, Description = ".NET Foundation T-shirt", Name = ".NET Foundation T-shirt", Price = 12, PictureFileName = "4.png" }, - new CatalogItem { CatalogTypeId = 3, CatalogBrandId = 5, AvailableStock = 100, Description = "Roslyn Red Sheet", Name = "Roslyn Red Sheet", Price = 8.5M, PictureFileName = "5.png" }, - new CatalogItem { CatalogTypeId = 2, CatalogBrandId = 2, AvailableStock = 100, Description = ".NET Blue Hoodie", Name = ".NET Blue Hoodie", Price = 12, PictureFileName = "6.png" }, - new CatalogItem { CatalogTypeId = 2, CatalogBrandId = 5, AvailableStock = 100, Description = "Roslyn Red T-Shirt", Name = "Roslyn Red T-Shirt", Price = 12, PictureFileName = "7.png" }, - new CatalogItem { CatalogTypeId = 2, CatalogBrandId = 5, AvailableStock = 100, Description = "Kudu Purple Hoodie", Name = "Kudu Purple Hoodie", Price = 8.5M, PictureFileName = "8.png" }, - new CatalogItem { CatalogTypeId = 1, CatalogBrandId = 5, AvailableStock = 100, Description = "Cup White Mug", Name = "Cup White Mug", Price = 12, PictureFileName = "9.png" }, - new CatalogItem { CatalogTypeId = 3, CatalogBrandId = 2, AvailableStock = 100, Description = ".NET Foundation Sheet", Name = ".NET Foundation Sheet", Price = 12, PictureFileName = "10.png" }, - new CatalogItem { CatalogTypeId = 3, CatalogBrandId = 2, AvailableStock = 100, Description = "Cup Sheet", Name = "Cup Sheet", Price = 8.5M, PictureFileName = "11.png" }, - new CatalogItem { CatalogTypeId = 2, CatalogBrandId = 5, AvailableStock = 100, Description = "Prism White TShirt", Name = "Prism White TShirt", Price = 12, PictureFileName = "12.png" }, + new() { CatalogTypeId = 2, CatalogBrandId = 2, AvailableStock = 100, Description = ".NET Bot Black Hoodie", Name = ".NET Bot Black Hoodie", Price = 19.5M, PictureFileName = "1.png" }, + new() { CatalogTypeId = 1, CatalogBrandId = 2, AvailableStock = 100, Description = ".NET Black & White Mug", Name = ".NET Black & White Mug", Price= 8.50M, PictureFileName = "2.png" }, + new() { CatalogTypeId = 2, CatalogBrandId = 5, AvailableStock = 100, Description = "Prism White T-Shirt", Name = "Prism White T-Shirt", Price = 12, PictureFileName = "3.png" }, + new() { CatalogTypeId = 2, CatalogBrandId = 2, AvailableStock = 100, Description = ".NET Foundation T-shirt", Name = ".NET Foundation T-shirt", Price = 12, PictureFileName = "4.png" }, + new() { CatalogTypeId = 3, CatalogBrandId = 5, AvailableStock = 100, Description = "Roslyn Red Sheet", Name = "Roslyn Red Sheet", Price = 8.5M, PictureFileName = "5.png" }, + new() { CatalogTypeId = 2, CatalogBrandId = 2, AvailableStock = 100, Description = ".NET Blue Hoodie", Name = ".NET Blue Hoodie", Price = 12, PictureFileName = "6.png" }, + new() { CatalogTypeId = 2, CatalogBrandId = 5, AvailableStock = 100, Description = "Roslyn Red T-Shirt", Name = "Roslyn Red T-Shirt", Price = 12, PictureFileName = "7.png" }, + new() { CatalogTypeId = 2, CatalogBrandId = 5, AvailableStock = 100, Description = "Kudu Purple Hoodie", Name = "Kudu Purple Hoodie", Price = 8.5M, PictureFileName = "8.png" }, + new() { CatalogTypeId = 1, CatalogBrandId = 5, AvailableStock = 100, Description = "Cup White Mug", Name = "Cup White Mug", Price = 12, PictureFileName = "9.png" }, + new() { CatalogTypeId = 3, CatalogBrandId = 2, AvailableStock = 100, Description = ".NET Foundation Sheet", Name = ".NET Foundation Sheet", Price = 12, PictureFileName = "10.png" }, + new() { CatalogTypeId = 3, CatalogBrandId = 2, AvailableStock = 100, Description = "Cup Sheet", Name = "Cup Sheet", Price = 8.5M, PictureFileName = "11.png" }, + new() { CatalogTypeId = 2, CatalogBrandId = 5, AvailableStock = 100, Description = "Prism White TShirt", Name = "Prism White TShirt", Price = 12, PictureFileName = "12.png" }, }; } diff --git a/src/Services/Catalog/Catalog.FunctionalTests/CatalogScenarios.cs b/src/Services/Catalog/Catalog.FunctionalTests/CatalogScenarios.cs index 574d20bcb..956d29403 100644 --- a/src/Services/Catalog/Catalog.FunctionalTests/CatalogScenarios.cs +++ b/src/Services/Catalog/Catalog.FunctionalTests/CatalogScenarios.cs @@ -6,135 +6,113 @@ public class CatalogScenarios [Fact] public async Task Get_get_all_catalogitems_and_response_ok_status_code() { - using (var server = CreateServer()) - { - var response = await server.CreateClient() - .GetAsync(Get.Items()); + using var server = CreateServer(); + var response = await server.CreateClient() + .GetAsync(Get.Items()); - response.EnsureSuccessStatusCode(); - } + response.EnsureSuccessStatusCode(); } [Fact] public async Task Get_get_catalogitem_by_id_and_response_ok_status_code() { - using (var server = CreateServer()) - { - var response = await server.CreateClient() - .GetAsync(Get.ItemById(1)); + using var server = CreateServer(); + var response = await server.CreateClient() + .GetAsync(Get.ItemById(1)); - response.EnsureSuccessStatusCode(); - } + response.EnsureSuccessStatusCode(); } [Fact] public async Task Get_get_catalogitem_by_id_and_response_bad_request_status_code() { - using (var server = CreateServer()) - { - var response = await server.CreateClient() - .GetAsync(Get.ItemById(int.MinValue)); + using var server = CreateServer(); + var response = await server.CreateClient() + .GetAsync(Get.ItemById(int.MinValue)); - Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); - } + Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); } [Fact] public async Task Get_get_catalogitem_by_id_and_response_not_found_status_code() { - using (var server = CreateServer()) - { - var response = await server.CreateClient() - .GetAsync(Get.ItemById(int.MaxValue)); + using var server = CreateServer(); + var response = await server.CreateClient() + .GetAsync(Get.ItemById(int.MaxValue)); - Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); - } + Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); } [Fact] public async Task Get_get_catalogitem_by_name_and_response_ok_status_code() { - using (var server = CreateServer()) - { - var response = await server.CreateClient() - .GetAsync(Get.ItemByName(".NET")); + using var server = CreateServer(); + var response = await server.CreateClient() + .GetAsync(Get.ItemByName(".NET")); - response.EnsureSuccessStatusCode(); - } + response.EnsureSuccessStatusCode(); } [Fact] public async Task Get_get_paginated_catalogitem_by_name_and_response_ok_status_code() { - using (var server = CreateServer()) - { - const bool paginated = true; - var response = await server.CreateClient() - .GetAsync(Get.ItemByName(".NET", paginated)); - - response.EnsureSuccessStatusCode(); - } + using var server = CreateServer(); + const bool paginated = true; + var response = await server.CreateClient() + .GetAsync(Get.ItemByName(".NET", paginated)); + + response.EnsureSuccessStatusCode(); } [Fact] public async Task Get_get_paginated_catalog_items_and_response_ok_status_code() { - using (var server = CreateServer()) - { - const bool paginated = true; - var response = await server.CreateClient() - .GetAsync(Get.Items(paginated)); - - response.EnsureSuccessStatusCode(); - } + using var server = CreateServer(); + const bool paginated = true; + var response = await server.CreateClient() + .GetAsync(Get.Items(paginated)); + + response.EnsureSuccessStatusCode(); } [Fact] public async Task Get_get_filtered_catalog_items_and_response_ok_status_code() { - using (var server = CreateServer()) - { - var response = await server.CreateClient() - .GetAsync(Get.Filtered(1, 1)); + using var server = CreateServer(); + var response = await server.CreateClient() + .GetAsync(Get.Filtered(1, 1)); - response.EnsureSuccessStatusCode(); - } + response.EnsureSuccessStatusCode(); } [Fact] public async Task Get_get_paginated_filtered_catalog_items_and_response_ok_status_code() { - using (var server = CreateServer()) - { - const bool paginated = true; - var response = await server.CreateClient() - .GetAsync(Get.Filtered(1, 1, paginated)); - - response.EnsureSuccessStatusCode(); - } + using var server = CreateServer(); + const bool paginated = true; + var response = await server.CreateClient() + .GetAsync(Get.Filtered(1, 1, paginated)); + + response.EnsureSuccessStatusCode(); } [Fact] public async Task Get_catalog_types_response_ok_status_code() { - using (var server = CreateServer()) - { - var response = await server.CreateClient() - .GetAsync(Get.Types); + using var server = CreateServer(); + var response = await server.CreateClient() + .GetAsync(Get.Types); - response.EnsureSuccessStatusCode(); - } + response.EnsureSuccessStatusCode(); } [Fact] public async Task Get_catalog_brands_response_ok_status_code() { - using (var server = CreateServer()) - { - var response = await server.CreateClient() - .GetAsync(Get.Brands); + using var server = CreateServer(); + var response = await server.CreateClient() + .GetAsync(Get.Brands); - response.EnsureSuccessStatusCode(); - } + response.EnsureSuccessStatusCode(); } } diff --git a/src/Services/Catalog/Catalog.FunctionalTests/GlobalUsings.cs b/src/Services/Catalog/Catalog.FunctionalTests/GlobalUsings.cs index d1910b9c2..2ceffc535 100644 --- a/src/Services/Catalog/Catalog.FunctionalTests/GlobalUsings.cs +++ b/src/Services/Catalog/Catalog.FunctionalTests/GlobalUsings.cs @@ -1,7 +1,7 @@ -global using Catalog.API.Extensions; -global using Microsoft.AspNetCore.Hosting; +global using Microsoft.AspNetCore.Hosting; global using Microsoft.AspNetCore.TestHost; global using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF; +global using Microsoft.eShopOnContainers.Services.Catalog.API.Extensions; global using Microsoft.eShopOnContainers.Services.Catalog.API.Infrastructure; global using Microsoft.eShopOnContainers.Services.Catalog.API; global using Microsoft.Extensions.Configuration; diff --git a/src/Services/Catalog/Catalog.UnitTests/Application/CatalogControllerTest.cs b/src/Services/Catalog/Catalog.UnitTests/Application/CatalogControllerTest.cs index 1a9cdcc9b..53efafbfd 100644 --- a/src/Services/Catalog/Catalog.UnitTests/Application/CatalogControllerTest.cs +++ b/src/Services/Catalog/Catalog.UnitTests/Application/CatalogControllerTest.cs @@ -25,11 +25,9 @@ public class CatalogControllerTest .UseInMemoryDatabase(databaseName: "in-memory") .Options; - using (var dbContext = new CatalogContext(_dbOptions)) - { - dbContext.AddRange(GetFakeCatalog()); - dbContext.SaveChanges(); - } + using var dbContext = new CatalogContext(_dbOptions); + dbContext.AddRange(GetFakeCatalog()); + dbContext.SaveChanges(); } [Fact] @@ -66,7 +64,7 @@ public class CatalogControllerTest { return new List() { - new CatalogItem() + new() { Id = 1, Name = "fakeItemA", @@ -74,7 +72,7 @@ public class CatalogControllerTest CatalogBrandId = 1, PictureFileName = "fakeItemA.png" }, - new CatalogItem() + new() { Id = 2, Name = "fakeItemB", @@ -82,7 +80,7 @@ public class CatalogControllerTest CatalogBrandId = 1, PictureFileName = "fakeItemB.png" }, - new CatalogItem() + new() { Id = 3, Name = "fakeItemC", @@ -90,7 +88,7 @@ public class CatalogControllerTest CatalogBrandId = 1, PictureFileName = "fakeItemC.png" }, - new CatalogItem() + new() { Id = 4, Name = "fakeItemD", @@ -98,7 +96,7 @@ public class CatalogControllerTest CatalogBrandId = 1, PictureFileName = "fakeItemD.png" }, - new CatalogItem() + new() { Id = 5, Name = "fakeItemE", @@ -106,7 +104,7 @@ public class CatalogControllerTest CatalogBrandId = 1, PictureFileName = "fakeItemE.png" }, - new CatalogItem() + new() { Id = 6, Name = "fakeItemF", @@ -120,7 +118,7 @@ public class CatalogControllerTest public class TestCatalogSettings : IOptionsSnapshot { - public CatalogSettings Value => new CatalogSettings + public CatalogSettings Value => new() { PicBaseUrl = "http://image-server.com/", AzureStorageEnabled = true diff --git a/src/Services/Identity/Identity.API/Certificate/Certificate.cs b/src/Services/Identity/Identity.API/Certificate/Certificate.cs index 4bb0155b5..91aa74a6c 100644 --- a/src/Services/Identity/Identity.API/Certificate/Certificate.cs +++ b/src/Services/Identity/Identity.API/Certificate/Certificate.cs @@ -12,24 +12,20 @@ * real environment the certificate should be created and stored in a secure way, which is out * of the scope of this project. **********************************************************************************************/ - using (var stream = assembly.GetManifestResourceStream("Identity.API.Certificate.idsrv3test.pfx")) - { - return new X509Certificate2(ReadStream(stream), "idsrv3test"); - } + using var stream = assembly.GetManifestResourceStream("Identity.API.Certificate.idsrv3test.pfx"); + return new X509Certificate2(ReadStream(stream), "idsrv3test"); } private static byte[] ReadStream(Stream input) { byte[] buffer = new byte[16 * 1024]; - using (MemoryStream ms = new MemoryStream()) + using MemoryStream ms = new MemoryStream(); + int read; + while ((read = input.Read(buffer, 0, buffer.Length)) > 0) { - int read; - while ((read = input.Read(buffer, 0, buffer.Length)) > 0) - { - ms.Write(buffer, 0, read); - } - return ms.ToArray(); + ms.Write(buffer, 0, read); } + return ms.ToArray(); } } } \ No newline at end of file diff --git a/src/Services/Identity/Identity.API/Data/ApplicationDbContextSeed.cs b/src/Services/Identity/Identity.API/Data/ApplicationDbContextSeed.cs index d2f604c1c..6ee9fd499 100644 --- a/src/Services/Identity/Identity.API/Data/ApplicationDbContextSeed.cs +++ b/src/Services/Identity/Identity.API/Data/ApplicationDbContextSeed.cs @@ -191,23 +191,21 @@ string imagePath = Path.Combine(webroot, "images"); string[] imageFiles = Directory.GetFiles(imagePath).Select(file => Path.GetFileName(file)).ToArray(); - using (ZipArchive zip = ZipFile.Open(imagesZipFile, ZipArchiveMode.Read)) + using ZipArchive zip = ZipFile.Open(imagesZipFile, ZipArchiveMode.Read); + foreach (ZipArchiveEntry entry in zip.Entries) { - foreach (ZipArchiveEntry entry in zip.Entries) + if (imageFiles.Contains(entry.Name)) { - if (imageFiles.Contains(entry.Name)) + string destinationFilename = Path.Combine(imagePath, entry.Name); + if (File.Exists(destinationFilename)) { - string destinationFilename = Path.Combine(imagePath, entry.Name); - if (File.Exists(destinationFilename)) - { - File.Delete(destinationFilename); - } - entry.ExtractToFile(destinationFilename); - } - else - { - logger.LogWarning("Skipped file '{FileName}' in zipfile '{ZipFileName}'", entry.Name, imagesZipFile); + File.Delete(destinationFilename); } + entry.ExtractToFile(destinationFilename); + } + else + { + logger.LogWarning("Skipped file '{FileName}' in zipfile '{ZipFileName}'", entry.Name, imagesZipFile); } } } diff --git a/src/Services/Identity/Identity.API/IWebHostExtensions.cs b/src/Services/Identity/Identity.API/IWebHostExtensions.cs index c6c0cd4b7..57c386559 100644 --- a/src/Services/Identity/Identity.API/IWebHostExtensions.cs +++ b/src/Services/Identity/Identity.API/IWebHostExtensions.cs @@ -13,52 +13,50 @@ namespace Microsoft.AspNetCore.Hosting { var underK8s = webHost.IsInKubernetes(); - using (var scope = webHost.Services.CreateScope()) + using var scope = webHost.Services.CreateScope(); + var services = scope.ServiceProvider; + var logger = services.GetRequiredService>(); + var context = services.GetService(); + + try { - var services = scope.ServiceProvider; - var logger = services.GetRequiredService>(); - var context = services.GetService(); + logger.LogInformation("Migrating database associated with context {DbContextName}", typeof(TContext).Name); - try + if (underK8s) { - logger.LogInformation("Migrating database associated with context {DbContextName}", typeof(TContext).Name); - - if (underK8s) - { - InvokeSeeder(seeder, context, services); - } - else - { - var retries = 10; - var retry = Policy.Handle() - .WaitAndRetry( - retryCount: retries, - sleepDurationProvider: retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)), - onRetry: (exception, timeSpan, retry, ctx) => - { - logger.LogWarning(exception, "[{prefix}] Exception {ExceptionType} with message {Message} detected on attempt {retry} of {retries}", nameof(TContext), exception.GetType().Name, exception.Message, retry, retries); - }); - - //if the sql server container is not created on run docker compose this - //migration can't fail for network related exception. The retry options for DbContext only - //apply to transient exceptions - // Note that this is NOT applied when running some orchestrators (let the orchestrator to recreate the failing service) - retry.Execute(() => InvokeSeeder(seeder, context, services)); - } + InvokeSeeder(seeder, context, services); + } + else + { + var retries = 10; + var retry = Policy.Handle() + .WaitAndRetry( + retryCount: retries, + sleepDurationProvider: retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)), + onRetry: (exception, timeSpan, retry, ctx) => + { + logger.LogWarning(exception, "[{prefix}] Exception {ExceptionType} with message {Message} detected on attempt {retry} of {retries}", nameof(TContext), exception.GetType().Name, exception.Message, retry, retries); + }); - logger.LogInformation("Migrated database associated with context {DbContextName}", typeof(TContext).Name); + //if the sql server container is not created on run docker compose this + //migration can't fail for network related exception. The retry options for DbContext only + //apply to transient exceptions + // Note that this is NOT applied when running some orchestrators (let the orchestrator to recreate the failing service) + retry.Execute(() => InvokeSeeder(seeder, context, services)); } - catch (Exception ex) + + logger.LogInformation("Migrated database associated with context {DbContextName}", typeof(TContext).Name); + } + catch (Exception ex) + { + logger.LogError(ex, "An error occurred while migrating the database used on context {DbContextName}", typeof(TContext).Name); + if (underK8s) { - logger.LogError(ex, "An error occurred while migrating the database used on context {DbContextName}", typeof(TContext).Name); - if (underK8s) - { - throw; // Rethrow under k8s because we rely on k8s to re-run the pod - } + throw; // Rethrow under k8s because we rely on k8s to re-run the pod } } - return webHost; + return webHost; } private static void InvokeSeeder(Action seeder, TContext context, IServiceProvider services) diff --git a/src/Services/Ordering/Ordering.API/Application/Behaviors/TransactionBehaviour.cs b/src/Services/Ordering/Ordering.API/Application/Behaviors/TransactionBehaviour.cs index 0417d40f6..bed25d3cc 100644 --- a/src/Services/Ordering/Ordering.API/Application/Behaviors/TransactionBehaviour.cs +++ b/src/Services/Ordering/Ordering.API/Application/Behaviors/TransactionBehaviour.cs @@ -35,7 +35,7 @@ public class TransactionBehaviour : IPipelineBehavior GetOrderAsync(int id) { - using (var connection = new SqlConnection(_connectionString)) - { - connection.Open(); + using var connection = new SqlConnection(_connectionString); + connection.Open(); - var result = await connection.QueryAsync( - @"select o.[Id] as ordernumber,o.OrderDate as date, o.Description as description, + var result = await connection.QueryAsync( + @"select o.[Id] as ordernumber,o.OrderDate as date, o.Description as description, o.Address_City as city, o.Address_Country as country, o.Address_State as state, o.Address_Street as street, o.Address_ZipCode as zipcode, os.Name as status, oi.ProductName as productname, oi.Units as units, oi.UnitPrice as unitprice, oi.PictureUrl as pictureurl @@ -26,23 +25,21 @@ public class OrderQueries LEFT JOIN ordering.Orderitems oi ON o.Id = oi.orderid LEFT JOIN ordering.orderstatus os on o.OrderStatusId = os.Id WHERE o.Id=@id" - , new { id } - ); + , new { id } + ); - if (result.AsList().Count == 0) - throw new KeyNotFoundException(); + if (result.AsList().Count == 0) + throw new KeyNotFoundException(); - return MapOrderItems(result); - } + return MapOrderItems(result); } public async Task> GetOrdersFromUserAsync(Guid userId) { - using (var connection = new SqlConnection(_connectionString)) - { - connection.Open(); + using var connection = new SqlConnection(_connectionString); + connection.Open(); - return await connection.QueryAsync(@"SELECT o.[Id] as ordernumber,o.[OrderDate] as [date],os.[Name] as [status], SUM(oi.units*oi.unitprice) as total + return await connection.QueryAsync(@"SELECT o.[Id] as ordernumber,o.[OrderDate] as [date],os.[Name] as [status], SUM(oi.units*oi.unitprice) as total FROM [ordering].[Orders] o LEFT JOIN[ordering].[orderitems] oi ON o.Id = oi.orderid LEFT JOIN[ordering].[orderstatus] os on o.OrderStatusId = os.Id @@ -50,17 +47,14 @@ public class OrderQueries WHERE ob.IdentityGuid = @userId GROUP BY o.[Id], o.[OrderDate], os.[Name] ORDER BY o.[Id]", new { userId }); - } } public async Task> GetCardTypesAsync() { - using (var connection = new SqlConnection(_connectionString)) - { - connection.Open(); + using var connection = new SqlConnection(_connectionString); + connection.Open(); - return await connection.QueryAsync("SELECT * FROM ordering.cardtypes"); - } + return await connection.QueryAsync("SELECT * FROM ordering.cardtypes"); } private Order MapOrderItems(dynamic result) diff --git a/src/Services/Ordering/Ordering.API/Infrastructure/Filters/AuthorizeCheckOperationFilter.cs b/src/Services/Ordering/Ordering.API/Infrastructure/Filters/AuthorizeCheckOperationFilter.cs index cdc4b76b1..b4689bf9a 100644 --- a/src/Services/Ordering/Ordering.API/Infrastructure/Filters/AuthorizeCheckOperationFilter.cs +++ b/src/Services/Ordering/Ordering.API/Infrastructure/Filters/AuthorizeCheckOperationFilter.cs @@ -20,7 +20,7 @@ public class AuthorizeCheckOperationFilter : IOperationFilter operation.Security = new List { - new OpenApiSecurityRequirement + new() { [ oAuthScheme ] = new [] { "orderingapi" } } diff --git a/src/Services/Ordering/Ordering.BackgroundTasks/Services/GracePeriodManagerService.cs b/src/Services/Ordering/Ordering.BackgroundTasks/Services/GracePeriodManagerService.cs index b53437d9b..9f00f3f60 100644 --- a/src/Services/Ordering/Ordering.BackgroundTasks/Services/GracePeriodManagerService.cs +++ b/src/Services/Ordering/Ordering.BackgroundTasks/Services/GracePeriodManagerService.cs @@ -63,24 +63,22 @@ namespace Ordering.BackgroundTasks.Services { IEnumerable orderIds = new List(); - using (var conn = new SqlConnection(_settings.ConnectionString)) + using var conn = new SqlConnection(_settings.ConnectionString); + try { - try - { - conn.Open(); - orderIds = conn.Query( - @"SELECT Id FROM [ordering].[orders] - WHERE DATEDIFF(minute, [OrderDate], GETDATE()) >= @GracePeriodTime - AND [OrderStatusId] = 1", - new { _settings.GracePeriodTime }); - } - catch (SqlException exception) - { - _logger.LogCritical(exception, "FATAL ERROR: Database connections could not be opened: {Message}", exception.Message); - } - + conn.Open(); + orderIds = conn.Query( + @"SELECT Id FROM [ordering].[orders] + WHERE DATEDIFF(minute, [OrderDate], GETDATE()) >= @GracePeriodTime + AND [OrderStatusId] = 1", + new { _settings.GracePeriodTime }); + } + catch (SqlException exception) + { + _logger.LogCritical(exception, "FATAL ERROR: Database connections could not be opened: {Message}", exception.Message); } + return orderIds; } } diff --git a/src/Services/Ordering/Ordering.FunctionalTests/OrderingScenarios.cs b/src/Services/Ordering/Ordering.FunctionalTests/OrderingScenarios.cs index f6c96f28e..d49f41960 100644 --- a/src/Services/Ordering/Ordering.FunctionalTests/OrderingScenarios.cs +++ b/src/Services/Ordering/Ordering.FunctionalTests/OrderingScenarios.cs @@ -14,39 +14,33 @@ namespace Ordering.FunctionalTests [Fact] public async Task Get_get_all_stored_orders_and_response_ok_status_code() { - using (var server = CreateServer()) - { - var response = await server.CreateClient() - .GetAsync(Get.Orders); + using var server = CreateServer(); + var response = await server.CreateClient() + .GetAsync(Get.Orders); - response.EnsureSuccessStatusCode(); - } + response.EnsureSuccessStatusCode(); } [Fact] public async Task Cancel_order_no_order_created_bad_request_response() { - using (var server = CreateServer()) - { - var content = new StringContent(BuildOrder(), UTF8Encoding.UTF8, "application/json"); - var response = await server.CreateIdempotentClient() - .PutAsync(Put.CancelOrder, content); + using var server = CreateServer(); + var content = new StringContent(BuildOrder(), UTF8Encoding.UTF8, "application/json"); + var response = await server.CreateIdempotentClient() + .PutAsync(Put.CancelOrder, content); - Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); - } + Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); } [Fact] public async Task Ship_order_no_order_created_bad_request_response() { - using (var server = CreateServer()) - { - var content = new StringContent(BuildOrder(), UTF8Encoding.UTF8, "application/json"); - var response = await server.CreateIdempotentClient() - .PutAsync(Put.ShipOrder, content); + using var server = CreateServer(); + var content = new StringContent(BuildOrder(), UTF8Encoding.UTF8, "application/json"); + var response = await server.CreateIdempotentClient() + .PutAsync(Put.ShipOrder, content); - Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); - } + Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); } string BuildOrder() diff --git a/src/Services/Webhooks/Webhooks.API/Infrastructure/AuthorizeCheckOperationFilter.cs b/src/Services/Webhooks/Webhooks.API/Infrastructure/AuthorizeCheckOperationFilter.cs index ea9667263..13b0fcbdb 100644 --- a/src/Services/Webhooks/Webhooks.API/Infrastructure/AuthorizeCheckOperationFilter.cs +++ b/src/Services/Webhooks/Webhooks.API/Infrastructure/AuthorizeCheckOperationFilter.cs @@ -20,7 +20,7 @@ public class AuthorizeCheckOperationFilter : IOperationFilter operation.Security = new List { - new OpenApiSecurityRequirement + new() { [ oAuthScheme ] = new [] { "webhooksapi" } } diff --git a/src/Tests/Services/Application.FunctionalTests/Services/IntegrationEventsScenarios.cs b/src/Tests/Services/Application.FunctionalTests/Services/IntegrationEventsScenarios.cs index ffc710e33..86466766f 100644 --- a/src/Tests/Services/Application.FunctionalTests/Services/IntegrationEventsScenarios.cs +++ b/src/Tests/Services/Application.FunctionalTests/Services/IntegrationEventsScenarios.cs @@ -11,45 +11,43 @@ public class IntegrationEventsScenarios decimal priceModification = 0.15M; string userId = "JohnId"; - using (var catalogServer = new CatalogScenariosBase().CreateServer()) - using (var basketServer = new BasketScenariosBase().CreateServer()) - { - var catalogClient = catalogServer.CreateClient(); - var basketClient = basketServer.CreateClient(); + using var catalogServer = new CatalogScenariosBase().CreateServer(); + using var basketServer = new BasketScenariosBase().CreateServer(); + var catalogClient = catalogServer.CreateClient(); + var basketClient = basketServer.CreateClient(); - // GIVEN a product catalog list - var originalCatalogProducts = await GetCatalogAsync(catalogClient); + // GIVEN a product catalog list + var originalCatalogProducts = await GetCatalogAsync(catalogClient); - // AND a user basket filled with products - var basket = ComposeBasket(userId, originalCatalogProducts.Data.Take(3)); - var res = await basketClient.PostAsync( - BasketScenariosBase.Post.CreateBasket, - new StringContent(JsonSerializer.Serialize(basket), UTF8Encoding.UTF8, "application/json") - ); + // AND a user basket filled with products + var basket = ComposeBasket(userId, originalCatalogProducts.Data.Take(3)); + var res = await basketClient.PostAsync( + BasketScenariosBase.Post.CreateBasket, + new StringContent(JsonSerializer.Serialize(basket), UTF8Encoding.UTF8, "application/json") + ); - // WHEN the price of one product is modified in the catalog - var itemToModify = basket.Items[2]; - var oldPrice = itemToModify.UnitPrice; - var newPrice = oldPrice + priceModification; - var pRes = await catalogClient.PutAsync(CatalogScenariosBase.Put.UpdateCatalogProduct, new StringContent(ChangePrice(itemToModify, newPrice, originalCatalogProducts), UTF8Encoding.UTF8, "application/json")); + // WHEN the price of one product is modified in the catalog + var itemToModify = basket.Items[2]; + var oldPrice = itemToModify.UnitPrice; + var newPrice = oldPrice + priceModification; + var pRes = await catalogClient.PutAsync(CatalogScenariosBase.Put.UpdateCatalogProduct, new StringContent(ChangePrice(itemToModify, newPrice, originalCatalogProducts), UTF8Encoding.UTF8, "application/json")); - var modifiedCatalogProducts = await GetCatalogAsync(catalogClient); + var modifiedCatalogProducts = await GetCatalogAsync(catalogClient); - var itemUpdated = await GetUpdatedBasketItem(newPrice, itemToModify.ProductId, userId, basketClient); + var itemUpdated = await GetUpdatedBasketItem(newPrice, itemToModify.ProductId, userId, basketClient); - if (itemUpdated == null) - { - Assert.False(true, $"The basket service has not been updated."); - } - else - { - //THEN the product price changes in the catalog - Assert.Equal(newPrice, modifiedCatalogProducts.Data.Single(it => it.Id == itemToModify.ProductId).Price); + if (itemUpdated == null) + { + Assert.False(true, $"The basket service has not been updated."); + } + else + { + //THEN the product price changes in the catalog + Assert.Equal(newPrice, modifiedCatalogProducts.Data.Single(it => it.Id == itemToModify.ProductId).Price); - // AND the products in the basket reflects the changed priced and the original price - Assert.Equal(newPrice, itemUpdated.UnitPrice); - Assert.Equal(oldPrice, itemUpdated.OldUnitPrice); - } + // AND the products in the basket reflects the changed priced and the original price + Assert.Equal(newPrice, itemUpdated.UnitPrice); + Assert.Equal(oldPrice, itemUpdated.OldUnitPrice); } } diff --git a/src/Tests/Services/Application.FunctionalTests/Services/Ordering/OrderingScenarios.cs b/src/Tests/Services/Application.FunctionalTests/Services/Ordering/OrderingScenarios.cs index 1af7d7417..e97a95e9d 100644 --- a/src/Tests/Services/Application.FunctionalTests/Services/Ordering/OrderingScenarios.cs +++ b/src/Tests/Services/Application.FunctionalTests/Services/Ordering/OrderingScenarios.cs @@ -5,35 +5,33 @@ public class OrderingScenarios : OrderingScenariosBase [Fact] public async Task Cancel_basket_and_check_order_status_cancelled() { - using (var orderServer = new OrderingScenariosBase().CreateServer()) - using (var basketServer = new BasketScenariosBase().CreateServer()) - { - // Expected data - var cityExpected = $"city-{Guid.NewGuid()}"; - var orderStatusExpected = "cancelled"; + using var orderServer = new OrderingScenariosBase().CreateServer(); + using var basketServer = new BasketScenariosBase().CreateServer(); + // Expected data + var cityExpected = $"city-{Guid.NewGuid()}"; + var orderStatusExpected = "cancelled"; - var basketClient = basketServer.CreateIdempotentClient(); - var orderClient = orderServer.CreateIdempotentClient(); + var basketClient = basketServer.CreateIdempotentClient(); + var orderClient = orderServer.CreateIdempotentClient(); - // GIVEN a basket is created - var contentBasket = new StringContent(BuildBasket(), UTF8Encoding.UTF8, "application/json"); - await basketClient.PostAsync(BasketScenariosBase.Post.CreateBasket, contentBasket); + // GIVEN a basket is created + var contentBasket = new StringContent(BuildBasket(), UTF8Encoding.UTF8, "application/json"); + await basketClient.PostAsync(BasketScenariosBase.Post.CreateBasket, contentBasket); - // AND basket checkout is sent - await basketClient.PostAsync(BasketScenariosBase.Post.CheckoutOrder, new StringContent(BuildCheckout(cityExpected), UTF8Encoding.UTF8, "application/json")); + // AND basket checkout is sent + await basketClient.PostAsync(BasketScenariosBase.Post.CheckoutOrder, new StringContent(BuildCheckout(cityExpected), UTF8Encoding.UTF8, "application/json")); - // WHEN Order is created in Ordering.api - var newOrder = await TryGetNewOrderCreated(cityExpected, orderClient); + // WHEN Order is created in Ordering.api + var newOrder = await TryGetNewOrderCreated(cityExpected, orderClient); - // AND Order is cancelled in Ordering.api - await orderClient.PutAsync(OrderingScenariosBase.Put.CancelOrder, new StringContent(BuildCancelOrder(newOrder.OrderNumber), UTF8Encoding.UTF8, "application/json")); + // AND Order is cancelled in Ordering.api + await orderClient.PutAsync(OrderingScenariosBase.Put.CancelOrder, new StringContent(BuildCancelOrder(newOrder.OrderNumber), UTF8Encoding.UTF8, "application/json")); - // AND the requested order is retrieved - var order = await TryGetOrder(newOrder.OrderNumber, orderClient); + // AND the requested order is retrieved + var order = await TryGetOrder(newOrder.OrderNumber, orderClient); - // THEN check status - Assert.Equal(orderStatusExpected, order.Status); - } + // THEN check status + Assert.Equal(orderStatusExpected, order.Status); } async Task TryGetOrder(string orderNumber, HttpClient orderClient) diff --git a/src/Web/WebMVC/Infrastructure/WebContextSeed.cs b/src/Web/WebMVC/Infrastructure/WebContextSeed.cs index a0ab5832e..6ee7678e1 100644 --- a/src/Web/WebMVC/Infrastructure/WebContextSeed.cs +++ b/src/Web/WebMVC/Infrastructure/WebContextSeed.cs @@ -56,23 +56,21 @@ public class WebContextSeed string imagePath = Path.Combine(webroot, "images"); string[] imageFiles = Directory.GetFiles(imagePath).Select(file => Path.GetFileName(file)).ToArray(); - using (ZipArchive zip = ZipFile.Open(imagesZipFile, ZipArchiveMode.Read)) + using ZipArchive zip = ZipFile.Open(imagesZipFile, ZipArchiveMode.Read); + foreach (ZipArchiveEntry entry in zip.Entries) { - foreach (ZipArchiveEntry entry in zip.Entries) + if (imageFiles.Contains(entry.Name)) { - if (imageFiles.Contains(entry.Name)) + string destinationFilename = Path.Combine(imagePath, entry.Name); + if (File.Exists(destinationFilename)) { - string destinationFilename = Path.Combine(imagePath, entry.Name); - if (File.Exists(destinationFilename)) - { - File.Delete(destinationFilename); - } - entry.ExtractToFile(destinationFilename); - } - else - { - log.Warning("Skipped file '{FileName}' in zipfile '{ZipFileName}'", entry.Name, imagesZipFile); + File.Delete(destinationFilename); } + entry.ExtractToFile(destinationFilename); + } + else + { + log.Warning("Skipped file '{FileName}' in zipfile '{ZipFileName}'", entry.Name, imagesZipFile); } } } diff --git a/src/Web/WebSPA/Server/Infrastructure/WebContextSeed.cs b/src/Web/WebSPA/Server/Infrastructure/WebContextSeed.cs index b23da90bb..483d3f9ce 100644 --- a/src/Web/WebSPA/Server/Infrastructure/WebContextSeed.cs +++ b/src/Web/WebSPA/Server/Infrastructure/WebContextSeed.cs @@ -39,23 +39,21 @@ public class WebContextSeed } string[] imageFiles = Directory.GetFiles(imagePath).Select(file => Path.GetFileName(file)).ToArray(); - using (ZipArchive zip = ZipFile.Open(imagesZipFile, ZipArchiveMode.Read)) + using ZipArchive zip = ZipFile.Open(imagesZipFile, ZipArchiveMode.Read); + foreach (ZipArchiveEntry entry in zip.Entries) { - foreach (ZipArchiveEntry entry in zip.Entries) + if (!imageFiles.Contains(entry.Name)) { - if (!imageFiles.Contains(entry.Name)) + string destinationFilename = Path.Combine(imagePath, entry.Name); + if (File.Exists(destinationFilename)) { - string destinationFilename = Path.Combine(imagePath, entry.Name); - if (File.Exists(destinationFilename)) - { - File.Delete(destinationFilename); - } - entry.ExtractToFile(destinationFilename); - } - else - { - log.LogWarning("Skipped file '{FileName}' in zipfile '{ZipFileName}'", entry.Name, imagesZipFile); + File.Delete(destinationFilename); } + entry.ExtractToFile(destinationFilename); + } + else + { + log.LogWarning("Skipped file '{FileName}' in zipfile '{ZipFileName}'", entry.Name, imagesZipFile); } } }