Merge pull request #1884 from szukuro/dev

Adding various language enhancements, removing unused/duplicated extension
This commit is contained in:
Tarun Jain 2022-04-29 19:26:06 +05:30 committed by GitHub
commit 59805331cd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
29 changed files with 447 additions and 671 deletions

View File

@ -22,7 +22,7 @@
operation.Security = new List<OpenApiSecurityRequirement> operation.Security = new List<OpenApiSecurityRequirement>
{ {
new OpenApiSecurityRequirement new()
{ {
[ oAuthScheme ] = new [] { "Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator" } [ oAuthScheme ] = new [] { "Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator" }
} }

View File

@ -22,7 +22,7 @@
operation.Security = new List<OpenApiSecurityRequirement> operation.Security = new List<OpenApiSecurityRequirement>
{ {
new OpenApiSecurityRequirement new()
{ {
[ oAuthScheme ] = new[] { "Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator" } [ oAuthScheme ] = new[] { "Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator" }
} }

View File

@ -34,8 +34,7 @@ public class EventBusRabbitMQ : IEventBus, IDisposable
_persistentConnection.TryConnect(); _persistentConnection.TryConnect();
} }
using (var channel = _persistentConnection.CreateModel()) using var channel = _persistentConnection.CreateModel();
{
channel.QueueUnbind(queue: _queueName, channel.QueueUnbind(queue: _queueName,
exchange: BROKER_NAME, exchange: BROKER_NAME,
routingKey: eventName); routingKey: eventName);
@ -46,7 +45,6 @@ public class EventBusRabbitMQ : IEventBus, IDisposable
_consumerChannel.Close(); _consumerChannel.Close();
} }
} }
}
public void Publish(IntegrationEvent @event) public void Publish(IntegrationEvent @event)
{ {
@ -66,8 +64,7 @@ public class EventBusRabbitMQ : IEventBus, IDisposable
_logger.LogTrace("Creating RabbitMQ channel to publish event: {EventId} ({EventName})", @event.Id, eventName); _logger.LogTrace("Creating RabbitMQ channel to publish event: {EventId} ({EventName})", @event.Id, eventName);
using (var channel = _persistentConnection.CreateModel()) using var channel = _persistentConnection.CreateModel();
{
_logger.LogTrace("Declaring RabbitMQ exchange to publish event: {EventId}", @event.Id); _logger.LogTrace("Declaring RabbitMQ exchange to publish event: {EventId}", @event.Id);
channel.ExchangeDeclare(exchange: BROKER_NAME, type: "direct"); channel.ExchangeDeclare(exchange: BROKER_NAME, type: "direct");
@ -92,7 +89,6 @@ public class EventBusRabbitMQ : IEventBus, IDisposable
body: body); body: body);
}); });
} }
}
public void SubscribeDynamic<TH>(string eventName) public void SubscribeDynamic<TH>(string eventName)
where TH : IDynamicIntegrationEventHandler where TH : IDynamicIntegrationEventHandler
@ -244,15 +240,13 @@ public class EventBusRabbitMQ : IEventBus, IDisposable
if (_subsManager.HasSubscriptionsForEvent(eventName)) 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); var subscriptions = _subsManager.GetHandlersForEvent(eventName);
foreach (var subscription in subscriptions) foreach (var subscription in subscriptions)
{ {
if (subscription.IsDynamic) if (subscription.IsDynamic)
{ {
var handler = scope.ResolveOptional(subscription.HandlerType) as IDynamicIntegrationEventHandler; if (scope.ResolveOptional(subscription.HandlerType) is not IDynamicIntegrationEventHandler handler) continue;
if (handler == null) continue;
using dynamic eventData = JsonDocument.Parse(message); using dynamic eventData = JsonDocument.Parse(message);
await Task.Yield(); await Task.Yield();
await handler.Handle(eventData); await handler.Handle(eventData);
@ -270,7 +264,6 @@ public class EventBusRabbitMQ : IEventBus, IDisposable
} }
} }
} }
}
else else
{ {
_logger.LogWarning("No subscription for RabbitMQ event: {EventName}", eventName); _logger.LogWarning("No subscription for RabbitMQ event: {EventName}", eventName);

View File

@ -155,15 +155,13 @@ public class EventBusServiceBus : IEventBus, IDisposable
var processed = false; var processed = false;
if (_subsManager.HasSubscriptionsForEvent(eventName)) if (_subsManager.HasSubscriptionsForEvent(eventName))
{ {
using (var scope = _autofac.BeginLifetimeScope(AUTOFAC_SCOPE_NAME)) var scope = _autofac.BeginLifetimeScope(AUTOFAC_SCOPE_NAME);
{
var subscriptions = _subsManager.GetHandlersForEvent(eventName); var subscriptions = _subsManager.GetHandlersForEvent(eventName);
foreach (var subscription in subscriptions) foreach (var subscription in subscriptions)
{ {
if (subscription.IsDynamic) if (subscription.IsDynamic)
{ {
var handler = scope.ResolveOptional(subscription.HandlerType) as IDynamicIntegrationEventHandler; if (scope.ResolveOptional(subscription.HandlerType) is not IDynamicIntegrationEventHandler handler) continue;
if (handler == null) continue;
using dynamic eventData = JsonDocument.Parse(message); using dynamic eventData = JsonDocument.Parse(message);
await handler.Handle(eventData); await handler.Handle(eventData);
@ -180,7 +178,6 @@ public class EventBusServiceBus : IEventBus, IDisposable
} }
} }
processed = true; processed = true;
}
return processed; return processed;
} }

View File

@ -15,11 +15,9 @@ public class ResilientTransaction
var strategy = _context.Database.CreateExecutionStrategy(); var strategy = _context.Database.CreateExecutionStrategy();
await strategy.ExecuteAsync(async () => await strategy.ExecuteAsync(async () =>
{ {
using (var transaction = _context.Database.BeginTransaction()) using var transaction = _context.Database.BeginTransaction();
{
await action(); await action();
transaction.Commit(); transaction.Commit();
}
}); });
} }
} }

View File

@ -21,8 +21,7 @@ namespace Microsoft.AspNetCore.Hosting
{ {
var underK8s = webHost.IsInKubernetes(); var underK8s = webHost.IsInKubernetes();
using (var scope = webHost.Services.CreateScope()) using var scope = webHost.Services.CreateScope();
{
var services = scope.ServiceProvider; var services = scope.ServiceProvider;
var logger = services.GetRequiredService<ILogger<TContext>>(); var logger = services.GetRequiredService<ILogger<TContext>>();
var context = services.GetService<TContext>(); var context = services.GetService<TContext>();
@ -64,7 +63,6 @@ namespace Microsoft.AspNetCore.Hosting
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;
} }

View File

@ -20,7 +20,7 @@ public class AuthorizeCheckOperationFilter : IOperationFilter
operation.Security = new List<OpenApiSecurityRequirement> operation.Security = new List<OpenApiSecurityRequirement>
{ {
new OpenApiSecurityRequirement new()
{ {
[ oAuthScheme ] = new [] { "basketapi" } [ oAuthScheme ] = new [] { "basketapi" }
} }

View File

@ -6,33 +6,28 @@ public class BasketScenarios
[Fact] [Fact]
public async Task Post_basket_and_response_ok_status_code() public async Task Post_basket_and_response_ok_status_code()
{ {
using (var server = CreateServer()) using var server = CreateServer();
{
var content = new StringContent(BuildBasket(), UTF8Encoding.UTF8, "application/json"); var content = new StringContent(BuildBasket(), UTF8Encoding.UTF8, "application/json");
var response = await server.CreateClient() var response = await server.CreateClient()
.PostAsync(Post.Basket, content); .PostAsync(Post.Basket, content);
response.EnsureSuccessStatusCode(); response.EnsureSuccessStatusCode();
} }
}
[Fact] [Fact]
public async Task Get_basket_and_response_ok_status_code() public async Task Get_basket_and_response_ok_status_code()
{ {
using (var server = CreateServer()) using var server = CreateServer();
{
var response = await server.CreateClient() var response = await server.CreateClient()
.GetAsync(Get.GetBasket(1)); .GetAsync(Get.GetBasket(1));
response.EnsureSuccessStatusCode(); response.EnsureSuccessStatusCode();
} }
}
[Fact] [Fact]
public async Task Send_Checkout_basket_and_response_ok_status_code() public async Task Send_Checkout_basket_and_response_ok_status_code()
{ {
using (var server = CreateServer()) using var server = CreateServer();
{
var contentBasket = new StringContent(BuildBasket(), UTF8Encoding.UTF8, "application/json"); var contentBasket = new StringContent(BuildBasket(), UTF8Encoding.UTF8, "application/json");
await server.CreateClient() await server.CreateClient()
@ -45,7 +40,6 @@ public class BasketScenarios
response.EnsureSuccessStatusCode(); response.EnsureSuccessStatusCode();
} }
}
string BuildBasket() string BuildBasket()
{ {

View File

@ -9,8 +9,7 @@ namespace Basket.FunctionalTests
[Fact] [Fact]
public async Task UpdateBasket_return_and_add_basket() public async Task UpdateBasket_return_and_add_basket()
{ {
using (var server = CreateServer()) using var server = CreateServer();
{
var redis = server.Host.Services.GetRequiredService<ConnectionMultiplexer>(); var redis = server.Host.Services.GetRequiredService<ConnectionMultiplexer>();
var redisBasketRepository = BuildBasketRepository(redis); var redisBasketRepository = BuildBasketRepository(redis);
@ -23,7 +22,6 @@ namespace Basket.FunctionalTests
Assert.NotNull(basket); Assert.NotNull(basket);
Assert.Single(basket.Items); Assert.Single(basket.Items);
}
} }
@ -32,8 +30,7 @@ namespace Basket.FunctionalTests
public async Task Delete_Basket_return_null() public async Task Delete_Basket_return_null()
{ {
using (var server = CreateServer()) using var server = CreateServer();
{
var redis = server.Host.Services.GetRequiredService<ConnectionMultiplexer>(); var redis = server.Host.Services.GetRequiredService<ConnectionMultiplexer>();
var redisBasketRepository = BuildBasketRepository(redis); var redisBasketRepository = BuildBasketRepository(redis);
@ -51,7 +48,6 @@ namespace Basket.FunctionalTests
Assert.True(deleteResult); Assert.True(deleteResult);
Assert.Null(result); Assert.Null(result);
} }
}
RedisBasketRepository BuildBasketRepository(ConnectionMultiplexer connMux) RedisBasketRepository BuildBasketRepository(ConnectionMultiplexer connMux)
{ {

View File

@ -47,40 +47,18 @@ public class PicController : ControllerBase
private string GetImageMimeTypeFromImageFileExtension(string extension) private string GetImageMimeTypeFromImageFileExtension(string extension)
{ {
string mimetype; string mimetype = extension switch
switch (extension)
{ {
case ".png": ".png" => "image/png",
mimetype = "image/png"; ".gif" => "image/gif",
break; ".jpg" or ".jpeg" => "image/jpeg",
case ".gif": ".bmp" => "image/bmp",
mimetype = "image/gif"; ".tiff" => "image/tiff",
break; ".wmf" => "image/wmf",
case ".jpg": ".jp2" => "image/jp2",
case ".jpeg": ".svg" => "image/svg+xml",
mimetype = "image/jpeg"; _ => "application/octet-stream",
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;
}
return mimetype; return mimetype;
} }
} }

View File

@ -1,122 +0,0 @@
namespace Catalog.API.Extensions;
public static class HostExtensions
{
public static bool IsInKubernetes(this IHost host)
{
var cfg = host.Services.GetService<IConfiguration>();
var orchestratorType = cfg.GetValue<string>("OrchestratorType");
return orchestratorType?.ToUpper() == "K8S";
}
public static IHost MigrateDbContext<TContext>(this IHost host, Action<TContext, IServiceProvider> seeder) where TContext : DbContext
{
var underK8s = host.IsInKubernetes();
using (var scope = host.Services.CreateScope())
{
var services = scope.ServiceProvider;
var logger = services.GetRequiredService<ILogger<TContext>>();
var context = services.GetService<TContext>();
try
{
logger.LogInformation("Migrating database associated with context {DbContextName}", typeof(TContext).Name);
if (underK8s)
{
InvokeSeeder(seeder, context, services);
}
else
{
var retry = Policy.Handle<SqlException>()
.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<TContext>(this IWebHost host, Action<TContext, IServiceProvider> seeder) where TContext : DbContext
{
var underK8s = host.IsInKubernetes();
using (var scope = host.Services.CreateScope())
{
var services = scope.ServiceProvider;
var logger = services.GetRequiredService<ILogger<TContext>>();
var context = services.GetService<TContext>();
try
{
logger.LogInformation("Migrating database associated with context {DbContextName}", typeof(TContext).Name);
if (underK8s)
{
InvokeSeeder(seeder, context, services);
}
else
{
var retry = Policy.Handle<SqlException>()
.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<TContext>(Action<TContext, IServiceProvider> seeder, TContext context, IServiceProvider services)
where TContext : DbContext
{
context.Database.Migrate();
seeder(context, services);
}
}

View File

@ -13,8 +13,7 @@ public static class WebHostExtensions
{ {
var underK8s = host.IsInKubernetes(); var underK8s = host.IsInKubernetes();
using (var scope = host.Services.CreateScope()) using var scope = host.Services.CreateScope();
{
var services = scope.ServiceProvider; var services = scope.ServiceProvider;
var logger = services.GetRequiredService<ILogger<TContext>>(); var logger = services.GetRequiredService<ILogger<TContext>>();
@ -56,7 +55,6 @@ public static class WebHostExtensions
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 host; return host;
} }

View File

@ -92,11 +92,11 @@ public class CatalogContextSeed
{ {
return new List<CatalogBrand>() return new List<CatalogBrand>()
{ {
new CatalogBrand() { Brand = "Azure"}, new() { Brand = "Azure"},
new CatalogBrand() { Brand = ".NET" }, new() { Brand = ".NET" },
new CatalogBrand() { Brand = "Visual Studio" }, new() { Brand = "Visual Studio" },
new CatalogBrand() { Brand = "SQL Server" }, new() { Brand = "SQL Server" },
new CatalogBrand() { Brand = "Other" } new() { Brand = "Other" }
}; };
} }
@ -147,10 +147,10 @@ public class CatalogContextSeed
{ {
return new List<CatalogType>() return new List<CatalogType>()
{ {
new CatalogType() { Type = "Mug"}, new() { Type = "Mug"},
new CatalogType() { Type = "T-Shirt" }, new() { Type = "T-Shirt" },
new CatalogType() { Type = "Sheet" }, new() { Type = "Sheet" },
new CatalogType() { Type = "USB Memory Stick" } new() { Type = "USB Memory Stick" }
}; };
} }
@ -297,18 +297,18 @@ public class CatalogContextSeed
{ {
return new List<CatalogItem>() return new List<CatalogItem>()
{ {
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() { 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() { 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() { 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() { 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() { 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() { 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() { 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() { 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<T> White Mug", Name = "Cup<T> White Mug", Price = 12, PictureFileName = "9.png" }, new() { CatalogTypeId = 1, CatalogBrandId = 5, AvailableStock = 100, Description = "Cup<T> White Mug", Name = "Cup<T> 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() { 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<T> Sheet", Name = "Cup<T> Sheet", Price = 8.5M, PictureFileName = "11.png" }, new() { CatalogTypeId = 3, CatalogBrandId = 2, AvailableStock = 100, Description = "Cup<T> Sheet", Name = "Cup<T> 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 = 5, AvailableStock = 100, Description = "Prism White TShirt", Name = "Prism White TShirt", Price = 12, PictureFileName = "12.png" },
}; };
} }

View File

@ -6,135 +6,113 @@ public class CatalogScenarios
[Fact] [Fact]
public async Task Get_get_all_catalogitems_and_response_ok_status_code() public async Task Get_get_all_catalogitems_and_response_ok_status_code()
{ {
using (var server = CreateServer()) using var server = CreateServer();
{
var response = await server.CreateClient() var response = await server.CreateClient()
.GetAsync(Get.Items()); .GetAsync(Get.Items());
response.EnsureSuccessStatusCode(); response.EnsureSuccessStatusCode();
} }
}
[Fact] [Fact]
public async Task Get_get_catalogitem_by_id_and_response_ok_status_code() public async Task Get_get_catalogitem_by_id_and_response_ok_status_code()
{ {
using (var server = CreateServer()) using var server = CreateServer();
{
var response = await server.CreateClient() var response = await server.CreateClient()
.GetAsync(Get.ItemById(1)); .GetAsync(Get.ItemById(1));
response.EnsureSuccessStatusCode(); response.EnsureSuccessStatusCode();
} }
}
[Fact] [Fact]
public async Task Get_get_catalogitem_by_id_and_response_bad_request_status_code() public async Task Get_get_catalogitem_by_id_and_response_bad_request_status_code()
{ {
using (var server = CreateServer()) using var server = CreateServer();
{
var response = await server.CreateClient() var response = await server.CreateClient()
.GetAsync(Get.ItemById(int.MinValue)); .GetAsync(Get.ItemById(int.MinValue));
Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode);
} }
}
[Fact] [Fact]
public async Task Get_get_catalogitem_by_id_and_response_not_found_status_code() public async Task Get_get_catalogitem_by_id_and_response_not_found_status_code()
{ {
using (var server = CreateServer()) using var server = CreateServer();
{
var response = await server.CreateClient() var response = await server.CreateClient()
.GetAsync(Get.ItemById(int.MaxValue)); .GetAsync(Get.ItemById(int.MaxValue));
Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);
} }
}
[Fact] [Fact]
public async Task Get_get_catalogitem_by_name_and_response_ok_status_code() public async Task Get_get_catalogitem_by_name_and_response_ok_status_code()
{ {
using (var server = CreateServer()) using var server = CreateServer();
{
var response = await server.CreateClient() var response = await server.CreateClient()
.GetAsync(Get.ItemByName(".NET")); .GetAsync(Get.ItemByName(".NET"));
response.EnsureSuccessStatusCode(); response.EnsureSuccessStatusCode();
} }
}
[Fact] [Fact]
public async Task Get_get_paginated_catalogitem_by_name_and_response_ok_status_code() public async Task Get_get_paginated_catalogitem_by_name_and_response_ok_status_code()
{ {
using (var server = CreateServer()) using var server = CreateServer();
{
const bool paginated = true; const bool paginated = true;
var response = await server.CreateClient() var response = await server.CreateClient()
.GetAsync(Get.ItemByName(".NET", paginated)); .GetAsync(Get.ItemByName(".NET", paginated));
response.EnsureSuccessStatusCode(); response.EnsureSuccessStatusCode();
} }
}
[Fact] [Fact]
public async Task Get_get_paginated_catalog_items_and_response_ok_status_code() public async Task Get_get_paginated_catalog_items_and_response_ok_status_code()
{ {
using (var server = CreateServer()) using var server = CreateServer();
{
const bool paginated = true; const bool paginated = true;
var response = await server.CreateClient() var response = await server.CreateClient()
.GetAsync(Get.Items(paginated)); .GetAsync(Get.Items(paginated));
response.EnsureSuccessStatusCode(); response.EnsureSuccessStatusCode();
} }
}
[Fact] [Fact]
public async Task Get_get_filtered_catalog_items_and_response_ok_status_code() public async Task Get_get_filtered_catalog_items_and_response_ok_status_code()
{ {
using (var server = CreateServer()) using var server = CreateServer();
{
var response = await server.CreateClient() var response = await server.CreateClient()
.GetAsync(Get.Filtered(1, 1)); .GetAsync(Get.Filtered(1, 1));
response.EnsureSuccessStatusCode(); response.EnsureSuccessStatusCode();
} }
}
[Fact] [Fact]
public async Task Get_get_paginated_filtered_catalog_items_and_response_ok_status_code() public async Task Get_get_paginated_filtered_catalog_items_and_response_ok_status_code()
{ {
using (var server = CreateServer()) using var server = CreateServer();
{
const bool paginated = true; const bool paginated = true;
var response = await server.CreateClient() var response = await server.CreateClient()
.GetAsync(Get.Filtered(1, 1, paginated)); .GetAsync(Get.Filtered(1, 1, paginated));
response.EnsureSuccessStatusCode(); response.EnsureSuccessStatusCode();
} }
}
[Fact] [Fact]
public async Task Get_catalog_types_response_ok_status_code() public async Task Get_catalog_types_response_ok_status_code()
{ {
using (var server = CreateServer()) using var server = CreateServer();
{
var response = await server.CreateClient() var response = await server.CreateClient()
.GetAsync(Get.Types); .GetAsync(Get.Types);
response.EnsureSuccessStatusCode(); response.EnsureSuccessStatusCode();
} }
}
[Fact] [Fact]
public async Task Get_catalog_brands_response_ok_status_code() public async Task Get_catalog_brands_response_ok_status_code()
{ {
using (var server = CreateServer()) using var server = CreateServer();
{
var response = await server.CreateClient() var response = await server.CreateClient()
.GetAsync(Get.Brands); .GetAsync(Get.Brands);
response.EnsureSuccessStatusCode(); response.EnsureSuccessStatusCode();
} }
} }
}

View File

@ -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.AspNetCore.TestHost;
global using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF; 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.Infrastructure;
global using Microsoft.eShopOnContainers.Services.Catalog.API; global using Microsoft.eShopOnContainers.Services.Catalog.API;
global using Microsoft.Extensions.Configuration; global using Microsoft.Extensions.Configuration;

View File

@ -25,12 +25,10 @@ public class CatalogControllerTest
.UseInMemoryDatabase(databaseName: "in-memory") .UseInMemoryDatabase(databaseName: "in-memory")
.Options; .Options;
using (var dbContext = new CatalogContext(_dbOptions)) using var dbContext = new CatalogContext(_dbOptions);
{
dbContext.AddRange(GetFakeCatalog()); dbContext.AddRange(GetFakeCatalog());
dbContext.SaveChanges(); dbContext.SaveChanges();
} }
}
[Fact] [Fact]
public async Task Get_catalog_items_success() public async Task Get_catalog_items_success()
@ -66,7 +64,7 @@ public class CatalogControllerTest
{ {
return new List<CatalogItem>() return new List<CatalogItem>()
{ {
new CatalogItem() new()
{ {
Id = 1, Id = 1,
Name = "fakeItemA", Name = "fakeItemA",
@ -74,7 +72,7 @@ public class CatalogControllerTest
CatalogBrandId = 1, CatalogBrandId = 1,
PictureFileName = "fakeItemA.png" PictureFileName = "fakeItemA.png"
}, },
new CatalogItem() new()
{ {
Id = 2, Id = 2,
Name = "fakeItemB", Name = "fakeItemB",
@ -82,7 +80,7 @@ public class CatalogControllerTest
CatalogBrandId = 1, CatalogBrandId = 1,
PictureFileName = "fakeItemB.png" PictureFileName = "fakeItemB.png"
}, },
new CatalogItem() new()
{ {
Id = 3, Id = 3,
Name = "fakeItemC", Name = "fakeItemC",
@ -90,7 +88,7 @@ public class CatalogControllerTest
CatalogBrandId = 1, CatalogBrandId = 1,
PictureFileName = "fakeItemC.png" PictureFileName = "fakeItemC.png"
}, },
new CatalogItem() new()
{ {
Id = 4, Id = 4,
Name = "fakeItemD", Name = "fakeItemD",
@ -98,7 +96,7 @@ public class CatalogControllerTest
CatalogBrandId = 1, CatalogBrandId = 1,
PictureFileName = "fakeItemD.png" PictureFileName = "fakeItemD.png"
}, },
new CatalogItem() new()
{ {
Id = 5, Id = 5,
Name = "fakeItemE", Name = "fakeItemE",
@ -106,7 +104,7 @@ public class CatalogControllerTest
CatalogBrandId = 1, CatalogBrandId = 1,
PictureFileName = "fakeItemE.png" PictureFileName = "fakeItemE.png"
}, },
new CatalogItem() new()
{ {
Id = 6, Id = 6,
Name = "fakeItemF", Name = "fakeItemF",
@ -120,7 +118,7 @@ public class CatalogControllerTest
public class TestCatalogSettings : IOptionsSnapshot<CatalogSettings> public class TestCatalogSettings : IOptionsSnapshot<CatalogSettings>
{ {
public CatalogSettings Value => new CatalogSettings public CatalogSettings Value => new()
{ {
PicBaseUrl = "http://image-server.com/", PicBaseUrl = "http://image-server.com/",
AzureStorageEnabled = true AzureStorageEnabled = true

View File

@ -12,17 +12,14 @@
* real environment the certificate should be created and stored in a secure way, which is out * real environment the certificate should be created and stored in a secure way, which is out
* of the scope of this project. * of the scope of this project.
**********************************************************************************************/ **********************************************************************************************/
using (var stream = assembly.GetManifestResourceStream("Identity.API.Certificate.idsrv3test.pfx")) using var stream = assembly.GetManifestResourceStream("Identity.API.Certificate.idsrv3test.pfx");
{
return new X509Certificate2(ReadStream(stream), "idsrv3test"); return new X509Certificate2(ReadStream(stream), "idsrv3test");
} }
}
private static byte[] ReadStream(Stream input) private static byte[] ReadStream(Stream input)
{ {
byte[] buffer = new byte[16 * 1024]; byte[] buffer = new byte[16 * 1024];
using (MemoryStream ms = new MemoryStream()) using MemoryStream ms = new MemoryStream();
{
int read; int read;
while ((read = input.Read(buffer, 0, buffer.Length)) > 0) while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
{ {
@ -32,4 +29,3 @@
} }
} }
} }
}

View File

@ -191,8 +191,7 @@
string imagePath = Path.Combine(webroot, "images"); string imagePath = Path.Combine(webroot, "images");
string[] imageFiles = Directory.GetFiles(imagePath).Select(file => Path.GetFileName(file)).ToArray(); 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))
@ -210,7 +209,6 @@
} }
} }
} }
}
catch (Exception ex) catch (Exception ex)
{ {
logger.LogError(ex, "EXCEPTION ERROR: {Message}", ex.Message); ; logger.LogError(ex, "EXCEPTION ERROR: {Message}", ex.Message); ;

View File

@ -13,8 +13,7 @@ namespace Microsoft.AspNetCore.Hosting
{ {
var underK8s = webHost.IsInKubernetes(); var underK8s = webHost.IsInKubernetes();
using (var scope = webHost.Services.CreateScope()) using var scope = webHost.Services.CreateScope();
{
var services = scope.ServiceProvider; var services = scope.ServiceProvider;
var logger = services.GetRequiredService<ILogger<TContext>>(); var logger = services.GetRequiredService<ILogger<TContext>>();
var context = services.GetService<TContext>(); var context = services.GetService<TContext>();
@ -56,7 +55,6 @@ namespace Microsoft.AspNetCore.Hosting
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;
} }

View File

@ -35,7 +35,7 @@ public class TransactionBehaviour<TRequest, TResponse> : IPipelineBehavior<TRequ
{ {
Guid transactionId; Guid transactionId;
using (var transaction = await _dbContext.BeginTransactionAsync()) using var transaction = await _dbContext.BeginTransactionAsync();
using (LogContext.PushProperty("TransactionContext", transaction.TransactionId)) using (LogContext.PushProperty("TransactionContext", transaction.TransactionId))
{ {
_logger.LogInformation("----- Begin transaction {TransactionId} for {CommandName} ({@Command})", transaction.TransactionId, typeName, request); _logger.LogInformation("----- Begin transaction {TransactionId} for {CommandName} ({@Command})", transaction.TransactionId, typeName, request);

View File

@ -13,8 +13,7 @@ public class OrderQueries
public async Task<Order> GetOrderAsync(int id) public async Task<Order> GetOrderAsync(int id)
{ {
using (var connection = new SqlConnection(_connectionString)) using var connection = new SqlConnection(_connectionString);
{
connection.Open(); connection.Open();
var result = await connection.QueryAsync<dynamic>( var result = await connection.QueryAsync<dynamic>(
@ -34,12 +33,10 @@ public class OrderQueries
return MapOrderItems(result); return MapOrderItems(result);
} }
}
public async Task<IEnumerable<OrderSummary>> GetOrdersFromUserAsync(Guid userId) public async Task<IEnumerable<OrderSummary>> GetOrdersFromUserAsync(Guid userId)
{ {
using (var connection = new SqlConnection(_connectionString)) using var connection = new SqlConnection(_connectionString);
{
connection.Open(); connection.Open();
return await connection.QueryAsync<OrderSummary>(@"SELECT o.[Id] as ordernumber,o.[OrderDate] as [date],os.[Name] as [status], SUM(oi.units*oi.unitprice) as total return await connection.QueryAsync<OrderSummary>(@"SELECT o.[Id] as ordernumber,o.[OrderDate] as [date],os.[Name] as [status], SUM(oi.units*oi.unitprice) as total
@ -51,17 +48,14 @@ public class OrderQueries
GROUP BY o.[Id], o.[OrderDate], os.[Name] GROUP BY o.[Id], o.[OrderDate], os.[Name]
ORDER BY o.[Id]", new { userId }); ORDER BY o.[Id]", new { userId });
} }
}
public async Task<IEnumerable<CardType>> GetCardTypesAsync() public async Task<IEnumerable<CardType>> GetCardTypesAsync()
{ {
using (var connection = new SqlConnection(_connectionString)) using var connection = new SqlConnection(_connectionString);
{
connection.Open(); connection.Open();
return await connection.QueryAsync<CardType>("SELECT * FROM ordering.cardtypes"); return await connection.QueryAsync<CardType>("SELECT * FROM ordering.cardtypes");
} }
}
private Order MapOrderItems(dynamic result) private Order MapOrderItems(dynamic result)
{ {

View File

@ -20,7 +20,7 @@ public class AuthorizeCheckOperationFilter : IOperationFilter
operation.Security = new List<OpenApiSecurityRequirement> operation.Security = new List<OpenApiSecurityRequirement>
{ {
new OpenApiSecurityRequirement new()
{ {
[ oAuthScheme ] = new [] { "orderingapi" } [ oAuthScheme ] = new [] { "orderingapi" }
} }

View File

@ -63,8 +63,7 @@ namespace Ordering.BackgroundTasks.Services
{ {
IEnumerable<int> orderIds = new List<int>(); IEnumerable<int> orderIds = new List<int>();
using (var conn = new SqlConnection(_settings.ConnectionString)) using var conn = new SqlConnection(_settings.ConnectionString);
{
try try
{ {
conn.Open(); conn.Open();
@ -79,7 +78,6 @@ namespace Ordering.BackgroundTasks.Services
_logger.LogCritical(exception, "FATAL ERROR: Database connections could not be opened: {Message}", exception.Message); _logger.LogCritical(exception, "FATAL ERROR: Database connections could not be opened: {Message}", exception.Message);
} }
}
return orderIds; return orderIds;
} }

View File

@ -14,40 +14,34 @@ namespace Ordering.FunctionalTests
[Fact] [Fact]
public async Task Get_get_all_stored_orders_and_response_ok_status_code() public async Task Get_get_all_stored_orders_and_response_ok_status_code()
{ {
using (var server = CreateServer()) using var server = CreateServer();
{
var response = await server.CreateClient() var response = await server.CreateClient()
.GetAsync(Get.Orders); .GetAsync(Get.Orders);
response.EnsureSuccessStatusCode(); response.EnsureSuccessStatusCode();
} }
}
[Fact] [Fact]
public async Task Cancel_order_no_order_created_bad_request_response() public async Task Cancel_order_no_order_created_bad_request_response()
{ {
using (var server = CreateServer()) using var server = CreateServer();
{
var content = new StringContent(BuildOrder(), UTF8Encoding.UTF8, "application/json"); var content = new StringContent(BuildOrder(), UTF8Encoding.UTF8, "application/json");
var response = await server.CreateIdempotentClient() var response = await server.CreateIdempotentClient()
.PutAsync(Put.CancelOrder, content); .PutAsync(Put.CancelOrder, content);
Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode);
} }
}
[Fact] [Fact]
public async Task Ship_order_no_order_created_bad_request_response() public async Task Ship_order_no_order_created_bad_request_response()
{ {
using (var server = CreateServer()) using var server = CreateServer();
{
var content = new StringContent(BuildOrder(), UTF8Encoding.UTF8, "application/json"); var content = new StringContent(BuildOrder(), UTF8Encoding.UTF8, "application/json");
var response = await server.CreateIdempotentClient() var response = await server.CreateIdempotentClient()
.PutAsync(Put.ShipOrder, content); .PutAsync(Put.ShipOrder, content);
Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode);
} }
}
string BuildOrder() string BuildOrder()
{ {

View File

@ -20,7 +20,7 @@ public class AuthorizeCheckOperationFilter : IOperationFilter
operation.Security = new List<OpenApiSecurityRequirement> operation.Security = new List<OpenApiSecurityRequirement>
{ {
new OpenApiSecurityRequirement new()
{ {
[ oAuthScheme ] = new [] { "webhooksapi" } [ oAuthScheme ] = new [] { "webhooksapi" }
} }

View File

@ -11,9 +11,8 @@ public class IntegrationEventsScenarios
decimal priceModification = 0.15M; decimal priceModification = 0.15M;
string userId = "JohnId"; string userId = "JohnId";
using (var catalogServer = new CatalogScenariosBase().CreateServer()) using var catalogServer = new CatalogScenariosBase().CreateServer();
using (var basketServer = new BasketScenariosBase().CreateServer()) using var basketServer = new BasketScenariosBase().CreateServer();
{
var catalogClient = catalogServer.CreateClient(); var catalogClient = catalogServer.CreateClient();
var basketClient = basketServer.CreateClient(); var basketClient = basketServer.CreateClient();
@ -51,7 +50,6 @@ public class IntegrationEventsScenarios
Assert.Equal(oldPrice, itemUpdated.OldUnitPrice); Assert.Equal(oldPrice, itemUpdated.OldUnitPrice);
} }
} }
}
private async Task<BasketItem> GetUpdatedBasketItem(decimal newPrice, int productId, string userId, HttpClient basketClient) private async Task<BasketItem> GetUpdatedBasketItem(decimal newPrice, int productId, string userId, HttpClient basketClient)
{ {

View File

@ -5,9 +5,8 @@ public class OrderingScenarios : OrderingScenariosBase
[Fact] [Fact]
public async Task Cancel_basket_and_check_order_status_cancelled() public async Task Cancel_basket_and_check_order_status_cancelled()
{ {
using (var orderServer = new OrderingScenariosBase().CreateServer()) using var orderServer = new OrderingScenariosBase().CreateServer();
using (var basketServer = new BasketScenariosBase().CreateServer()) using var basketServer = new BasketScenariosBase().CreateServer();
{
// Expected data // Expected data
var cityExpected = $"city-{Guid.NewGuid()}"; var cityExpected = $"city-{Guid.NewGuid()}";
var orderStatusExpected = "cancelled"; var orderStatusExpected = "cancelled";
@ -34,7 +33,6 @@ public class OrderingScenarios : OrderingScenariosBase
// THEN check status // THEN check status
Assert.Equal(orderStatusExpected, order.Status); Assert.Equal(orderStatusExpected, order.Status);
} }
}
async Task<Order> TryGetOrder(string orderNumber, HttpClient orderClient) async Task<Order> TryGetOrder(string orderNumber, HttpClient orderClient)
{ {

View File

@ -56,8 +56,7 @@ public class WebContextSeed
string imagePath = Path.Combine(webroot, "images"); string imagePath = Path.Combine(webroot, "images");
string[] imageFiles = Directory.GetFiles(imagePath).Select(file => Path.GetFileName(file)).ToArray(); 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))
@ -75,7 +74,6 @@ public class WebContextSeed
} }
} }
} }
}
catch (Exception ex) catch (Exception ex)
{ {
log.Error(ex, "EXCEPTION ERROR: {Message}", ex.Message); log.Error(ex, "EXCEPTION ERROR: {Message}", ex.Message);

View File

@ -39,8 +39,7 @@ public class WebContextSeed
} }
string[] imageFiles = Directory.GetFiles(imagePath).Select(file => Path.GetFileName(file)).ToArray(); 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))
@ -58,7 +57,6 @@ public class WebContextSeed
} }
} }
} }
}
catch (Exception ex) catch (Exception ex)
{ {
log.LogError(ex, "ERROR in GetPreconfiguredImages: {Message}", ex.Message); log.LogError(ex, "ERROR in GetPreconfiguredImages: {Message}", ex.Message);