diff --git a/eShopOnContainers-ServicesAndWebApps.sln b/eShopOnContainers-ServicesAndWebApps.sln index cc63417a3..e4ddff1c2 100644 --- a/eShopOnContainers-ServicesAndWebApps.sln +++ b/eShopOnContainers-ServicesAndWebApps.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 -VisualStudioVersion = 15.0.27004.2002 +VisualStudioVersion = 15.0.27004.2009 MinimumVisualStudioVersion = 10.0.40219.1 Project("{E53339B2-1760-4266-BCC7-CA923CBCF16C}") = "docker-compose", "docker-compose.dcproj", "{FEA0C318-FFED-4D39-8781-265718CA43DD}" EndProject @@ -83,10 +83,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Location", "Location", "{41 EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Locations.API", "src\Services\Location\Locations.API\Locations.API.csproj", "{E7581357-FC34-474C-B8F5-307EE3CE05EF}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "DataProtection", "DataProtection", "{88B22DBB-AA8F-4290-A454-2C109352C345}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DataProtection", "src\BuildingBlocks\DataProtection\DataProtection\DataProtection.csproj", "{23A33F9B-7672-426D-ACF9-FF8436ADC81A}" -EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Marketing", "Marketing", "{A5260DE0-1FDD-467E-9CC1-A028AB081CEE}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Marketing.API", "src\Services\Marketing\Marketing.API\Marketing.API.csproj", "{DF395F85-B010-465D-857A-7EBCC512C0C2}" @@ -1075,54 +1071,6 @@ Global {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Release|x64.Build.0 = Release|Any CPU {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Release|x86.ActiveCfg = Release|Any CPU {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Release|x86.Build.0 = Release|Any CPU - {23A33F9B-7672-426D-ACF9-FF8436ADC81A}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU - {23A33F9B-7672-426D-ACF9-FF8436ADC81A}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU - {23A33F9B-7672-426D-ACF9-FF8436ADC81A}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU - {23A33F9B-7672-426D-ACF9-FF8436ADC81A}.Ad-Hoc|ARM.Build.0 = Debug|Any CPU - {23A33F9B-7672-426D-ACF9-FF8436ADC81A}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU - {23A33F9B-7672-426D-ACF9-FF8436ADC81A}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU - {23A33F9B-7672-426D-ACF9-FF8436ADC81A}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU - {23A33F9B-7672-426D-ACF9-FF8436ADC81A}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU - {23A33F9B-7672-426D-ACF9-FF8436ADC81A}.Ad-Hoc|x64.ActiveCfg = Debug|Any CPU - {23A33F9B-7672-426D-ACF9-FF8436ADC81A}.Ad-Hoc|x64.Build.0 = Debug|Any CPU - {23A33F9B-7672-426D-ACF9-FF8436ADC81A}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU - {23A33F9B-7672-426D-ACF9-FF8436ADC81A}.Ad-Hoc|x86.Build.0 = Debug|Any CPU - {23A33F9B-7672-426D-ACF9-FF8436ADC81A}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU - {23A33F9B-7672-426D-ACF9-FF8436ADC81A}.AppStore|Any CPU.Build.0 = Debug|Any CPU - {23A33F9B-7672-426D-ACF9-FF8436ADC81A}.AppStore|ARM.ActiveCfg = Debug|Any CPU - {23A33F9B-7672-426D-ACF9-FF8436ADC81A}.AppStore|ARM.Build.0 = Debug|Any CPU - {23A33F9B-7672-426D-ACF9-FF8436ADC81A}.AppStore|iPhone.ActiveCfg = Debug|Any CPU - {23A33F9B-7672-426D-ACF9-FF8436ADC81A}.AppStore|iPhone.Build.0 = Debug|Any CPU - {23A33F9B-7672-426D-ACF9-FF8436ADC81A}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU - {23A33F9B-7672-426D-ACF9-FF8436ADC81A}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU - {23A33F9B-7672-426D-ACF9-FF8436ADC81A}.AppStore|x64.ActiveCfg = Debug|Any CPU - {23A33F9B-7672-426D-ACF9-FF8436ADC81A}.AppStore|x64.Build.0 = Debug|Any CPU - {23A33F9B-7672-426D-ACF9-FF8436ADC81A}.AppStore|x86.ActiveCfg = Debug|Any CPU - {23A33F9B-7672-426D-ACF9-FF8436ADC81A}.AppStore|x86.Build.0 = Debug|Any CPU - {23A33F9B-7672-426D-ACF9-FF8436ADC81A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {23A33F9B-7672-426D-ACF9-FF8436ADC81A}.Debug|Any CPU.Build.0 = Debug|Any CPU - {23A33F9B-7672-426D-ACF9-FF8436ADC81A}.Debug|ARM.ActiveCfg = Debug|Any CPU - {23A33F9B-7672-426D-ACF9-FF8436ADC81A}.Debug|ARM.Build.0 = Debug|Any CPU - {23A33F9B-7672-426D-ACF9-FF8436ADC81A}.Debug|iPhone.ActiveCfg = Debug|Any CPU - {23A33F9B-7672-426D-ACF9-FF8436ADC81A}.Debug|iPhone.Build.0 = Debug|Any CPU - {23A33F9B-7672-426D-ACF9-FF8436ADC81A}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU - {23A33F9B-7672-426D-ACF9-FF8436ADC81A}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU - {23A33F9B-7672-426D-ACF9-FF8436ADC81A}.Debug|x64.ActiveCfg = Debug|Any CPU - {23A33F9B-7672-426D-ACF9-FF8436ADC81A}.Debug|x64.Build.0 = Debug|Any CPU - {23A33F9B-7672-426D-ACF9-FF8436ADC81A}.Debug|x86.ActiveCfg = Debug|Any CPU - {23A33F9B-7672-426D-ACF9-FF8436ADC81A}.Debug|x86.Build.0 = Debug|Any CPU - {23A33F9B-7672-426D-ACF9-FF8436ADC81A}.Release|Any CPU.ActiveCfg = Release|Any CPU - {23A33F9B-7672-426D-ACF9-FF8436ADC81A}.Release|Any CPU.Build.0 = Release|Any CPU - {23A33F9B-7672-426D-ACF9-FF8436ADC81A}.Release|ARM.ActiveCfg = Release|Any CPU - {23A33F9B-7672-426D-ACF9-FF8436ADC81A}.Release|ARM.Build.0 = Release|Any CPU - {23A33F9B-7672-426D-ACF9-FF8436ADC81A}.Release|iPhone.ActiveCfg = Release|Any CPU - {23A33F9B-7672-426D-ACF9-FF8436ADC81A}.Release|iPhone.Build.0 = Release|Any CPU - {23A33F9B-7672-426D-ACF9-FF8436ADC81A}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU - {23A33F9B-7672-426D-ACF9-FF8436ADC81A}.Release|iPhoneSimulator.Build.0 = Release|Any CPU - {23A33F9B-7672-426D-ACF9-FF8436ADC81A}.Release|x64.ActiveCfg = Release|Any CPU - {23A33F9B-7672-426D-ACF9-FF8436ADC81A}.Release|x64.Build.0 = Release|Any CPU - {23A33F9B-7672-426D-ACF9-FF8436ADC81A}.Release|x86.ActiveCfg = Release|Any CPU - {23A33F9B-7672-426D-ACF9-FF8436ADC81A}.Release|x86.Build.0 = Release|Any CPU {DF395F85-B010-465D-857A-7EBCC512C0C2}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU {DF395F85-B010-465D-857A-7EBCC512C0C2}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU {DF395F85-B010-465D-857A-7EBCC512C0C2}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU @@ -1402,8 +1350,6 @@ Global {4BD76717-3102-4969-8C2C-BAAA3F0263B6} = {A81ECBC2-6B00-4DCD-8388-469174033379} {41139F64-4046-4F16-96B7-D941D96FA9C6} = {91CF7717-08AB-4E65-B10E-0B426F01E2E8} {E7581357-FC34-474C-B8F5-307EE3CE05EF} = {41139F64-4046-4F16-96B7-D941D96FA9C6} - {88B22DBB-AA8F-4290-A454-2C109352C345} = {DB0EFB20-B024-4E5E-A75C-52143C131D25} - {23A33F9B-7672-426D-ACF9-FF8436ADC81A} = {88B22DBB-AA8F-4290-A454-2C109352C345} {A5260DE0-1FDD-467E-9CC1-A028AB081CEE} = {91CF7717-08AB-4E65-B10E-0B426F01E2E8} {DF395F85-B010-465D-857A-7EBCC512C0C2} = {A5260DE0-1FDD-467E-9CC1-A028AB081CEE} {69AF10D3-AA76-4FF7-B187-EC7E8CC5F5B8} = {807BB76E-B2BB-47A2-A57B-3D1B20FF5E7F} diff --git a/src/BuildingBlocks/DataProtection/DataProtection/DataProtection.csproj b/src/BuildingBlocks/DataProtection/DataProtection/DataProtection.csproj deleted file mode 100644 index 93a919894..000000000 --- a/src/BuildingBlocks/DataProtection/DataProtection/DataProtection.csproj +++ /dev/null @@ -1,13 +0,0 @@ - - - - netstandard1.5 - Microsoft.eShopOnContainers.BuildingBlocks - - - - - - - - \ No newline at end of file diff --git a/src/BuildingBlocks/DataProtection/DataProtection/DataProtectionBuilderExtensions.cs b/src/BuildingBlocks/DataProtection/DataProtection/DataProtectionBuilderExtensions.cs deleted file mode 100644 index 1f5bffda5..000000000 --- a/src/BuildingBlocks/DataProtection/DataProtection/DataProtectionBuilderExtensions.cs +++ /dev/null @@ -1,97 +0,0 @@ -namespace Microsoft.eShopOnContainers.BuildingBlocks -{ - using Microsoft.AspNetCore.DataProtection; - using Microsoft.AspNetCore.DataProtection.Repositories; - using Microsoft.Extensions.DependencyInjection; - using Microsoft.Extensions.Logging; - using StackExchange.Redis; - using System; - using System.Linq; - using System.Net; - - /// - /// Extension methods for for configuring - /// data protection options. - /// - public static class DataProtectionBuilderExtensions - { - /// - /// Sets up data protection to persist session keys in Redis. - /// - /// The used to set up data protection options. - /// The connection string specifying the Redis instance and database for key storage. - /// - /// The for continued configuration. - /// - /// - /// Thrown if or is . - /// - /// - /// Thrown if is empty. - /// - public static IDataProtectionBuilder PersistKeysToRedis(this IDataProtectionBuilder builder, string redisConnectionString) - { - if (builder == null) - { - throw new ArgumentNullException(nameof(builder)); - } - - if (redisConnectionString == null) - { - throw new ArgumentNullException(nameof(redisConnectionString)); - } - - if (redisConnectionString.Length == 0) - { - throw new ArgumentException("Redis connection string may not be empty.", nameof(redisConnectionString)); - } - - var configuration = ConfigurationOptions.Parse(redisConnectionString, true); - configuration.ResolveDns = true; - - return builder.Use(ServiceDescriptor.Singleton(services => - new RedisXmlRepository(configuration, services.GetRequiredService>()))); - } - - /// - /// Updates an to use the service of - /// a specific type, removing all other services of that type. - /// - /// The that should use the specified service. - /// The with the service the should use. - /// - /// The for continued configuration. - /// - /// - /// Thrown if or is . - /// - public static IDataProtectionBuilder Use(this IDataProtectionBuilder builder, ServiceDescriptor descriptor) - { - // This algorithm of removing all other services of a specific type - // before adding the new/replacement service is how the base ASP.NET - // DataProtection bits work. Due to some of the differences in how - // that base set of bits handles DI, it's better to follow suit - // and work in the same way than to try and debug weird issues. - if (builder == null) - { - throw new ArgumentNullException(nameof(builder)); - } - - if (descriptor == null) - { - throw new ArgumentNullException(nameof(descriptor)); - } - - for (int i = builder.Services.Count - 1; i >= 0; i--) - { - if (builder.Services[i]?.ServiceType == descriptor.ServiceType) - { - builder.Services.RemoveAt(i); - } - } - - builder.Services.Add(descriptor); - return builder; - } - } -} diff --git a/src/BuildingBlocks/DataProtection/DataProtection/RedisXmlRepository.cs b/src/BuildingBlocks/DataProtection/DataProtection/RedisXmlRepository.cs deleted file mode 100644 index d71f9df53..000000000 --- a/src/BuildingBlocks/DataProtection/DataProtection/RedisXmlRepository.cs +++ /dev/null @@ -1,210 +0,0 @@ -namespace Microsoft.eShopOnContainers.BuildingBlocks -{ - using Microsoft.AspNetCore.DataProtection.Repositories; - using Microsoft.Extensions.Logging; - using StackExchange.Redis; - using System; - using System.Collections.Generic; - using System.Text.RegularExpressions; - using System.Xml.Linq; - - /// - /// Key repository that stores XML encrypted keys in a Redis distributed cache. - /// - /// - /// - /// The values stored in Redis are XML documents that contain encrypted session - /// keys used for the protection of things like session state. The document contents - /// are double-encrypted - first with a changing session key; then by a master key. - /// As such, there's no risk in storing the keys in Redis - even if someone can crack - /// the master key, they still need to also crack the session key. (Other solutions - /// for sharing keys across a farm environment include writing them to files - /// on a file share.) - /// - /// - /// While the repository uses a hash to keep the set of encrypted keys separate, you - /// can further separate these items from other items in Redis by specifying a unique - /// database in the connection string. - /// - /// - /// Consumers of the repository are responsible for caching the XML items as needed. - /// Typically repositories are consumed by things like - /// which generates - /// values that get cached. The mechanism is already optimized for caching so there's - /// no need to create a redundant cache. - /// - /// - /// - /// - public class RedisXmlRepository : IXmlRepository, IDisposable - { - /// - /// The root cache key for XML items stored in Redis - /// - public static readonly string RedisHashKey = "DataProtectionXmlRepository"; - - /// - /// The connection to the Redis backing store. - /// - private IConnectionMultiplexer _connection; - - /// - /// Flag indicating whether the object has been disposed. - /// - private bool _disposed = false; - - /// - /// Initializes a new instance of the class. - /// - /// - /// The Redis connection string. - /// - /// - /// The used to log diagnostic messages. - /// - /// - /// Thrown if or is . - /// - public RedisXmlRepository(ConfigurationOptions connectionString, ILogger logger) - : this(ConnectionMultiplexer.Connect(connectionString), logger) - { - } - - /// - /// Initializes a new instance of the class. - /// - /// - /// The Redis database connection. - /// - /// - /// The used to log diagnostic messages. - /// - /// - /// Thrown if or is . - /// - public RedisXmlRepository(IConnectionMultiplexer connection, ILogger logger) - { - if (connection == null) - { - throw new ArgumentNullException(nameof(connection)); - } - - if (logger == null) - { - throw new ArgumentNullException(nameof(logger)); - } - - this._connection = connection; - this.Logger = logger; - - // Mask the password so it doesn't get logged. - var configuration = Regex.Replace(this._connection.Configuration, @"password\s*=\s*[^,]*", "password=****", RegexOptions.IgnoreCase); - this.Logger.LogDebug("Storing data protection keys in Redis: {RedisConfiguration}", configuration); - } - - /// - /// Gets the logger. - /// - /// - /// The used to log diagnostic messages. - /// - public ILogger Logger { get; private set; } - - /// - /// Performs application-defined tasks associated with freeing, releasing, - /// or resetting unmanaged resources. - /// - public void Dispose() - { - this.Dispose(true); - } - - /// - /// Gets all top-level XML elements in the repository. - /// - /// - /// An with the set of elements - /// stored in the repository. - /// - public IReadOnlyCollection GetAllElements() - { - var database = this._connection.GetDatabase(); - var hash = database.HashGetAll(RedisHashKey); - var elements = new List(); - - if (hash == null || hash.Length == 0) - { - return elements.AsReadOnly(); - } - - foreach (var item in hash.ToStringDictionary()) - { - elements.Add(XElement.Parse(item.Value)); - } - - this.Logger.LogDebug("Read {XmlElementCount} XML elements from Redis.", elements.Count); - return elements.AsReadOnly(); - } - - /// - /// Adds a top-level XML element to the repository. - /// - /// The element to add. - /// - /// An optional name to be associated with the XML element. - /// For instance, if this repository stores XML files on disk, the friendly name may - /// be used as part of the file name. Repository implementations are not required to - /// observe this parameter even if it has been provided by the caller. - /// - /// - /// The parameter must be unique if specified. - /// For instance, it could be the ID of the key being stored. - /// - /// - /// Thrown if is . - /// - public void StoreElement(XElement element, string friendlyName) - { - if (element == null) - { - throw new ArgumentNullException(nameof(element)); - } - - if (string.IsNullOrEmpty(friendlyName)) - { - // The framework always passes in a name, but - // the contract indicates this may be null or empty. - friendlyName = Guid.NewGuid().ToString(); - } - - this.Logger.LogDebug("Storing XML element with friendly name {XmlElementFriendlyName}.", friendlyName); - - this._connection.GetDatabase().HashSet(RedisHashKey, friendlyName, element.ToString()); - } - - /// - /// Releases unmanaged and - optionally - managed resources. - /// - /// - /// to release both managed and unmanaged resources; - /// to release only unmanaged resources. - /// - protected virtual void Dispose(bool disposing) - { - if (!this._disposed) - { - if (disposing) - { - if (this._connection != null) - { - this._connection.Close(); - this._connection.Dispose(); - } - } - - this._connection = null; - this._disposed = true; - } - } - } -} diff --git a/src/Services/Basket/Basket.API/Controllers/BasketController.cs b/src/Services/Basket/Basket.API/Controllers/BasketController.cs index 18a3b221d..11ecac7c2 100644 --- a/src/Services/Basket/Basket.API/Controllers/BasketController.cs +++ b/src/Services/Basket/Basket.API/Controllers/BasketController.cs @@ -59,6 +59,12 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API.Controllers guid : basketCheckout.RequestId; var basket = await _repository.GetBasketAsync(userId); + + if (basket == null) + { + return BadRequest(); + } + var eventMessage = new UserCheckoutAcceptedIntegrationEvent(userId, basketCheckout.City, basketCheckout.Street, basketCheckout.State, basketCheckout.Country, basketCheckout.ZipCode, basketCheckout.CardNumber, basketCheckout.CardHolderName, basketCheckout.CardExpiration, basketCheckout.CardSecurityNumber, basketCheckout.CardTypeId, basketCheckout.Buyer, basketCheckout.RequestId, basket); @@ -66,12 +72,7 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API.Controllers // Once basket is checkout, sends an integration event to // ordering.api to convert basket to order and proceeds with // order creation process - _eventBus.Publish(eventMessage); - - if (basket == null) - { - return BadRequest(); - } + _eventBus.Publish(eventMessage); return Accepted(); } diff --git a/src/Services/Identity/Identity.API/Identity.API.csproj b/src/Services/Identity/Identity.API/Identity.API.csproj index 8d761b9ed..d5c4debe8 100644 --- a/src/Services/Identity/Identity.API/Identity.API.csproj +++ b/src/Services/Identity/Identity.API/Identity.API.csproj @@ -23,6 +23,7 @@ + @@ -43,7 +44,6 @@ - diff --git a/src/Services/Identity/Identity.API/Startup.cs b/src/Services/Identity/Identity.API/Startup.cs index 6ac0815fd..ead58768b 100644 --- a/src/Services/Identity/Identity.API/Startup.cs +++ b/src/Services/Identity/Identity.API/Startup.cs @@ -4,10 +4,10 @@ using IdentityServer4.Services; using Microsoft.ApplicationInsights.Extensibility; using Microsoft.ApplicationInsights.ServiceFabric; using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.DataProtection; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Identity; using Microsoft.EntityFrameworkCore; -using Microsoft.eShopOnContainers.BuildingBlocks; using Microsoft.eShopOnContainers.Services.Identity.API.Certificates; using Microsoft.eShopOnContainers.Services.Identity.API.Data; using Microsoft.eShopOnContainers.Services.Identity.API.Models; @@ -16,6 +16,7 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.HealthChecks; using Microsoft.Extensions.Logging; +using StackExchange.Redis; using System; using System.Reflection; @@ -59,7 +60,7 @@ namespace Microsoft.eShopOnContainers.Services.Identity.API { opts.ApplicationDiscriminator = "eshop.identity"; }) - .PersistKeysToRedis(Configuration["DPConnectionString"]); + .PersistKeysToRedis(ConnectionMultiplexer.Connect(Configuration["DPConnectionString"]), "DataProtection-Keys"); } services.AddHealthChecks(checks => diff --git a/src/Services/Ordering/Ordering.API/Controllers/OrdersController.cs b/src/Services/Ordering/Ordering.API/Controllers/OrdersController.cs index bc1fef585..993986543 100644 --- a/src/Services/Ordering/Ordering.API/Controllers/OrdersController.cs +++ b/src/Services/Ordering/Ordering.API/Controllers/OrdersController.cs @@ -86,9 +86,7 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.API.Controllers [ProducesResponseType(typeof(IEnumerable), (int)HttpStatusCode.OK)] public async Task GetOrders() { - var orderTask = _orderQueries.GetOrdersAsync(); - - var orders = await orderTask; + var orders = await _orderQueries.GetOrdersAsync(); return Ok(orders); } diff --git a/src/Services/Ordering/Ordering.Domain/AggregatesModel/OrderAggregate/Order.cs b/src/Services/Ordering/Ordering.Domain/AggregatesModel/OrderAggregate/Order.cs index cd69aa211..d2e742b33 100644 --- a/src/Services/Ordering/Ordering.Domain/AggregatesModel/OrderAggregate/Order.cs +++ b/src/Services/Ordering/Ordering.Domain/AggregatesModel/OrderAggregate/Order.cs @@ -92,42 +92,34 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.O } public void SetAwaitingValidationStatus() - { - if (_orderStatusId == OrderStatus.Cancelled.Id || - _orderStatusId != OrderStatus.Submitted.Id) + { + if (_orderStatusId == OrderStatus.Submitted.Id) { - StatusChangeException(OrderStatus.AwaitingValidation); - } - - AddDomainEvent(new OrderStatusChangedToAwaitingValidationDomainEvent(Id, _orderItems)); - - _orderStatusId = OrderStatus.AwaitingValidation.Id; + AddDomainEvent(new OrderStatusChangedToAwaitingValidationDomainEvent(Id, _orderItems)); + _orderStatusId = OrderStatus.AwaitingValidation.Id; + } } public void SetStockConfirmedStatus() { - if (_orderStatusId != OrderStatus.AwaitingValidation.Id) + if (_orderStatusId == OrderStatus.AwaitingValidation.Id) { - StatusChangeException(OrderStatus.StockConfirmed); - } - - AddDomainEvent(new OrderStatusChangedToStockConfirmedDomainEvent(Id)); + AddDomainEvent(new OrderStatusChangedToStockConfirmedDomainEvent(Id)); - _orderStatusId = OrderStatus.StockConfirmed.Id; - _description = "All the items were confirmed with available stock."; + _orderStatusId = OrderStatus.StockConfirmed.Id; + _description = "All the items were confirmed with available stock."; + } } public void SetPaidStatus() { - if (_orderStatusId != OrderStatus.StockConfirmed.Id) + if (_orderStatusId == OrderStatus.StockConfirmed.Id) { - StatusChangeException(OrderStatus.Paid); - } + AddDomainEvent(new OrderStatusChangedToPaidDomainEvent(Id, OrderItems)); - AddDomainEvent(new OrderStatusChangedToPaidDomainEvent(Id, OrderItems)); - - _orderStatusId = OrderStatus.Paid.Id; - _description = "The payment was performed at a simulated \"American Bank checking bank account endinf on XX35071\""; + _orderStatusId = OrderStatus.Paid.Id; + _description = "The payment was performed at a simulated \"American Bank checking bank account endinf on XX35071\""; + } } public void SetShippedStatus() @@ -155,19 +147,17 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.O public void SetCancelledStatusWhenStockIsRejected(IEnumerable orderStockRejectedItems) { - if (_orderStatusId != OrderStatus.AwaitingValidation.Id) + if (_orderStatusId == OrderStatus.AwaitingValidation.Id) { - StatusChangeException(OrderStatus.Cancelled); - } - - _orderStatusId = OrderStatus.Cancelled.Id; + _orderStatusId = OrderStatus.Cancelled.Id; - var itemsStockRejectedProductNames = OrderItems - .Where(c => orderStockRejectedItems.Contains(c.ProductId)) - .Select(c => c.GetOrderItemProductName()); + var itemsStockRejectedProductNames = OrderItems + .Where(c => orderStockRejectedItems.Contains(c.ProductId)) + .Select(c => c.GetOrderItemProductName()); - var itemsStockRejectedDescription = string.Join(", ", itemsStockRejectedProductNames); - _description = $"The product items don't have stock: ({itemsStockRejectedDescription})."; + var itemsStockRejectedDescription = string.Join(", ", itemsStockRejectedProductNames); + _description = $"The product items don't have stock: ({itemsStockRejectedDescription})."; + } } private void AddOrderStartedDomainEvent(string userId, int cardTypeId, string cardNumber, diff --git a/src/Web/WebMVC/Controllers/CartController.cs b/src/Web/WebMVC/Controllers/CartController.cs index a7bb84959..8b41c5320 100644 --- a/src/Web/WebMVC/Controllers/CartController.cs +++ b/src/Web/WebMVC/Controllers/CartController.cs @@ -1,13 +1,11 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; +using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.eShopOnContainers.WebMVC.Services; using Microsoft.eShopOnContainers.WebMVC.ViewModels; -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Authentication; using Polly.CircuitBreaker; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; namespace Microsoft.eShopOnContainers.WebMVC.Controllers { @@ -94,12 +92,12 @@ namespace Microsoft.eShopOnContainers.WebMVC.Controllers HandleBrokenCircuitException(); } - return RedirectToAction("Index", "Catalog"); + return RedirectToAction("Index", "Catalog", new { errorMsg = ViewBag.BasketInoperativeMsg }); } private void HandleBrokenCircuitException() { - TempData["BasketInoperativeMsg"] = "Basket Service is inoperative, please try later on. (Business Msg Due to Circuit-Breaker)"; + ViewBag.BasketInoperativeMsg = "Basket Service is inoperative, please try later on. (Business Msg Due to Circuit-Breaker)"; } } } diff --git a/src/Web/WebMVC/Controllers/CatalogController.cs b/src/Web/WebMVC/Controllers/CatalogController.cs index 0e6dc3257..9e0859858 100644 --- a/src/Web/WebMVC/Controllers/CatalogController.cs +++ b/src/Web/WebMVC/Controllers/CatalogController.cs @@ -4,6 +4,7 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.eShopOnContainers.WebMVC.ViewModels.Pagination; using Microsoft.eShopOnContainers.WebMVC.Services; using Microsoft.eShopOnContainers.WebMVC.ViewModels.CatalogViewModels; +using Microsoft.AspNetCore.Http; namespace Microsoft.eShopOnContainers.WebMVC.Controllers { @@ -14,7 +15,7 @@ namespace Microsoft.eShopOnContainers.WebMVC.Controllers public CatalogController(ICatalogService catalogSvc) => _catalogSvc = catalogSvc; - public async Task Index(int? BrandFilterApplied, int? TypesFilterApplied, int? page) + public async Task Index(int? BrandFilterApplied, int? TypesFilterApplied, int? page, [FromQuery]string errorMsg) { var itemsPage = 10; var catalog = await _catalogSvc.GetCatalogItems(page ?? 0, itemsPage, BrandFilterApplied, TypesFilterApplied); @@ -37,6 +38,8 @@ namespace Microsoft.eShopOnContainers.WebMVC.Controllers vm.PaginationInfo.Next = (vm.PaginationInfo.ActualPage == vm.PaginationInfo.TotalPages - 1) ? "is-disabled" : ""; vm.PaginationInfo.Previous = (vm.PaginationInfo.ActualPage == 0) ? "is-disabled" : ""; + ViewBag.BasketInoperativeMsg = errorMsg; + return View(vm); } } diff --git a/src/Web/WebMVC/Startup.cs b/src/Web/WebMVC/Startup.cs index 63ce47045..ced47ea67 100644 --- a/src/Web/WebMVC/Startup.cs +++ b/src/Web/WebMVC/Startup.cs @@ -3,9 +3,9 @@ using Microsoft.ApplicationInsights.ServiceFabric; using Microsoft.AspNetCore.Authentication.Cookies; using Microsoft.AspNetCore.Authentication.OpenIdConnect; using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.DataProtection; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; -using Microsoft.eShopOnContainers.BuildingBlocks; using Microsoft.eShopOnContainers.BuildingBlocks.Resilience.Http; using Microsoft.eShopOnContainers.WebMVC.Infrastructure; using Microsoft.eShopOnContainers.WebMVC.Services; @@ -14,6 +14,7 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.HealthChecks; using Microsoft.Extensions.Logging; +using StackExchange.Redis; using System; using System.IdentityModel.Tokens.Jwt; using WebMVC.Infrastructure; @@ -36,7 +37,8 @@ namespace Microsoft.eShopOnContainers.WebMVC { RegisterAppInsights(services); - services.AddMvc(); + services.AddMvc(); + services.AddSession(); if (Configuration.GetValue("IsClusterEnv") == bool.TrueString) @@ -45,7 +47,7 @@ namespace Microsoft.eShopOnContainers.WebMVC { opts.ApplicationDiscriminator = "eshop.webmvc"; }) - .PersistKeysToRedis(Configuration["DPConnectionString"]); + .PersistKeysToRedis(ConnectionMultiplexer.Connect(Configuration["DPConnectionString"]), "DataProtection-Keys"); } services.Configure(Configuration); diff --git a/src/Web/WebMVC/ViewComponents/CartList.cs b/src/Web/WebMVC/ViewComponents/CartList.cs index 04a7a783a..60fe863d4 100644 --- a/src/Web/WebMVC/ViewComponents/CartList.cs +++ b/src/Web/WebMVC/ViewComponents/CartList.cs @@ -24,9 +24,9 @@ namespace Microsoft.eShopOnContainers.WebMVC.ViewComponents return View(vm); } catch (BrokenCircuitException) - { + { // Catch error when Basket.api is in circuit-opened mode - TempData["BasketInoperativeMsg"] = "Basket Service is inoperative, please try later on. (Business Msg Due to Circuit-Breaker)"; + ViewBag.BasketInoperativeMsg = "Basket Service is inoperative, please try later on. (Business Msg Due to Circuit-Breaker)"; } return View(vm); diff --git a/src/Web/WebMVC/Views/Catalog/Index.cshtml b/src/Web/WebMVC/Views/Catalog/Index.cshtml index 23667500f..c2ef7f367 100644 --- a/src/Web/WebMVC/Views/Catalog/Index.cshtml +++ b/src/Web/WebMVC/Views/Catalog/Index.cshtml @@ -25,10 +25,10 @@

- @if(TempData.ContainsKey("BasketInoperativeMsg")) + @if(ViewBag.BasketInoperativeMsg != null) { }
diff --git a/src/Web/WebMVC/Views/Shared/Components/CartList/Default.cshtml b/src/Web/WebMVC/Views/Shared/Components/CartList/Default.cshtml index 091365e1e..ac188e0fe 100644 --- a/src/Web/WebMVC/Views/Shared/Components/CartList/Default.cshtml +++ b/src/Web/WebMVC/Views/Shared/Components/CartList/Default.cshtml @@ -5,21 +5,21 @@ }
- @if (TempData.ContainsKey("BasketInoperativeMsg")) + @if (ViewBag.BasketInoperativeMsg != null) {
} else {

- @if (TempData.ContainsKey("BasketInoperativeMsg")) + @if (ViewBag.BasketInoperativeMsg != null) { } diff --git a/src/Web/WebMVC/WebMVC.csproj b/src/Web/WebMVC/WebMVC.csproj index 47603f10f..7c403e1de 100644 --- a/src/Web/WebMVC/WebMVC.csproj +++ b/src/Web/WebMVC/WebMVC.csproj @@ -24,6 +24,7 @@ + @@ -39,7 +40,6 @@ - diff --git a/src/Web/WebSPA/Startup.cs b/src/Web/WebSPA/Startup.cs index 243976d8f..3f2354b97 100644 --- a/src/Web/WebSPA/Startup.cs +++ b/src/Web/WebSPA/Startup.cs @@ -3,13 +3,14 @@ using Microsoft.ApplicationInsights.Extensibility; using Microsoft.ApplicationInsights.ServiceFabric; using Microsoft.AspNetCore.Antiforgery; using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.DataProtection; using Microsoft.AspNetCore.Hosting; -using Microsoft.eShopOnContainers.BuildingBlocks; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.HealthChecks; using Microsoft.Extensions.Logging; using Newtonsoft.Json.Serialization; +using StackExchange.Redis; using System; using System.IO; using WebSPA.Infrastructure; @@ -64,7 +65,7 @@ namespace eShopConContainers.WebSPA { opts.ApplicationDiscriminator = "eshop.webspa"; }) - .PersistKeysToRedis(Configuration["DPConnectionString"]); + .PersistKeysToRedis(ConnectionMultiplexer.Connect(Configuration["DPConnectionString"]), "DataProtection-Keys"); } services.AddAntiforgery(options => options.HeaderName = "X-XSRF-TOKEN"); diff --git a/src/Web/WebSPA/WebSPA.csproj b/src/Web/WebSPA/WebSPA.csproj index 308dc5324..5440ee30e 100644 --- a/src/Web/WebSPA/WebSPA.csproj +++ b/src/Web/WebSPA/WebSPA.csproj @@ -32,6 +32,7 @@ + @@ -61,7 +62,6 @@ --> - @@ -76,4 +76,6 @@ + + diff --git a/test/Services/UnitTest/Catalog/Application/CatalogControllerTest.cs b/test/Services/UnitTest/Catalog/Application/CatalogControllerTest.cs index 4b4a63817..58d32c212 100644 --- a/test/Services/UnitTest/Catalog/Application/CatalogControllerTest.cs +++ b/test/Services/UnitTest/Catalog/Application/CatalogControllerTest.cs @@ -44,7 +44,7 @@ namespace UnitTest.Catalog.Application //Act var orderController = new CatalogController(_catalogServiceMock.Object); - var actionResult = await orderController.Index(fakeBrandFilterApplied, fakeTypesFilterApplied, fakePage); + var actionResult = await orderController.Index(fakeBrandFilterApplied, fakeTypesFilterApplied, fakePage, null); //Assert var viewResult = Assert.IsType(actionResult);