From f48a50388576238d1be768f2f4f62c26cf15647f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ram=C3=B3n=20Tom=C3=A1s?= Date: Thu, 13 Apr 2017 10:51:19 +0200 Subject: [PATCH 1/3] Fix issue error when building the SPA app from the CLI #164 --- eShopOnContainers-ServicesAndWebApps.sln | 14 -------------- src/Web/WebSPA/WebSPA.csproj | 7 +++++++ 2 files changed, 7 insertions(+), 14 deletions(-) diff --git a/eShopOnContainers-ServicesAndWebApps.sln b/eShopOnContainers-ServicesAndWebApps.sln index d4d39437c..53a9ceada 100644 --- a/eShopOnContainers-ServicesAndWebApps.sln +++ b/eShopOnContainers-ServicesAndWebApps.sln @@ -39,24 +39,10 @@ EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ordering.Infrastructure", "src\Services\Ordering\Ordering.Infrastructure\Ordering.Infrastructure.csproj", "{95F1F07C-4D92-4742-BD07-E5B805AAB651}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnitTest", "test\Services\UnitTest\UnitTest.csproj", "{7796F5D8-31FC-45A4-B673-19DE5BA194CF}" - ProjectSection(ProjectDependencies) = postProject - {A579E108-5445-403D-A407-339AC4D1611B} = {A579E108-5445-403D-A407-339AC4D1611B} - {F16E3C6A-1C94-4EAB-BE91-099618060B68} = {F16E3C6A-1C94-4EAB-BE91-099618060B68} - EndProjectSection EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Identity.API", "src\Services\Identity\Identity.API\Identity.API.csproj", "{A579E108-5445-403D-A407-339AC4D1611B}" EndProject Project("{E53339B2-1760-4266-BCC7-CA923CBCF16C}") = "docker-compose", "docker-compose.dcproj", "{FEA0C318-FFED-4D39-8781-265718CA43DD}" - ProjectSection(ProjectDependencies) = postProject - {A579E108-5445-403D-A407-339AC4D1611B} = {A579E108-5445-403D-A407-339AC4D1611B} - {5B810E3D-112E-4857-B197-F09D2FD41E27} = {5B810E3D-112E-4857-B197-F09D2FD41E27} - {F16E3C6A-1C94-4EAB-BE91-099618060B68} = {F16E3C6A-1C94-4EAB-BE91-099618060B68} - {F0333D8E-0B27-42B7-B2C6-78F3657624E2} = {F0333D8E-0B27-42B7-B2C6-78F3657624E2} - {42681D9D-750A-4DF7-BD9F-9292CFD5C253} = {42681D9D-750A-4DF7-BD9F-9292CFD5C253} - {2110CBB0-3B38-4EE4-A743-DF6968D80D90} = {2110CBB0-3B38-4EE4-A743-DF6968D80D90} - {CFE2FACB-4538-4B99-8A10-306F3882952D} = {CFE2FACB-4538-4B99-8A10-306F3882952D} - {231226CE-690B-4979-8870-9A79D80928E2} = {231226CE-690B-4979-8870-9A79D80928E2} - EndProjectSection EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WebSPA", "src\Web\WebSPA\WebSPA.csproj", "{F16E3C6A-1C94-4EAB-BE91-099618060B68}" EndProject diff --git a/src/Web/WebSPA/WebSPA.csproj b/src/Web/WebSPA/WebSPA.csproj index e81a11d59..d5161d753 100644 --- a/src/Web/WebSPA/WebSPA.csproj +++ b/src/Web/WebSPA/WebSPA.csproj @@ -13,6 +13,8 @@ ..\..\..\docker-compose.dcproj false true + wwwroot/dist/** + $(DefaultItemExcludes);$(GeneratedItemPatterns) @@ -67,9 +69,14 @@ + + + <_GeneratedFiles Include="$(GeneratedItemPatterns)" /> + + From 4ef6b63913ac8bc43f420139ade6e1d552085e12 Mon Sep 17 00:00:00 2001 From: Unai Zorrilla Castro Date: Mon, 17 Apr 2017 12:28:12 +0200 Subject: [PATCH 2/3] Review on 17/04/2017 --- .../Basket/Basket.API/BasketSettings.cs | 7 +- .../InternalServerErrorObjectResult.cs | 4 -- .../OrderStartedIntegrationEventHandler.cs | 5 +- ...ductPriceChangedIntegrationEventHandler.cs | 9 ++- .../Events/OrderStartedIntegrationEvent.cs | 4 -- .../ProductPriceChangedIntegrationEvent.cs | 3 - .../Basket.API/Model/IBasketRepository.cs | 6 +- .../Basket.API/Model/RedisBasketRepository.cs | 20 +++--- src/Services/Basket/Basket.API/Startup.cs | 70 +++++++++++-------- .../Catalog/Catalog.API/CatalogSettings.cs | 9 +++ .../Controllers/CatalogController.cs | 49 +++++++------ .../Catalog.API/Controllers/HomeController.cs | 6 +- .../Catalog.API/Controllers/PicController.cs | 12 ++-- .../InternalServerErrorObjectResult.cs | 4 -- .../Exceptions/CatalogDomainException.cs | 3 - .../CatalogIntegrationEventService.cs | 1 + .../ICatalogIntegrationEventService.cs | 3 - .../Catalog/Catalog.API/Model/CatalogBrand.cs | 6 -- .../Catalog/Catalog.API/Model/CatalogType.cs | 5 -- src/Services/Catalog/Catalog.API/Startup.cs | 44 +++++++----- src/Services/Catalog/Catalog.API/settings.cs | 14 ---- .../Commands/IdentifierCommandHandler.cs | 6 +- .../Application/Queries/IOrderQueries.cs | 6 +- .../Application/Queries/OrderQueries.cs | 6 +- .../CreateOrderCommandValidator.cs | 24 +++---- .../Validations/IdentifierCommandValidator.cs | 6 +- .../Controllers/OrdersController.cs | 10 ++- src/Services/Ordering/Ordering.API/Startup.cs | 16 ++--- .../AggregatesModel/BuyerAggregate/Buyer.cs | 4 ++ .../OrderAggregate/IOrderRepository.cs | 4 +- .../Ordering.Domain/SeedWork/Enumeration.cs | 6 +- .../{ => Idempotency}/ClientRequest.cs | 4 +- .../Idempotency/IRequestManager.cs | 3 +- .../Idempotency/RequestManager.cs | 20 +++--- .../MediatorExtension.cs | 15 ++-- .../OrderingContext.cs | 3 +- .../Ordering/Application/OrdersWebApiTest.cs | 6 +- 37 files changed, 207 insertions(+), 216 deletions(-) create mode 100644 src/Services/Catalog/Catalog.API/CatalogSettings.cs delete mode 100644 src/Services/Catalog/Catalog.API/settings.cs rename src/Services/Ordering/Ordering.Infrastructure/{ => Idempotency}/ClientRequest.cs (80%) diff --git a/src/Services/Basket/Basket.API/BasketSettings.cs b/src/Services/Basket/Basket.API/BasketSettings.cs index 6aae45015..9d143545a 100644 --- a/src/Services/Basket/Basket.API/BasketSettings.cs +++ b/src/Services/Basket/Basket.API/BasketSettings.cs @@ -1,9 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; - -namespace Microsoft.eShopOnContainers.Services.Basket.API +namespace Microsoft.eShopOnContainers.Services.Basket.API { public class BasketSettings { diff --git a/src/Services/Basket/Basket.API/Infrastructure/ActionResults/InternalServerErrorObjectResult.cs b/src/Services/Basket/Basket.API/Infrastructure/ActionResults/InternalServerErrorObjectResult.cs index 2ec3727a6..a0b988156 100644 --- a/src/Services/Basket/Basket.API/Infrastructure/ActionResults/InternalServerErrorObjectResult.cs +++ b/src/Services/Basket/Basket.API/Infrastructure/ActionResults/InternalServerErrorObjectResult.cs @@ -1,9 +1,5 @@ using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; namespace Basket.API.Infrastructure.ActionResults { diff --git a/src/Services/Basket/Basket.API/IntegrationEvents/EventHandling/OrderStartedIntegrationEventHandler.cs b/src/Services/Basket/Basket.API/IntegrationEvents/EventHandling/OrderStartedIntegrationEventHandler.cs index e35badc64..19ae1b594 100644 --- a/src/Services/Basket/Basket.API/IntegrationEvents/EventHandling/OrderStartedIntegrationEventHandler.cs +++ b/src/Services/Basket/Basket.API/IntegrationEvents/EventHandling/OrderStartedIntegrationEventHandler.cs @@ -2,8 +2,6 @@ using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; using Microsoft.eShopOnContainers.Services.Basket.API.Model; using System; -using System.Collections.Generic; -using System.Linq; using System.Threading.Tasks; namespace Basket.API.IntegrationEvents.EventHandling @@ -11,9 +9,10 @@ namespace Basket.API.IntegrationEvents.EventHandling public class OrderStartedIntegrationEventHandler : IIntegrationEventHandler { private readonly IBasketRepository _repository; + public OrderStartedIntegrationEventHandler(IBasketRepository repository) { - _repository = repository; + _repository = repository ?? throw new ArgumentNullException(nameof(repository)); } public async Task Handle(OrderStartedIntegrationEvent @event) diff --git a/src/Services/Basket/Basket.API/IntegrationEvents/EventHandling/ProductPriceChangedIntegrationEventHandler.cs b/src/Services/Basket/Basket.API/IntegrationEvents/EventHandling/ProductPriceChangedIntegrationEventHandler.cs index 50d6b9e25..88244404a 100644 --- a/src/Services/Basket/Basket.API/IntegrationEvents/EventHandling/ProductPriceChangedIntegrationEventHandler.cs +++ b/src/Services/Basket/Basket.API/IntegrationEvents/EventHandling/ProductPriceChangedIntegrationEventHandler.cs @@ -1,6 +1,7 @@ using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; using Microsoft.eShopOnContainers.Services.Basket.API.IntegrationEvents.Events; using Microsoft.eShopOnContainers.Services.Basket.API.Model; +using System; using System.Linq; using System.Threading.Tasks; @@ -9,17 +10,20 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API.IntegrationEvents.Even public class ProductPriceChangedIntegrationEventHandler : IIntegrationEventHandler { private readonly IBasketRepository _repository; + public ProductPriceChangedIntegrationEventHandler(IBasketRepository repository) { - _repository = repository; + _repository = repository ?? throw new ArgumentNullException(nameof(repository)); } public async Task Handle(ProductPriceChangedIntegrationEvent @event) { - var userIds = await _repository.GetUsers(); + var userIds = await _repository.GetUsersAsync(); + foreach (var id in userIds) { var basket = await _repository.GetBasketAsync(id); + await UpdatePriceInBasketItems(@event.ProductId, @event.NewPrice, @event.OldPrice, basket); } } @@ -27,6 +31,7 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API.IntegrationEvents.Even private async Task UpdatePriceInBasketItems(int productId, decimal newPrice, decimal oldPrice, CustomerBasket basket) { var itemsToUpdate = basket?.Items?.Where(x => int.Parse(x.ProductId) == productId).ToList(); + if (itemsToUpdate != null) { foreach (var item in itemsToUpdate) diff --git a/src/Services/Basket/Basket.API/IntegrationEvents/Events/OrderStartedIntegrationEvent.cs b/src/Services/Basket/Basket.API/IntegrationEvents/Events/OrderStartedIntegrationEvent.cs index 3b5726e83..a32ad0beb 100644 --- a/src/Services/Basket/Basket.API/IntegrationEvents/Events/OrderStartedIntegrationEvent.cs +++ b/src/Services/Basket/Basket.API/IntegrationEvents/Events/OrderStartedIntegrationEvent.cs @@ -1,8 +1,4 @@ using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; namespace Basket.API.IntegrationEvents.Events { diff --git a/src/Services/Basket/Basket.API/IntegrationEvents/Events/ProductPriceChangedIntegrationEvent.cs b/src/Services/Basket/Basket.API/IntegrationEvents/Events/ProductPriceChangedIntegrationEvent.cs index 87d2e9e81..6f51010be 100644 --- a/src/Services/Basket/Basket.API/IntegrationEvents/Events/ProductPriceChangedIntegrationEvent.cs +++ b/src/Services/Basket/Basket.API/IntegrationEvents/Events/ProductPriceChangedIntegrationEvent.cs @@ -1,7 +1,4 @@ using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; -using System; -using System.Collections.Generic; -using System.Text; namespace Microsoft.eShopOnContainers.Services.Basket.API.IntegrationEvents.Events { diff --git a/src/Services/Basket/Basket.API/Model/IBasketRepository.cs b/src/Services/Basket/Basket.API/Model/IBasketRepository.cs index 7f75ea342..fcdc69faa 100644 --- a/src/Services/Basket/Basket.API/Model/IBasketRepository.cs +++ b/src/Services/Basket/Basket.API/Model/IBasketRepository.cs @@ -1,6 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; +using System.Collections.Generic; using System.Threading.Tasks; namespace Microsoft.eShopOnContainers.Services.Basket.API.Model @@ -8,7 +6,7 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API.Model public interface IBasketRepository { Task GetBasketAsync(string customerId); - Task> GetUsers(); + Task> GetUsersAsync(); Task UpdateBasketAsync(CustomerBasket basket); Task DeleteBasketAsync(string id); } diff --git a/src/Services/Basket/Basket.API/Model/RedisBasketRepository.cs b/src/Services/Basket/Basket.API/Model/RedisBasketRepository.cs index 59ca0da03..7bfdbaada 100644 --- a/src/Services/Basket/Basket.API/Model/RedisBasketRepository.cs +++ b/src/Services/Basket/Basket.API/Model/RedisBasketRepository.cs @@ -1,12 +1,11 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using StackExchange.Redis; +using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Newtonsoft.Json; -using Microsoft.Extensions.Logging; +using StackExchange.Redis; +using System.Collections.Generic; +using System.Linq; using System.Net; +using System.Threading.Tasks; namespace Microsoft.eShopOnContainers.Services.Basket.API.Model { @@ -31,7 +30,7 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API.Model return await database.KeyDeleteAsync(id.ToString()); } - public async Task> GetUsers() + public async Task> GetUsersAsync() { var server = await GetServer(); @@ -63,11 +62,12 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API.Model var created = await database.StringSetAsync(basket.BuyerId, JsonConvert.SerializeObject(basket)); if (!created) { - _logger.LogInformation("Problem persisting the item"); + _logger.LogInformation("Problem occur persisting the item."); return null; } - _logger.LogInformation("basket item persisted succesfully"); + _logger.LogInformation("Basket item persisted succesfully."); + return await GetBasketAsync(basket.BuyerId); } @@ -96,7 +96,9 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API.Model { //TODO: Need to make this more robust. Also want to understand why the static connection method cannot accept dns names. var ips = await Dns.GetHostAddressesAsync(_settings.ConnectionString); + _logger.LogInformation($"Connecting to database {_settings.ConnectionString} at IP {ips.First().ToString()}"); + _redis = await ConnectionMultiplexer.ConnectAsync(ips.First().ToString()); } diff --git a/src/Services/Basket/Basket.API/Startup.cs b/src/Services/Basket/Basket.API/Startup.cs index 11a6ebc97..f24818ab6 100644 --- a/src/Services/Basket/Basket.API/Startup.cs +++ b/src/Services/Basket/Basket.API/Startup.cs @@ -1,24 +1,23 @@ -using System.Linq; +using Basket.API.Infrastructure.Filters; +using Basket.API.IntegrationEvents.EventHandling; +using Basket.API.IntegrationEvents.Events; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; +using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; +using Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ; +using Microsoft.eShopOnContainers.Services.Basket.API.Auth.Server; +using Microsoft.eShopOnContainers.Services.Basket.API.IntegrationEvents.EventHandling; +using Microsoft.eShopOnContainers.Services.Basket.API.IntegrationEvents.Events; +using Microsoft.eShopOnContainers.Services.Basket.API.Model; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.HealthChecks; using Microsoft.Extensions.Logging; -using Microsoft.eShopOnContainers.Services.Basket.API.Model; -using StackExchange.Redis; using Microsoft.Extensions.Options; +using StackExchange.Redis; +using System.Linq; using System.Net; -using Microsoft.eShopOnContainers.Services.Basket.API.Auth.Server; -using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; -using Microsoft.eShopOnContainers.Services.Basket.API.IntegrationEvents.Events; -using Microsoft.eShopOnContainers.Services.Basket.API.IntegrationEvents.EventHandling; -using Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ; -using System; -using Microsoft.Extensions.HealthChecks; using System.Threading.Tasks; -using Basket.API.Infrastructure.Filters; -using Basket.API.IntegrationEvents.Events; -using Basket.API.IntegrationEvents.EventHandling; namespace Microsoft.eShopOnContainers.Services.Basket.API { @@ -59,17 +58,24 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API //and then creating the connection it seems reasonable to move //that cost to startup instead of having the first request pay the //penalty. - services.AddSingleton((sp) => { - var config = sp.GetRequiredService>().Value; - var ips = Dns.GetHostAddressesAsync(config.ConnectionString).Result; + services.AddSingleton(sp => { + var settings = sp.GetRequiredService>().Value; + var ips = Dns.GetHostAddressesAsync(settings.ConnectionString).Result; + return ConnectionMultiplexer.Connect(ips.First().ToString()); }); + services.AddSingleton(sp => + { + var settings = sp.GetRequiredService>().Value; + + return new EventBusRabbitMQ(settings.EventBusConnection); + }); + services.AddSwaggerGen(); - //var sch = new IdentitySecurityScheme(); + services.ConfigureSwaggerGen(options => { - //options.AddSecurityDefinition("IdentityServer", sch); options.OperationFilter(); options.DescribeAllEnumsAsStrings(); options.SingleApiVersion(new Swashbuckle.Swagger.Model.Info() @@ -95,10 +101,7 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API services.AddTransient, ProductPriceChangedIntegrationEventHandler>(); services.AddTransient, OrderStartedIntegrationEventHandler>(); - var serviceProvider = services.BuildServiceProvider(); - var configuration = serviceProvider.GetRequiredService>().Value; - services.AddSingleton(provider => new EventBusRabbitMQ(configuration.EventBusConnection)); - + } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. @@ -119,11 +122,7 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API app.UseSwagger() .UseSwaggerUi(); - var catalogPriceHandler = app.ApplicationServices.GetService>(); - var orderStartedHandler = app.ApplicationServices.GetService>(); - var eventBus = app.ApplicationServices.GetRequiredService(); - eventBus.Subscribe(catalogPriceHandler); - eventBus.Subscribe(orderStartedHandler); + ConfigureEventBus(app); } @@ -136,6 +135,21 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API ScopeName = "basket", RequireHttpsMetadata = false }); - } + } + + protected virtual void ConfigureEventBus(IApplicationBuilder app) + { + var catalogPriceHandler = app.ApplicationServices + .GetService>(); + + var orderStartedHandler = app.ApplicationServices + .GetService>(); + + var eventBus = app.ApplicationServices + .GetRequiredService(); + + eventBus.Subscribe(catalogPriceHandler); + eventBus.Subscribe(orderStartedHandler); + } } } diff --git a/src/Services/Catalog/Catalog.API/CatalogSettings.cs b/src/Services/Catalog/Catalog.API/CatalogSettings.cs new file mode 100644 index 000000000..af6e0ab13 --- /dev/null +++ b/src/Services/Catalog/Catalog.API/CatalogSettings.cs @@ -0,0 +1,9 @@ +namespace Microsoft.eShopOnContainers.Services.Catalog.API +{ + public class CatalogSettings + { + public string ExternalCatalogBaseUrl {get;set;} + + public string EventBusConnection { get; set; } + } +} diff --git a/src/Services/Catalog/Catalog.API/Controllers/CatalogController.cs b/src/Services/Catalog/Catalog.API/Controllers/CatalogController.cs index 83a2de02d..bd5966a9c 100644 --- a/src/Services/Catalog/Catalog.API/Controllers/CatalogController.cs +++ b/src/Services/Catalog/Catalog.API/Controllers/CatalogController.cs @@ -1,9 +1,6 @@ -using Microsoft.AspNetCore.Mvc; +using Catalog.API.IntegrationEvents; +using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Storage; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; -using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF.Services; using Microsoft.eShopOnContainers.Services.Catalog.API.Infrastructure; using Microsoft.eShopOnContainers.Services.Catalog.API.IntegrationEvents.Events; using Microsoft.eShopOnContainers.Services.Catalog.API.Model; @@ -11,12 +8,8 @@ using Microsoft.eShopOnContainers.Services.Catalog.API.ViewModel; using Microsoft.Extensions.Options; using System; using System.Collections.Generic; -using System.Data.Common; using System.Linq; using System.Threading.Tasks; -using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; -using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF.Utilities; -using Catalog.API.IntegrationEvents; namespace Microsoft.eShopOnContainers.Services.Catalog.API.Controllers { @@ -24,16 +17,16 @@ namespace Microsoft.eShopOnContainers.Services.Catalog.API.Controllers public class CatalogController : ControllerBase { private readonly CatalogContext _catalogContext; - private readonly IOptionsSnapshot _settings; + private readonly CatalogSettings _settings; private readonly ICatalogIntegrationEventService _catalogIntegrationEventService; - public CatalogController(CatalogContext Context, IOptionsSnapshot settings, ICatalogIntegrationEventService catalogIntegrationEventService) + public CatalogController(CatalogContext context, IOptionsSnapshot settings, ICatalogIntegrationEventService catalogIntegrationEventService) { - _catalogContext = Context; - _catalogIntegrationEventService = catalogIntegrationEventService; - _settings = settings; + _catalogContext = context ?? throw new ArgumentNullException(nameof(context)); + _catalogIntegrationEventService = catalogIntegrationEventService ?? throw new ArgumentNullException(nameof(catalogIntegrationEventService)); - ((DbContext)Context).ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking; + _settings = settings.Value; + ((DbContext)context).ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking; } // GET api/v1/[controller]/items[?pageSize=3&pageIndex=10] @@ -51,7 +44,7 @@ namespace Microsoft.eShopOnContainers.Services.Catalog.API.Controllers .Take(pageSize) .ToListAsync(); - itemsOnPage = ComposePicUri(itemsOnPage); + itemsOnPage = ChangeUriPlaceholder(itemsOnPage); var model = new PaginatedItemsViewModel( pageIndex, pageSize, totalItems, itemsOnPage); @@ -75,7 +68,7 @@ namespace Microsoft.eShopOnContainers.Services.Catalog.API.Controllers .Take(pageSize) .ToListAsync(); - itemsOnPage = ComposePicUri(itemsOnPage); + itemsOnPage = ChangeUriPlaceholder(itemsOnPage); var model = new PaginatedItemsViewModel( pageIndex, pageSize, totalItems, itemsOnPage); @@ -108,7 +101,7 @@ namespace Microsoft.eShopOnContainers.Services.Catalog.API.Controllers .Take(pageSize) .ToListAsync(); - itemsOnPage = ComposePicUri(itemsOnPage); + itemsOnPage = ChangeUriPlaceholder(itemsOnPage); var model = new PaginatedItemsViewModel( pageIndex, pageSize, totalItems, itemsOnPage); @@ -143,10 +136,17 @@ namespace Microsoft.eShopOnContainers.Services.Catalog.API.Controllers [HttpPost] public async Task UpdateProduct([FromBody]CatalogItem productToUpdate) { - var catalogItem = await _catalogContext.CatalogItems.SingleOrDefaultAsync(i => i.Id == productToUpdate.Id); - if (catalogItem == null) return NotFound(); - var raiseProductPriceChangedEvent = catalogItem.Price != productToUpdate.Price; + var catalogItem = await _catalogContext.CatalogItems + .SingleOrDefaultAsync(i => i.Id == productToUpdate.Id); + + if (catalogItem == null) + { + return NotFound(); + } + var oldPrice = catalogItem.Price; + var raiseProductPriceChangedEvent = oldPrice != productToUpdate.Price; + // Update current product catalogItem = productToUpdate; @@ -205,13 +205,16 @@ namespace Microsoft.eShopOnContainers.Services.Catalog.API.Controllers } _catalogContext.CatalogItems.Remove(product); + await _catalogContext.SaveChangesAsync(); return Ok(); } - private List ComposePicUri(List items) { - var baseUri = _settings.Value.ExternalCatalogBaseUrl; + private List ChangeUriPlaceholder(List items) + { + var baseUri = _settings.ExternalCatalogBaseUrl; + items.ForEach(x => { x.PictureUri = x.PictureUri.Replace("http://externalcatalogbaseurltobereplaced", baseUri); diff --git a/src/Services/Catalog/Catalog.API/Controllers/HomeController.cs b/src/Services/Catalog/Catalog.API/Controllers/HomeController.cs index e6ade8cc5..9401b56f9 100644 --- a/src/Services/Catalog/Catalog.API/Controllers/HomeController.cs +++ b/src/Services/Catalog/Catalog.API/Controllers/HomeController.cs @@ -1,8 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc; // For more information on enabling MVC for empty projects, visit http://go.microsoft.com/fwlink/?LinkID=397860 diff --git a/src/Services/Catalog/Catalog.API/Controllers/PicController.cs b/src/Services/Catalog/Catalog.API/Controllers/PicController.cs index fa6b4ec94..8d8aaf9f2 100644 --- a/src/Services/Catalog/Catalog.API/Controllers/PicController.cs +++ b/src/Services/Catalog/Catalog.API/Controllers/PicController.cs @@ -1,10 +1,6 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; +using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Mvc; using System.IO; -using Microsoft.AspNetCore.Hosting; // For more information on enabling MVC for empty projects, visit http://go.microsoft.com/fwlink/?LinkID=397860 @@ -25,8 +21,10 @@ namespace Microsoft.eShopOnContainers.Services.Catalog.API.Controllers { var webRoot = _env.WebRootPath; var path = Path.Combine(webRoot, id + ".png"); - Byte[] b = System.IO.File.ReadAllBytes(path); - return File(b, "image/png"); + + var buffer = System.IO.File.ReadAllBytes(path); + + return File(buffer, "image/png"); } } } diff --git a/src/Services/Catalog/Catalog.API/Infrastructure/ActionResults/InternalServerErrorObjectResult.cs b/src/Services/Catalog/Catalog.API/Infrastructure/ActionResults/InternalServerErrorObjectResult.cs index 3ac3d0f78..a6138b476 100644 --- a/src/Services/Catalog/Catalog.API/Infrastructure/ActionResults/InternalServerErrorObjectResult.cs +++ b/src/Services/Catalog/Catalog.API/Infrastructure/ActionResults/InternalServerErrorObjectResult.cs @@ -1,9 +1,5 @@ using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; namespace Catalog.API.Infrastructure.ActionResults { diff --git a/src/Services/Catalog/Catalog.API/Infrastructure/Exceptions/CatalogDomainException.cs b/src/Services/Catalog/Catalog.API/Infrastructure/Exceptions/CatalogDomainException.cs index 0b27131cf..45295994e 100644 --- a/src/Services/Catalog/Catalog.API/Infrastructure/Exceptions/CatalogDomainException.cs +++ b/src/Services/Catalog/Catalog.API/Infrastructure/Exceptions/CatalogDomainException.cs @@ -1,7 +1,4 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; namespace Catalog.API.Infrastructure.Exceptions { diff --git a/src/Services/Catalog/Catalog.API/IntegrationEvents/CatalogIntegrationEventService.cs b/src/Services/Catalog/Catalog.API/IntegrationEvents/CatalogIntegrationEventService.cs index e6e48c54b..1b82251e3 100644 --- a/src/Services/Catalog/Catalog.API/IntegrationEvents/CatalogIntegrationEventService.cs +++ b/src/Services/Catalog/Catalog.API/IntegrationEvents/CatalogIntegrationEventService.cs @@ -30,6 +30,7 @@ namespace Catalog.API.IntegrationEvents public async Task PublishThroughEventBusAsync(IntegrationEvent evt) { _eventBus.Publish(evt); + await _eventLogService.MarkEventAsPublishedAsync(evt); } diff --git a/src/Services/Catalog/Catalog.API/IntegrationEvents/ICatalogIntegrationEventService.cs b/src/Services/Catalog/Catalog.API/IntegrationEvents/ICatalogIntegrationEventService.cs index bb958eeaa..4d87e8e94 100644 --- a/src/Services/Catalog/Catalog.API/IntegrationEvents/ICatalogIntegrationEventService.cs +++ b/src/Services/Catalog/Catalog.API/IntegrationEvents/ICatalogIntegrationEventService.cs @@ -1,7 +1,4 @@ using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; -using System; -using System.Collections.Generic; -using System.Linq; using System.Threading.Tasks; namespace Catalog.API.IntegrationEvents diff --git a/src/Services/Catalog/Catalog.API/Model/CatalogBrand.cs b/src/Services/Catalog/Catalog.API/Model/CatalogBrand.cs index eb1fabf7d..84d72899e 100644 --- a/src/Services/Catalog/Catalog.API/Model/CatalogBrand.cs +++ b/src/Services/Catalog/Catalog.API/Model/CatalogBrand.cs @@ -1,11 +1,5 @@ namespace Microsoft.eShopOnContainers.Services.Catalog.API.Model { - using System; - using System.Collections.Generic; - using System.Linq; - using System.Threading.Tasks; - - public class CatalogBrand { public int Id { get; set; } diff --git a/src/Services/Catalog/Catalog.API/Model/CatalogType.cs b/src/Services/Catalog/Catalog.API/Model/CatalogType.cs index ac71914ff..0bc640dee 100644 --- a/src/Services/Catalog/Catalog.API/Model/CatalogType.cs +++ b/src/Services/Catalog/Catalog.API/Model/CatalogType.cs @@ -1,10 +1,5 @@ namespace Microsoft.eShopOnContainers.Services.Catalog.API.Model { - using System; - using System.Collections.Generic; - using System.Linq; - using System.Threading.Tasks; - public class CatalogType { public int Id { get; set; } diff --git a/src/Services/Catalog/Catalog.API/Startup.cs b/src/Services/Catalog/Catalog.API/Startup.cs index f3f0735b2..e3f671652 100644 --- a/src/Services/Catalog/Catalog.API/Startup.cs +++ b/src/Services/Catalog/Catalog.API/Startup.cs @@ -1,6 +1,7 @@ namespace Microsoft.eShopOnContainers.Services.Catalog.API { using global::Catalog.API.Infrastructure.Filters; + using global::Catalog.API.IntegrationEvents; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.EntityFrameworkCore; @@ -16,12 +17,9 @@ using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using System; - using System.Data.SqlClient; - using System.IO; using System.Data.Common; + using System.Data.SqlClient; using System.Reflection; - using global::Catalog.API.IntegrationEvents; - using System.Threading.Tasks; public class Startup { @@ -47,7 +45,7 @@ public void ConfigureServices(IServiceCollection services) { // Add framework services. - + services.AddHealthChecks(checks => { checks.AddSqlCheck("CatalogDb", Configuration["ConnectionString"]); @@ -62,18 +60,19 @@ { options.UseSqlServer(Configuration["ConnectionString"], sqlServerOptionsAction: sqlOptions => - { + { sqlOptions.MigrationsAssembly(typeof(Startup).GetTypeInfo().Assembly.GetName().Name); //Configuring Connection Resiliency: https://docs.microsoft.com/en-us/ef/core/miscellaneous/connection-resiliency sqlOptions.EnableRetryOnFailure(maxRetryCount: 5, maxRetryDelay: TimeSpan.FromSeconds(30), errorNumbersToAdd: null); }); + // Changing default behavior when client evaluation occurs to throw. // Default in EF Core would be to log a warning when client evaluation is performed. options.ConfigureWarnings(warnings => warnings.Throw(RelationalEventId.QueryClientEvaluationWarning)); //Check Client vs. Server evaluation: https://docs.microsoft.com/en-us/ef/core/querying/client-eval }); - services.Configure(Configuration); + services.Configure(Configuration); // Add framework services. services.AddSwaggerGen(); @@ -99,11 +98,18 @@ }); services.AddTransient>( - sp => (DbConnection c) => new IntegrationEventLogService(c)); - var serviceProvider = services.BuildServiceProvider(); - var configuration = serviceProvider.GetRequiredService>().Value; + sp => (DbConnection c) => new IntegrationEventLogService(c)); + services.AddTransient(); - services.AddSingleton(new EventBusRabbitMQ(configuration.EventBusConnection)); + + + var serviceProvider = services.BuildServiceProvider(); + + services.AddSingleton(sp => + { + var settings = serviceProvider.GetRequiredService>().Value; + return new EventBusRabbitMQ(settings.EventBusConnection); + }); } public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) @@ -124,25 +130,28 @@ .ApplicationServices.GetService(typeof(CatalogContext)); WaitForSqlAvailability(context, loggerFactory); + //Seed Data CatalogContextSeed.SeedAsync(app, loggerFactory) - .Wait(); + .Wait(); var integrationEventLogContext = new IntegrationEventLogContext( new DbContextOptionsBuilder() .UseSqlServer(Configuration["ConnectionString"], b => b.MigrationsAssembly("Catalog.API")) .Options); + integrationEventLogContext.Database.Migrate(); } private void WaitForSqlAvailability(CatalogContext ctx, ILoggerFactory loggerFactory, int? retry = 0) { - int retryForAvailability = retry.Value; + int retryForAvailability = retry.Value; + try { ctx.Database.OpenConnection(); } - catch(SqlException ex) + catch (SqlException ex) { if (retryForAvailability < 10) { @@ -152,11 +161,10 @@ WaitForSqlAvailability(ctx, loggerFactory, retryForAvailability); } } - finally { - ctx.Database.CloseConnection(); + finally + { + ctx.Database.CloseConnection(); } - - } } } diff --git a/src/Services/Catalog/Catalog.API/settings.cs b/src/Services/Catalog/Catalog.API/settings.cs deleted file mode 100644 index a6e959552..000000000 --- a/src/Services/Catalog/Catalog.API/settings.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; - -namespace Microsoft.eShopOnContainers.Services.Catalog.API -{ - // TODO: Rename CatalogSettings for consistency? - public class Settings - { - public string ExternalCatalogBaseUrl {get;set;} - public string EventBusConnection { get; set; } - } -} diff --git a/src/Services/Ordering/Ordering.API/Application/Commands/IdentifierCommandHandler.cs b/src/Services/Ordering/Ordering.API/Application/Commands/IdentifierCommandHandler.cs index de7dc4fea..529c1aa05 100644 --- a/src/Services/Ordering/Ordering.API/Application/Commands/IdentifierCommandHandler.cs +++ b/src/Services/Ordering/Ordering.API/Application/Commands/IdentifierCommandHandler.cs @@ -45,9 +45,11 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands return CreateResultForDuplicateRequest(); } else - { - var result = await _mediator.SendAsync(message.Command); + { await _requestManager.CreateRequestForCommandAsync(message.Id); + + var result = await _mediator.SendAsync(message.Command); + return result; } } diff --git a/src/Services/Ordering/Ordering.API/Application/Queries/IOrderQueries.cs b/src/Services/Ordering/Ordering.API/Application/Queries/IOrderQueries.cs index f12a9e418..8d78524ea 100644 --- a/src/Services/Ordering/Ordering.API/Application/Queries/IOrderQueries.cs +++ b/src/Services/Ordering/Ordering.API/Application/Queries/IOrderQueries.cs @@ -4,10 +4,10 @@ public interface IOrderQueries { - Task GetOrder(int id); + Task GetOrderAsync(int id); - Task GetOrders(); + Task GetOrdersAsync(); - Task GetCardTypes(); + Task GetCardTypesAsync(); } } diff --git a/src/Services/Ordering/Ordering.API/Application/Queries/OrderQueries.cs b/src/Services/Ordering/Ordering.API/Application/Queries/OrderQueries.cs index f10f76273..9d909e254 100644 --- a/src/Services/Ordering/Ordering.API/Application/Queries/OrderQueries.cs +++ b/src/Services/Ordering/Ordering.API/Application/Queries/OrderQueries.cs @@ -19,7 +19,7 @@ } - public async Task GetOrder(int id) + public async Task GetOrderAsync(int id) { using (var connection = new SqlConnection(_connectionString)) { @@ -44,7 +44,7 @@ } } - public async Task GetOrders() + public async Task GetOrdersAsync() { using (var connection = new SqlConnection(_connectionString)) { @@ -58,7 +58,7 @@ } } - public async Task GetCardTypes() + public async Task GetCardTypesAsync() { using (var connection = new SqlConnection(_connectionString)) { diff --git a/src/Services/Ordering/Ordering.API/Application/Validations/CreateOrderCommandValidator.cs b/src/Services/Ordering/Ordering.API/Application/Validations/CreateOrderCommandValidator.cs index 449f95df5..e6bbdd4d9 100644 --- a/src/Services/Ordering/Ordering.API/Application/Validations/CreateOrderCommandValidator.cs +++ b/src/Services/Ordering/Ordering.API/Application/Validations/CreateOrderCommandValidator.cs @@ -1,10 +1,8 @@ using FluentValidation; -using MediatR; using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands; using System; using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; using static Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands.CreateOrderCommand; namespace Ordering.API.Application.Validations @@ -13,17 +11,17 @@ namespace Ordering.API.Application.Validations { public CreateOrderCommandValidator() { - RuleFor(order => order.City).NotEmpty(); - RuleFor(order => order.Street).NotEmpty(); - RuleFor(order => order.State).NotEmpty(); - RuleFor(order => order.Country).NotEmpty(); - RuleFor(order => order.ZipCode).NotEmpty(); - RuleFor(order => order.CardNumber).NotEmpty().Length(12, 19); - RuleFor(order => order.CardHolderName).NotEmpty(); - RuleFor(order => order.CardExpiration).NotEmpty().Must(BeValidExpirationDate).WithMessage("Please specify a valid card expiration date"); - RuleFor(order => order.CardSecurityNumber).NotEmpty().Length(3); - RuleFor(order => order.CardTypeId).NotEmpty(); - RuleFor(order => order.OrderItems).Must(ContainOrderItems).WithMessage("No order items found"); + RuleFor(command => command.City).NotEmpty(); + RuleFor(command => command.Street).NotEmpty(); + RuleFor(command => command.State).NotEmpty(); + RuleFor(command => command.Country).NotEmpty(); + RuleFor(command => command.ZipCode).NotEmpty(); + RuleFor(command => command.CardNumber).NotEmpty().Length(12, 19); + RuleFor(command => command.CardHolderName).NotEmpty(); + RuleFor(command => command.CardExpiration).NotEmpty().Must(BeValidExpirationDate).WithMessage("Please specify a valid card expiration date"); + RuleFor(command => command.CardSecurityNumber).NotEmpty().Length(3); + RuleFor(command => command.CardTypeId).NotEmpty(); + RuleFor(command => command.OrderItems).Must(ContainOrderItems).WithMessage("No order items found"); } private bool BeValidExpirationDate(DateTime dateTime) diff --git a/src/Services/Ordering/Ordering.API/Application/Validations/IdentifierCommandValidator.cs b/src/Services/Ordering/Ordering.API/Application/Validations/IdentifierCommandValidator.cs index 44b374ee6..e1482287f 100644 --- a/src/Services/Ordering/Ordering.API/Application/Validations/IdentifierCommandValidator.cs +++ b/src/Services/Ordering/Ordering.API/Application/Validations/IdentifierCommandValidator.cs @@ -1,9 +1,5 @@ using FluentValidation; using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; namespace Ordering.API.Application.Validations { @@ -11,7 +7,7 @@ namespace Ordering.API.Application.Validations { public IdentifierCommandValidator() { - RuleFor(customer => customer.Id).NotEmpty(); + RuleFor(command => command.Id).NotEmpty(); } } } diff --git a/src/Services/Ordering/Ordering.API/Controllers/OrdersController.cs b/src/Services/Ordering/Ordering.API/Controllers/OrdersController.cs index 4121e3214..d9a3752ed 100644 --- a/src/Services/Ordering/Ordering.API/Controllers/OrdersController.cs +++ b/src/Services/Ordering/Ordering.API/Controllers/OrdersController.cs @@ -57,7 +57,9 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.API.Controllers { try { - var order = await _orderQueries.GetOrder(orderId); + var order = await _orderQueries + .GetOrderAsync(orderId); + return Ok(order); } catch (KeyNotFoundException) @@ -70,7 +72,8 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.API.Controllers [HttpGet] public async Task GetOrders() { - var orders = await _orderQueries.GetOrders(); + var orders = await _orderQueries + .GetOrdersAsync(); return Ok(orders); } @@ -79,7 +82,8 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.API.Controllers [HttpGet] public async Task GetCardTypes() { - var cardTypes = await _orderQueries.GetCardTypes(); + var cardTypes = await _orderQueries + .GetCardTypesAsync(); return Ok(cardTypes); } diff --git a/src/Services/Ordering/Ordering.API/Startup.cs b/src/Services/Ordering/Ordering.API/Startup.cs index 6b120eb78..ae5c4c3ff 100644 --- a/src/Services/Ordering/Ordering.API/Startup.cs +++ b/src/Services/Ordering/Ordering.API/Startup.cs @@ -65,14 +65,14 @@ services.AddEntityFrameworkSqlServer() .AddDbContext(options => { - options.UseSqlServer(Configuration["ConnectionString"], - sqlServerOptionsAction: sqlOptions => - { - sqlOptions.MigrationsAssembly(typeof(Startup).GetTypeInfo().Assembly.GetName().Name); - sqlOptions.EnableRetryOnFailure(maxRetryCount: 5, maxRetryDelay: TimeSpan.FromSeconds(30), errorNumbersToAdd: null); - }); - }, - ServiceLifetime.Scoped //Showing explicitly that the DbContext is shared across the HTTP request scope (graph of objects started in the HTTP request) + options.UseSqlServer(Configuration["ConnectionString"], + sqlServerOptionsAction: sqlOptions => + { + sqlOptions.MigrationsAssembly(typeof(Startup).GetTypeInfo().Assembly.GetName().Name); + sqlOptions.EnableRetryOnFailure(maxRetryCount: 5, maxRetryDelay: TimeSpan.FromSeconds(30), errorNumbersToAdd: null); + }); + }, + ServiceLifetime.Scoped //Showing explicitly that the DbContext is shared across the HTTP request scope (graph of objects started in the HTTP request) ); services.AddSwaggerGen(); diff --git a/src/Services/Ordering/Ordering.Domain/AggregatesModel/BuyerAggregate/Buyer.cs b/src/Services/Ordering/Ordering.Domain/AggregatesModel/BuyerAggregate/Buyer.cs index 84040d8a1..c806cebeb 100644 --- a/src/Services/Ordering/Ordering.Domain/AggregatesModel/BuyerAggregate/Buyer.cs +++ b/src/Services/Ordering/Ordering.Domain/AggregatesModel/BuyerAggregate/Buyer.cs @@ -16,6 +16,7 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.B public IEnumerable PaymentMethods => _paymentMethods.AsReadOnly(); protected Buyer() { + _paymentMethods = new List(); } @@ -34,6 +35,7 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.B if (existingPayment != null) { AddDomainEvent(new BuyerAndPaymentMethodVerifiedDomainEvent(this, existingPayment, orderId)); + return existingPayment; } else @@ -41,7 +43,9 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.B var payment = new PaymentMethod(cardTypeId, alias, cardNumber, securityNumber, cardHolderName, expiration); _paymentMethods.Add(payment); + AddDomainEvent(new BuyerAndPaymentMethodVerifiedDomainEvent(this, payment, orderId)); + return payment; } } diff --git a/src/Services/Ordering/Ordering.Domain/AggregatesModel/OrderAggregate/IOrderRepository.cs b/src/Services/Ordering/Ordering.Domain/AggregatesModel/OrderAggregate/IOrderRepository.cs index a35188d8f..d7346ee4f 100644 --- a/src/Services/Ordering/Ordering.Domain/AggregatesModel/OrderAggregate/IOrderRepository.cs +++ b/src/Services/Ordering/Ordering.Domain/AggregatesModel/OrderAggregate/IOrderRepository.cs @@ -9,9 +9,9 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.O public interface IOrderRepository : IRepository { Order Add(Order order); + + void Update(Order order); Task GetAsync(int orderId); - - void Update(Order order); } } diff --git a/src/Services/Ordering/Ordering.Domain/SeedWork/Enumeration.cs b/src/Services/Ordering/Ordering.Domain/SeedWork/Enumeration.cs index fd74ab1df..ec8dfd968 100644 --- a/src/Services/Ordering/Ordering.Domain/SeedWork/Enumeration.cs +++ b/src/Services/Ordering/Ordering.Domain/SeedWork/Enumeration.cs @@ -71,17 +71,17 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.SeedWork public static T FromValue(int value) where T : Enumeration, new() { - var matchingItem = parse(value, "value", item => item.Id == value); + var matchingItem = Parse(value, "value", item => item.Id == value); return matchingItem; } public static T FromDisplayName(string displayName) where T : Enumeration, new() { - var matchingItem = parse(displayName, "display name", item => item.Name == displayName); + var matchingItem = Parse(displayName, "display name", item => item.Name == displayName); return matchingItem; } - private static T parse(K value, string description, Func predicate) where T : Enumeration, new() + private static T Parse(K value, string description, Func predicate) where T : Enumeration, new() { var matchingItem = GetAll().FirstOrDefault(predicate); diff --git a/src/Services/Ordering/Ordering.Infrastructure/ClientRequest.cs b/src/Services/Ordering/Ordering.Infrastructure/Idempotency/ClientRequest.cs similarity index 80% rename from src/Services/Ordering/Ordering.Infrastructure/ClientRequest.cs rename to src/Services/Ordering/Ordering.Infrastructure/Idempotency/ClientRequest.cs index 47a401aab..7ca49fa41 100644 --- a/src/Services/Ordering/Ordering.Infrastructure/ClientRequest.cs +++ b/src/Services/Ordering/Ordering.Infrastructure/Idempotency/ClientRequest.cs @@ -1,8 +1,6 @@ using System; -using System.Collections.Generic; -using System.Text; -namespace Microsoft.eShopOnContainers.Services.Ordering.Infrastructure +namespace Microsoft.eShopOnContainers.Services.Ordering.Infrastructure.Idempotency { public class ClientRequest { diff --git a/src/Services/Ordering/Ordering.Infrastructure/Idempotency/IRequestManager.cs b/src/Services/Ordering/Ordering.Infrastructure/Idempotency/IRequestManager.cs index a8a02f8ca..d38c23e09 100644 --- a/src/Services/Ordering/Ordering.Infrastructure/Idempotency/IRequestManager.cs +++ b/src/Services/Ordering/Ordering.Infrastructure/Idempotency/IRequestManager.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using System.Threading.Tasks; namespace Microsoft.eShopOnContainers.Services.Ordering.Infrastructure.Idempotency @@ -8,6 +6,7 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Infrastructure.Idempoten public interface IRequestManager { Task ExistAsync(Guid id); + Task CreateRequestForCommandAsync(Guid id); } } diff --git a/src/Services/Ordering/Ordering.Infrastructure/Idempotency/RequestManager.cs b/src/Services/Ordering/Ordering.Infrastructure/Idempotency/RequestManager.cs index 0ef005161..6b6a96579 100644 --- a/src/Services/Ordering/Ordering.Infrastructure/Idempotency/RequestManager.cs +++ b/src/Services/Ordering/Ordering.Infrastructure/Idempotency/RequestManager.cs @@ -1,8 +1,5 @@ -using Microsoft.eShopOnContainers.Services.Ordering.Infrastructure; -using Ordering.Domain.Exceptions; +using Ordering.Domain.Exceptions; using System; -using System.Collections.Generic; -using System.Text; using System.Threading.Tasks; namespace Microsoft.eShopOnContainers.Services.Ordering.Infrastructure.Idempotency @@ -10,22 +7,25 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Infrastructure.Idempoten public class RequestManager : IRequestManager { private readonly OrderingContext _context; - public RequestManager(OrderingContext ctx) + + public RequestManager(OrderingContext context) { - _context = ctx; + _context = context ?? throw new ArgumentNullException(nameof(context)); } public async Task ExistAsync(Guid id) { - var request = await _context.FindAsync(id); + var request = await _context. + FindAsync(id); + return request != null; } public async Task CreateRequestForCommandAsync(Guid id) - { - + { var exists = await ExistAsync(id); + var request = exists ? throw new OrderingDomainException($"Request with {id} already exists") : new ClientRequest() @@ -36,8 +36,8 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Infrastructure.Idempoten }; _context.Add(request); + await _context.SaveChangesAsync(); } - } } diff --git a/src/Services/Ordering/Ordering.Infrastructure/MediatorExtension.cs b/src/Services/Ordering/Ordering.Infrastructure/MediatorExtension.cs index 99e94e086..9135188cf 100644 --- a/src/Services/Ordering/Ordering.Infrastructure/MediatorExtension.cs +++ b/src/Services/Ordering/Ordering.Infrastructure/MediatorExtension.cs @@ -6,13 +6,20 @@ using System.Threading.Tasks; namespace Ordering.Infrastructure { - public static class MediatorExtension + static class MediatorExtension { public static async Task DispatchDomainEventsAsync(this IMediator mediator, OrderingContext ctx) { - var domainEntities = ctx.ChangeTracker.Entries().Where(x => x.Entity.DomainEvents != null && x.Entity.DomainEvents.Any()); - var domainEvents = domainEntities.SelectMany(x => x.Entity.DomainEvents).ToList(); - domainEntities.ToList().ForEach(entity => entity.Entity.DomainEvents.Clear()); + var domainEntities = ctx.ChangeTracker + .Entries() + .Where(x => x.Entity.DomainEvents != null && x.Entity.DomainEvents.Any()); + + var domainEvents = domainEntities + .SelectMany(x => x.Entity.DomainEvents) + .ToList(); + + domainEntities.ToList() + .ForEach(entity => entity.Entity.DomainEvents.Clear()); var tasks = domainEvents .Select(async (domainEvent) => { diff --git a/src/Services/Ordering/Ordering.Infrastructure/OrderingContext.cs b/src/Services/Ordering/Ordering.Infrastructure/OrderingContext.cs index 70bb8a51a..5b95ee23c 100644 --- a/src/Services/Ordering/Ordering.Infrastructure/OrderingContext.cs +++ b/src/Services/Ordering/Ordering.Infrastructure/OrderingContext.cs @@ -5,6 +5,7 @@ using Microsoft.EntityFrameworkCore.Metadata.Builders; using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.BuyerAggregate; using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate; using Microsoft.eShopOnContainers.Services.Ordering.Domain.Seedwork; +using Microsoft.eShopOnContainers.Services.Ordering.Infrastructure.Idempotency; using Ordering.Infrastructure; using System; using System.Threading; @@ -34,7 +35,7 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Infrastructure public OrderingContext(DbContextOptions options, IMediator mediator) : base(options) { - _mediator = mediator; + _mediator = mediator ?? throw new ArgumentNullException(nameof(mediator)); } protected override void OnModelCreating(ModelBuilder modelBuilder) diff --git a/test/Services/UnitTest/Ordering/Application/OrdersWebApiTest.cs b/test/Services/UnitTest/Ordering/Application/OrdersWebApiTest.cs index e81840bb3..8c7659862 100644 --- a/test/Services/UnitTest/Ordering/Application/OrdersWebApiTest.cs +++ b/test/Services/UnitTest/Ordering/Application/OrdersWebApiTest.cs @@ -60,7 +60,7 @@ namespace UnitTest.Ordering.Application { //Arrange var fakeDynamicResult = new Object(); - _orderQueriesMock.Setup(x => x.GetOrders()) + _orderQueriesMock.Setup(x => x.GetOrdersAsync()) .Returns(Task.FromResult(fakeDynamicResult)); //Act @@ -77,7 +77,7 @@ namespace UnitTest.Ordering.Application //Arrange var fakeOrderId = 123; var fakeDynamicResult = new Object(); - _orderQueriesMock.Setup(x => x.GetOrder(It.IsAny())) + _orderQueriesMock.Setup(x => x.GetOrderAsync(It.IsAny())) .Returns(Task.FromResult(fakeDynamicResult)); //Act @@ -93,7 +93,7 @@ namespace UnitTest.Ordering.Application { //Arrange var fakeDynamicResult = new Object(); - _orderQueriesMock.Setup(x => x.GetCardTypes()) + _orderQueriesMock.Setup(x => x.GetCardTypesAsync()) .Returns(Task.FromResult(fakeDynamicResult)); //Act From 7b779f001550c73099729486118556f216d6b75f Mon Sep 17 00:00:00 2001 From: Unai Zorrilla Castro Date: Mon, 17 Apr 2017 15:00:53 +0200 Subject: [PATCH 3/3] Pending review files --- .../EventBus/EventBus/Abstractions/IEventBus.cs | 3 --- .../EventBus/Abstractions/IIntegrationEventHandler.cs | 3 --- .../EventBus/EventBus/Events/IntegrationEvent.cs | 2 -- .../EventBus/EventBusRabbitMQ/EventBusRabbitMQ.cs | 5 +++-- 4 files changed, 3 insertions(+), 10 deletions(-) diff --git a/src/BuildingBlocks/EventBus/EventBus/Abstractions/IEventBus.cs b/src/BuildingBlocks/EventBus/EventBus/Abstractions/IEventBus.cs index af6ee1aa7..63f9f1b99 100644 --- a/src/BuildingBlocks/EventBus/EventBus/Abstractions/IEventBus.cs +++ b/src/BuildingBlocks/EventBus/EventBus/Abstractions/IEventBus.cs @@ -1,7 +1,4 @@ using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; -using System; -using System.Collections.Generic; -using System.Text; namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions { diff --git a/src/BuildingBlocks/EventBus/EventBus/Abstractions/IIntegrationEventHandler.cs b/src/BuildingBlocks/EventBus/EventBus/Abstractions/IIntegrationEventHandler.cs index d755bc066..828aed26a 100644 --- a/src/BuildingBlocks/EventBus/EventBus/Abstractions/IIntegrationEventHandler.cs +++ b/src/BuildingBlocks/EventBus/EventBus/Abstractions/IIntegrationEventHandler.cs @@ -1,7 +1,4 @@ using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; -using System; -using System.Collections.Generic; -using System.Text; using System.Threading.Tasks; namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions diff --git a/src/BuildingBlocks/EventBus/EventBus/Events/IntegrationEvent.cs b/src/BuildingBlocks/EventBus/EventBus/Events/IntegrationEvent.cs index c9e60a0cf..e01a7aaa8 100644 --- a/src/BuildingBlocks/EventBus/EventBus/Events/IntegrationEvent.cs +++ b/src/BuildingBlocks/EventBus/EventBus/Events/IntegrationEvent.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events { diff --git a/src/BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.cs b/src/BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.cs index 3388875ab..903601378 100644 --- a/src/BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.cs +++ b/src/BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.cs @@ -5,7 +5,6 @@ using Newtonsoft.Json; using RabbitMQ.Client; using RabbitMQ.Client.Events; using System; -using System.Collections; using System.Collections.Generic; using System.Linq; using System.Reflection; @@ -35,7 +34,9 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ public void Publish(IntegrationEvent @event) { - var eventName = @event.GetType().Name; + var eventName = @event.GetType() + .Name; + var factory = new ConnectionFactory() { HostName = _connectionString }; using (var connection = factory.CreateConnection()) using (var channel = connection.CreateModel())