Adding various language enhancements, removing unused/duplicated extension

This commit is contained in:
szukuro 2022-03-23 15:26:45 +01:00
parent 981507dccb
commit 303c958e43
29 changed files with 447 additions and 671 deletions

View File

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

View File

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

View File

@ -34,8 +34,7 @@ public class EventBusRabbitMQ : IEventBus, IDisposable
_persistentConnection.TryConnect();
}
using (var channel = _persistentConnection.CreateModel())
{
using var channel = _persistentConnection.CreateModel();
channel.QueueUnbind(queue: _queueName,
exchange: BROKER_NAME,
routingKey: eventName);
@ -46,7 +45,6 @@ public class EventBusRabbitMQ : IEventBus, IDisposable
_consumerChannel.Close();
}
}
}
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);
using (var channel = _persistentConnection.CreateModel())
{
using var channel = _persistentConnection.CreateModel();
_logger.LogTrace("Declaring RabbitMQ exchange to publish event: {EventId}", @event.Id);
channel.ExchangeDeclare(exchange: BROKER_NAME, type: "direct");
@ -92,7 +89,6 @@ public class EventBusRabbitMQ : IEventBus, IDisposable
body: body);
});
}
}
public void SubscribeDynamic<TH>(string eventName)
where TH : IDynamicIntegrationEventHandler
@ -244,15 +240,13 @@ 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)
{
if (subscription.IsDynamic)
{
var handler = scope.ResolveOptional(subscription.HandlerType) as IDynamicIntegrationEventHandler;
if (handler == null) continue;
if (scope.ResolveOptional(subscription.HandlerType) is not IDynamicIntegrationEventHandler handler) continue;
using dynamic eventData = JsonDocument.Parse(message);
await Task.Yield();
await handler.Handle(eventData);
@ -262,7 +256,7 @@ public class EventBusRabbitMQ : IEventBus, IDisposable
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 integrationEvent = JsonSerializer.Deserialize(message, eventType, new JsonSerializerOptions() { PropertyNameCaseInsensitive = true });
var concreteType = typeof(IIntegrationEventHandler<>).MakeGenericType(eventType);
await Task.Yield();
@ -270,7 +264,6 @@ public class EventBusRabbitMQ : IEventBus, IDisposable
}
}
}
}
else
{
_logger.LogWarning("No subscription for RabbitMQ event: {EventName}", eventName);

View File

@ -155,15 +155,13 @@ 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)
{
if (subscription.IsDynamic)
{
var handler = scope.ResolveOptional(subscription.HandlerType) as IDynamicIntegrationEventHandler;
if (handler == null) continue;
if (scope.ResolveOptional(subscription.HandlerType) is not IDynamicIntegrationEventHandler handler) continue;
using dynamic eventData = JsonDocument.Parse(message);
await handler.Handle(eventData);
@ -180,7 +178,6 @@ public class EventBusServiceBus : IEventBus, IDisposable
}
}
processed = true;
}
return processed;
}

View File

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

View File

@ -21,8 +21,7 @@ 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<ILogger<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
}
}
}
return webHost;
}

View File

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

View File

@ -6,33 +6,28 @@ public class BasketScenarios
[Fact]
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 response = await server.CreateClient()
.PostAsync(Post.Basket, content);
response.EnsureSuccessStatusCode();
}
}
[Fact]
public async Task Get_basket_and_response_ok_status_code()
{
using (var server = CreateServer())
{
using var server = CreateServer();
var response = await server.CreateClient()
.GetAsync(Get.GetBasket(1));
response.EnsureSuccessStatusCode();
}
}
[Fact]
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");
await server.CreateClient()
@ -45,7 +40,6 @@ public class BasketScenarios
response.EnsureSuccessStatusCode();
}
}
string BuildBasket()
{

View File

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

View File

@ -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;
}
}

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();
using (var scope = host.Services.CreateScope())
{
using var scope = host.Services.CreateScope();
var services = scope.ServiceProvider;
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
}
}
}
return host;
}

View File

@ -92,11 +92,11 @@ public class CatalogContextSeed
{
return new List<CatalogBrand>()
{
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<CatalogType>()
{
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<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 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<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 CatalogItem { 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 = 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<T> White Mug", Name = "Cup<T> 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<T> Sheet", Name = "Cup<T> 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" },
};
}

View File

@ -6,135 +6,113 @@ public class CatalogScenarios
[Fact]
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()
.GetAsync(Get.Items());
response.EnsureSuccessStatusCode();
}
}
[Fact]
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()
.GetAsync(Get.ItemById(1));
response.EnsureSuccessStatusCode();
}
}
[Fact]
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()
.GetAsync(Get.ItemById(int.MinValue));
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())
{
using var server = CreateServer();
var response = await server.CreateClient()
.GetAsync(Get.ItemById(int.MaxValue));
Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);
}
}
[Fact]
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()
.GetAsync(Get.ItemByName(".NET"));
response.EnsureSuccessStatusCode();
}
}
[Fact]
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;
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())
{
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())
{
using var server = CreateServer();
var response = await server.CreateClient()
.GetAsync(Get.Filtered(1, 1));
response.EnsureSuccessStatusCode();
}
}
[Fact]
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;
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())
{
using var server = CreateServer();
var response = await server.CreateClient()
.GetAsync(Get.Types);
response.EnsureSuccessStatusCode();
}
}
[Fact]
public async Task Get_catalog_brands_response_ok_status_code()
{
using (var server = CreateServer())
{
using var server = CreateServer();
var response = await server.CreateClient()
.GetAsync(Get.Brands);
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.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;

View File

@ -25,12 +25,10 @@ public class CatalogControllerTest
.UseInMemoryDatabase(databaseName: "in-memory")
.Options;
using (var dbContext = new CatalogContext(_dbOptions))
{
using var dbContext = new CatalogContext(_dbOptions);
dbContext.AddRange(GetFakeCatalog());
dbContext.SaveChanges();
}
}
[Fact]
public async Task Get_catalog_items_success()
@ -66,7 +64,7 @@ public class CatalogControllerTest
{
return new List<CatalogItem>()
{
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<CatalogSettings>
{
public CatalogSettings Value => new CatalogSettings
public CatalogSettings Value => new()
{
PicBaseUrl = "http://image-server.com/",
AzureStorageEnabled = true

View File

@ -12,17 +12,14 @@
* 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"))
{
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)
{
@ -31,5 +28,4 @@
return ms.ToArray();
}
}
}
}

View File

@ -191,8 +191,7 @@
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)
{
if (imageFiles.Contains(entry.Name))
@ -210,7 +209,6 @@
}
}
}
}
catch (Exception ex)
{
logger.LogError(ex, "EXCEPTION ERROR: {Message}", ex.Message); ;

View File

@ -13,8 +13,7 @@ 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<ILogger<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
}
}
}
return webHost;
}

View File

@ -35,7 +35,7 @@ public class TransactionBehaviour<TRequest, TResponse> : IPipelineBehavior<TRequ
{
Guid transactionId;
using (var transaction = await _dbContext.BeginTransactionAsync())
using var transaction = await _dbContext.BeginTransactionAsync();
using (LogContext.PushProperty("TransactionContext", transaction.TransactionId))
{
_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)
{
using (var connection = new SqlConnection(_connectionString))
{
using var connection = new SqlConnection(_connectionString);
connection.Open();
var result = await connection.QueryAsync<dynamic>(
@ -34,12 +33,10 @@ public class OrderQueries
return MapOrderItems(result);
}
}
public async Task<IEnumerable<OrderSummary>> GetOrdersFromUserAsync(Guid userId)
{
using (var connection = new SqlConnection(_connectionString))
{
using var connection = new SqlConnection(_connectionString);
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
@ -51,17 +48,14 @@ public class OrderQueries
GROUP BY o.[Id], o.[OrderDate], os.[Name]
ORDER BY o.[Id]", new { userId });
}
}
public async Task<IEnumerable<CardType>> GetCardTypesAsync()
{
using (var connection = new SqlConnection(_connectionString))
{
using var connection = new SqlConnection(_connectionString);
connection.Open();
return await connection.QueryAsync<CardType>("SELECT * FROM ordering.cardtypes");
}
}
private Order MapOrderItems(dynamic result)
{

View File

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

View File

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

View File

@ -14,40 +14,34 @@ namespace Ordering.FunctionalTests
[Fact]
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()
.GetAsync(Get.Orders);
response.EnsureSuccessStatusCode();
}
}
[Fact]
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 response = await server.CreateIdempotentClient()
.PutAsync(Put.CancelOrder, content);
Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode);
}
}
[Fact]
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 response = await server.CreateIdempotentClient()
.PutAsync(Put.ShipOrder, content);
Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode);
}
}
string BuildOrder()
{

View File

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

View File

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

View File

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

View File

@ -56,8 +56,7 @@ 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)
{
if (imageFiles.Contains(entry.Name))
@ -75,7 +74,6 @@ public class WebContextSeed
}
}
}
}
catch (Exception ex)
{
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();
using (ZipArchive zip = ZipFile.Open(imagesZipFile, ZipArchiveMode.Read))
{
using ZipArchive zip = ZipFile.Open(imagesZipFile, ZipArchiveMode.Read);
foreach (ZipArchiveEntry entry in zip.Entries)
{
if (!imageFiles.Contains(entry.Name))
@ -58,7 +57,6 @@ public class WebContextSeed
}
}
}
}
catch (Exception ex)
{
log.LogError(ex, "ERROR in GetPreconfiguredImages: {Message}", ex.Message);