From 0bc2a29b38b8f768c36170234bf6432482ce4f55 Mon Sep 17 00:00:00 2001 From: Rafsanul Hasan Date: Sun, 9 Sep 2018 04:14:16 +0600 Subject: [PATCH] Re-factored and formatted MobileAgg project codes --- .../aggregator/Config/UrlsConfig.cs | 7 +- .../Controllers/BasketController.cs | 243 +++++++------ .../aggregator/Controllers/HomeController.cs | 22 +- .../aggregator/Controllers/OrderController.cs | 61 ++-- .../Filters/AuthorizeCheckOperationFilter.cs | 56 +-- ...ttpClientAuthorizationDelegatingHandler.cs | 76 ++-- .../aggregator/Models/AddBasketItemRequest.cs | 9 +- .../aggregator/Models/BasketData.cs | 45 ++- .../aggregator/Models/CatalogItem.cs | 21 +- .../aggregator/Models/OrderData.cs | 50 ++- .../aggregator/Models/OrderItemData.cs | 25 +- .../Models/UpdateBasketItemsRequest.cs | 43 ++- .../aggregator/Models/UpdateBasketRequest.cs | 27 +- .../Mobile.Bff.Shopping/aggregator/Program.cs | 57 ++- .../aggregator/Services/BasketService.cs | 60 ++-- .../aggregator/Services/CatalogService.cs | 60 ++-- .../aggregator/Services/IBasketService.cs | 18 +- .../aggregator/Services/ICatalogService.cs | 17 +- .../aggregator/Services/IOrderApiClient.cs | 17 +- .../aggregator/Services/OrderApiClient.cs | 57 +-- .../Mobile.Bff.Shopping/aggregator/Startup.cs | 326 +++++++++--------- .../aggregator/appsettings.json | 26 +- .../aggregator/appsettings.localhost.json | 12 +- 23 files changed, 652 insertions(+), 683 deletions(-) diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Config/UrlsConfig.cs b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Config/UrlsConfig.cs index e920fbbb2..26e35deb8 100644 --- a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Config/UrlsConfig.cs +++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Config/UrlsConfig.cs @@ -1,11 +1,8 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; +using System.Collections.Generic; namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Config { - public class UrlsConfig + public class UrlsConfig { public class CatalogOperations { diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Controllers/BasketController.cs b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Controllers/BasketController.cs index 702c805fb..76fa4a4d7 100644 --- a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Controllers/BasketController.cs +++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Controllers/BasketController.cs @@ -3,131 +3,130 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Models; using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Services; using System; -using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Controllers { - [Route("api/v1/[controller]")] - [Authorize] - public class BasketController : Controller - { - private readonly ICatalogService _catalog; - private readonly IBasketService _basket; - public BasketController(ICatalogService catalogService, IBasketService basketService) - { - _catalog = catalogService; - _basket = basketService; - } - - [HttpPost] - [HttpPut] - public async Task UpdateAllBasket([FromBody] UpdateBasketRequest data) - { - - if (data.Items == null || !data.Items.Any()) - { - return BadRequest("Need to pass at least one basket line"); - } - - // Retrieve the current basket - var currentBasket = await _basket.GetById(data.BuyerId); - if (currentBasket == null) - { - currentBasket = new BasketData(data.BuyerId); - } - - var catalogItems = await _catalog.GetCatalogItems(data.Items.Select(x => x.ProductId)); - var newBasket = new BasketData(data.BuyerId); - - foreach (var bitem in data.Items) - { - var catalogItem = catalogItems.SingleOrDefault(ci => ci.Id == bitem.ProductId); - if (catalogItem == null) - { - return BadRequest($"Basket refers to a non-existing catalog item ({bitem.ProductId})"); - } - - newBasket.Items.Add(new BasketDataItem() - { - Id = bitem.Id, - ProductId = catalogItem.Id.ToString(), - ProductName = catalogItem.Name, - PictureUrl = catalogItem.PictureUri, - UnitPrice = catalogItem.Price, - Quantity = bitem.Quantity - }); - } - - await _basket.Update(newBasket); - return Ok(newBasket); - } - - [HttpPut] - [Route("items")] - public async Task UpdateQuantities([FromBody] UpdateBasketItemsRequest data) - { - if (!data.Updates.Any()) - { - return BadRequest("No updates sent"); - } - - // Retrieve the current basket - var currentBasket = await _basket.GetById(data.BasketId); - if (currentBasket == null) - { - return BadRequest($"Basket with id {data.BasketId} not found."); - } - - // Update with new quantities - foreach (var update in data.Updates) - { - var basketItem = currentBasket.Items.SingleOrDefault(bitem => bitem.Id == update.BasketItemId); - if (basketItem == null) - { - return BadRequest($"Basket item with id {update.BasketItemId} not found"); - } - basketItem.Quantity = update.NewQty; - } - - // Save the updated basket - await _basket.Update(currentBasket); - return Ok(currentBasket); - } - - [HttpPost] - [Route("items")] - public async Task AddBasketItem([FromBody] AddBasketItemRequest data) - { - if (data == null || data.Quantity == 0) - { - return BadRequest("Invalid payload"); - } - - // Step 1: Get the item from catalog - var item = await _catalog.GetCatalogItem(data.CatalogItemId); - - //item.PictureUri = - - // Step 2: Get current basket status - var currentBasket = (await _basket.GetById(data.BasketId)) ?? new BasketData(data.BasketId); - // Step 3: Merge current status with new product - currentBasket.Items.Add(new BasketDataItem() - { - UnitPrice = item.Price, - PictureUrl = item.PictureUri, - ProductId = item.Id.ToString(), - ProductName = item.Name, - Quantity = data.Quantity, - Id = Guid.NewGuid().ToString() - }); - - // Step 4: Update basket - await _basket.Update(currentBasket); - - - return Ok(); - } - } + [Route("api/v1/[controller]")] + [Authorize] + public class BasketController : Controller + { + private readonly ICatalogService _catalog; + private readonly IBasketService _basket; + public BasketController(ICatalogService catalogService, IBasketService basketService) + { + _catalog = catalogService; + _basket = basketService; + } + + [HttpPost] + [HttpPut] + public async Task UpdateAllBasket([FromBody] UpdateBasketRequest data) + { + + if (data.Items == null || !data.Items.Any()) + { + return BadRequest("Need to pass at least one basket line"); + } + + // Retrieve the current basket + var currentBasket = await _basket.GetById(data.BuyerId); + if (currentBasket == null) + { + currentBasket = new BasketData(data.BuyerId); + } + + System.Collections.Generic.IEnumerable catalogItems = await _catalog.GetCatalogItems(data.Items.Select(x => x.ProductId)); + BasketData newBasket = new BasketData(data.BuyerId); + + foreach (UpdateBasketRequestItemData bitem in data.Items) + { + var catalogItem = catalogItems.SingleOrDefault(ci => ci.Id == bitem.ProductId); + if (catalogItem == null) + { + return BadRequest($"Basket refers to a non-existing catalog item ({bitem.ProductId})"); + } + + newBasket.Items.Add(new BasketDataItem() + { + Id = bitem.Id, + ProductId = catalogItem.Id.ToString(), + ProductName = catalogItem.Name, + PictureUrl = catalogItem.PictureUri, + UnitPrice = catalogItem.Price, + Quantity = bitem.Quantity + }); + } + + await _basket.Update(newBasket); + return Ok(newBasket); + } + + [HttpPut] + [Route("items")] + public async Task UpdateQuantities([FromBody] UpdateBasketItemsRequest data) + { + if (!data.Updates.Any()) + { + return BadRequest("No updates sent"); + } + + // Retrieve the current basket + BasketData currentBasket = await _basket.GetById(data.BasketId); + if (currentBasket == null) + { + return BadRequest($"Basket with id {data.BasketId} not found."); + } + + // Update with new quantities + foreach (UpdateBasketItemData update in data.Updates) + { + BasketDataItem basketItem = currentBasket.Items.SingleOrDefault(bitem => bitem.Id == update.BasketItemId); + if (basketItem == null) + { + return BadRequest($"Basket item with id {update.BasketItemId} not found"); + } + basketItem.Quantity = update.NewQty; + } + + // Save the updated basket + await _basket.Update(currentBasket); + return Ok(currentBasket); + } + + [HttpPost] + [Route("items")] + public async Task AddBasketItem([FromBody] AddBasketItemRequest data) + { + if (data == null || data.Quantity == 0) + { + return BadRequest("Invalid payload"); + } + + // Step 1: Get the item from catalog + var item = await _catalog.GetCatalogItem(data.CatalogItemId); + + //item.PictureUri = + + // Step 2: Get current basket status + var currentBasket = (await _basket.GetById(data.BasketId)) ?? new BasketData(data.BasketId); + // Step 3: Merge current status with new product + currentBasket.Items.Add(new BasketDataItem() + { + UnitPrice = item.Price, + PictureUrl = item.PictureUri, + ProductId = item.Id.ToString(), + ProductName = item.Name, + Quantity = data.Quantity, + Id = Guid.NewGuid().ToString() + }); + + // Step 4: Update basket + await _basket.Update(currentBasket); + + + return Ok(); + } + } } diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Controllers/HomeController.cs b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Controllers/HomeController.cs index 48a71480a..81b2d7d7f 100644 --- a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Controllers/HomeController.cs +++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Controllers/HomeController.cs @@ -1,18 +1,14 @@ using Microsoft.AspNetCore.Mvc; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Controllers { - [Route("")] - public class HomeController : Controller - { - [HttpGet()] - public IActionResult Index() - { - return new RedirectResult("~/swagger"); - } - } + [Route("")] + public class HomeController : Controller + { + [HttpGet()] + public IActionResult Index() + { + return new RedirectResult("~/swagger"); + } + } } diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Controllers/OrderController.cs b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Controllers/OrderController.cs index 4c18d25ae..add51ee3f 100644 --- a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Controllers/OrderController.cs +++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Controllers/OrderController.cs @@ -1,42 +1,39 @@ using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Services; -using System; -using System.Collections.Generic; -using System.Linq; using System.Threading.Tasks; namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Controllers { - [Route("api/v1/[controller]")] - [Authorize] - public class OrderController : Controller - { - private readonly IBasketService _basketService; - private readonly IOrderApiClient _orderClient; - public OrderController(IBasketService basketService, IOrderApiClient orderClient) - { - _basketService = basketService; - _orderClient = orderClient; - } + [Route("api/v1/[controller]")] + [Authorize] + public class OrderController : Controller + { + private readonly IBasketService _basketService; + private readonly IOrderApiClient _orderClient; + public OrderController(IBasketService basketService, IOrderApiClient orderClient) + { + _basketService = basketService; + _orderClient = orderClient; + } - [Route("draft/{basketId}")] - [HttpGet] - public async Task GetOrderDraft(string basketId) - { - if (string.IsNullOrEmpty(basketId)) - { - return BadRequest("Need a valid basketid"); - } - // Get the basket data and build a order draft based on it - var basket = await _basketService.GetById(basketId); - if (basket == null) - { - return BadRequest($"No basket found for id {basketId}"); - } + [Route("draft/{basketId}")] + [HttpGet] + public async Task GetOrderDraft(string basketId) + { + if (string.IsNullOrEmpty(basketId)) + { + return BadRequest("Need a valid basketid"); + } + // Get the basket data and build a order draft based on it + var basket = await _basketService.GetById(basketId); + if (basket == null) + { + return BadRequest($"No basket found for id {basketId}"); + } - var orderDraft = await _orderClient.GetOrderDraftFromBasket(basket); - return Ok(orderDraft); - } - } + var orderDraft = await _orderClient.GetOrderDraftFromBasket(basket); + return Ok(orderDraft); + } + } } diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Filters/AuthorizeCheckOperationFilter.cs b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Filters/AuthorizeCheckOperationFilter.cs index b3a7246aa..89cbf52f2 100644 --- a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Filters/AuthorizeCheckOperationFilter.cs +++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Filters/AuthorizeCheckOperationFilter.cs @@ -1,33 +1,35 @@ namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Filters { - using Microsoft.AspNetCore.Authorization; - using Swashbuckle.AspNetCore.Swagger; - using Swashbuckle.AspNetCore.SwaggerGen; - using System.Collections.Generic; - using System.Linq; + using Microsoft.AspNetCore.Authorization; + using Swashbuckle.AspNetCore.Swagger; + using Swashbuckle.AspNetCore.SwaggerGen; + using System.Collections.Generic; + using System.Linq; - namespace Basket.API.Infrastructure.Filters - { - public class AuthorizeCheckOperationFilter : IOperationFilter - { - public void Apply(Operation operation, OperationFilterContext context) - { - // Check for authorize attribute - var hasAuthorize = context.ApiDescription.ControllerAttributes().OfType().Any() || - context.ApiDescription.ActionAttributes().OfType().Any(); + namespace Basket.API.Infrastructure.Filters + { + public class AuthorizeCheckOperationFilter : IOperationFilter + { + public void Apply(Operation operation, OperationFilterContext context) + { + // Check for authorize attribute + var hasAuthorize = context.ApiDescription.ControllerAttributes().OfType().Any() || + context.ApiDescription.ActionAttributes().OfType().Any(); - if (hasAuthorize) - { - operation.Responses.Add("401", new Response { Description = "Unauthorized" }); - operation.Responses.Add("403", new Response { Description = "Forbidden" }); + if (hasAuthorize) + { + operation.Responses.Add("401", new Response { Description = "Unauthorized" }); + operation.Responses.Add("403", new Response { Description = "Forbidden" }); - operation.Security = new List>>(); - operation.Security.Add(new Dictionary> - { - { "oauth2", new [] { "Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator" } } - }); - } - } - } - } + operation.Security = new List>> + { + new Dictionary> + { + { "oauth2", new [] { "Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator" } } + } + }; + } + } + } + } } diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Infrastructure/HttpClientAuthorizationDelegatingHandler.cs b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Infrastructure/HttpClientAuthorizationDelegatingHandler.cs index 967a8c826..9b2bf0cb7 100644 --- a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Infrastructure/HttpClientAuthorizationDelegatingHandler.cs +++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Infrastructure/HttpClientAuthorizationDelegatingHandler.cs @@ -8,42 +8,42 @@ using System.Threading.Tasks; namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Infrastructure { - public class HttpClientAuthorizationDelegatingHandler - : DelegatingHandler - { - private readonly IHttpContextAccessor _httpContextAccesor; - - public HttpClientAuthorizationDelegatingHandler(IHttpContextAccessor httpContextAccesor) - { - _httpContextAccesor = httpContextAccesor; - } - - protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) - { - var authorizationHeader = _httpContextAccesor.HttpContext - .Request.Headers["Authorization"]; - - if (!string.IsNullOrEmpty(authorizationHeader)) - { - request.Headers.Add("Authorization", new List() { authorizationHeader }); - } - - var token = await GetToken(); - - if (token != null) - { - request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token); - } - - return await base.SendAsync(request, cancellationToken); - } - - async Task GetToken() - { - const string ACCESS_TOKEN = "access_token"; - - return await _httpContextAccesor.HttpContext - .GetTokenAsync(ACCESS_TOKEN); - } - } + public class HttpClientAuthorizationDelegatingHandler + : DelegatingHandler + { + private readonly IHttpContextAccessor _httpContextAccesor; + + public HttpClientAuthorizationDelegatingHandler(IHttpContextAccessor httpContextAccesor) + { + _httpContextAccesor = httpContextAccesor; + } + + protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) + { + var authorizationHeader = _httpContextAccesor.HttpContext + .Request.Headers["Authorization"]; + + if (!string.IsNullOrEmpty(authorizationHeader)) + { + request.Headers.Add("Authorization", new List() { authorizationHeader }); + } + + var token = await GetToken(); + + if (token != null) + { + request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token); + } + + return await base.SendAsync(request, cancellationToken); + } + + async Task GetToken() + { + const string ACCESS_TOKEN = "access_token"; + + return await _httpContextAccesor.HttpContext + .GetTokenAsync(ACCESS_TOKEN); + } + } } diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/AddBasketItemRequest.cs b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/AddBasketItemRequest.cs index f81842c09..c1ba894be 100644 --- a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/AddBasketItemRequest.cs +++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/AddBasketItemRequest.cs @@ -1,11 +1,6 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; - -namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Models +namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Models { - public class AddBasketItemRequest + public class AddBasketItemRequest { public int CatalogItemId { get; set; } public string BasketId { get; set; } diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/BasketData.cs b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/BasketData.cs index 1b9348c44..73d41ebd6 100644 --- a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/BasketData.cs +++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/BasketData.cs @@ -1,31 +1,28 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; +using System.Collections.Generic; namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Models { - public class BasketData - { - public string BuyerId { get; set; } - public List Items { get; set; } + public class BasketData + { + public string BuyerId { get; set; } + public IList Items { get; set; } - public BasketData(string buyerId) - { - BuyerId = buyerId; - Items = new List(); - } - } + public BasketData(string buyerId) + { + BuyerId = buyerId; + Items = new List(); + } + } - public class BasketDataItem - { - public string Id { get; set; } - public string ProductId { get; set; } - public string ProductName { get; set; } - public decimal UnitPrice { get; set; } - public decimal OldUnitPrice { get; set; } - public int Quantity { get; set; } - public string PictureUrl { get; set; } + public class BasketDataItem + { + public string Id { get; set; } + public string ProductId { get; set; } + public string ProductName { get; set; } + public decimal UnitPrice { get; set; } + public decimal OldUnitPrice { get; set; } + public int Quantity { get; set; } + public string PictureUrl { get; set; } - } + } } diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/CatalogItem.cs b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/CatalogItem.cs index 25f766719..aeea0673a 100644 --- a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/CatalogItem.cs +++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/CatalogItem.cs @@ -1,20 +1,15 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; - -namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Models +namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Models { - public class CatalogItem - { - public int Id { get; set; } + public class CatalogItem + { + public int Id { get; set; } - public string Name { get; set; } + public string Name { get; set; } - public decimal Price { get; set; } + public decimal Price { get; set; } - public string PictureUri { get; set; } + public string PictureUri { get; set; } - } + } } diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/OrderData.cs b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/OrderData.cs index e87cc18f0..e892b3795 100644 --- a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/OrderData.cs +++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/OrderData.cs @@ -1,33 +1,31 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; +using System.Collections.Generic; +using DateTime = System.DateTime; namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Models { - public class OrderData - { - public string OrderNumber { get; set; } - public DateTime Date { get; set; } - public string Status { get; set; } - public decimal Total { get; set; } - public string Description { get; set; } - public string City { get; set; } - public string Street { get; set; } - public string State { get; set; } - public string Country { get; set; } - public string ZipCode { get; set; } - public string CardNumber { get; set; } - public string CardHolderName { get; set; } - public bool IsDraft { get; set; } - public DateTime CardExpiration { get; set; } - public string CardExpirationShort { get; set; } - public string CardSecurityNumber { get; set; } + public class OrderData + { + public string OrderNumber { get; set; } + public DateTime Date { get; set; } + public string Status { get; set; } + public decimal Total { get; set; } + public string Description { get; set; } + public string City { get; set; } + public string Street { get; set; } + public string State { get; set; } + public string Country { get; set; } + public string ZipCode { get; set; } + public string CardNumber { get; set; } + public string CardHolderName { get; set; } + public bool IsDraft { get; set; } + public DateTime CardExpiration { get; set; } + public string CardExpirationShort { get; set; } + public string CardSecurityNumber { get; set; } - public int CardTypeId { get; set; } + public int CardTypeId { get; set; } - public string Buyer { get; set; } + public string Buyer { get; set; } - public List OrderItems { get; } = new List(); - } + public IList OrderItems { get; } = new List(); + } } diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/OrderItemData.cs b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/OrderItemData.cs index b0179e470..82be819f6 100644 --- a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/OrderItemData.cs +++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/OrderItemData.cs @@ -1,17 +1,12 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; - -namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Models +namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Models { - public class OrderItemData - { - public int ProductId { get; set; } - public string ProductName { get; set; } - public decimal UnitPrice { get; set; } - public decimal Discount { get; set; } - public int Units { get; set; } - public string PictureUrl { get; set; } - } + public class OrderItemData + { + public int ProductId { get; set; } + public string ProductName { get; set; } + public decimal UnitPrice { get; set; } + public decimal Discount { get; set; } + public int Units { get; set; } + public string PictureUrl { get; set; } + } } diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/UpdateBasketItemsRequest.cs b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/UpdateBasketItemsRequest.cs index 43cc81b89..4eeaf7898 100644 --- a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/UpdateBasketItemsRequest.cs +++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/UpdateBasketItemsRequest.cs @@ -1,31 +1,28 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; +using System.Collections.Generic; namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Models { - public class UpdateBasketItemsRequest - { - - public string BasketId { get; set; } + public class UpdateBasketItemsRequest + { - public ICollection Updates { get; set; } + public string BasketId { get; set; } - public UpdateBasketItemsRequest() - { - Updates = new List(); - } - } + public ICollection Updates { get; set; } - public class UpdateBasketItemData - { - public string BasketItemId { get; set; } - public int NewQty { get; set; } + public UpdateBasketItemsRequest() + { + Updates = new List(); + } + } - public UpdateBasketItemData() - { - NewQty = 0; - } - } + public class UpdateBasketItemData + { + public string BasketItemId { get; set; } + public int NewQty { get; set; } + + public UpdateBasketItemData() + { + NewQty = 0; + } + } } diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/UpdateBasketRequest.cs b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/UpdateBasketRequest.cs index cb22bf55f..0933b6eac 100644 --- a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/UpdateBasketRequest.cs +++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/UpdateBasketRequest.cs @@ -1,21 +1,18 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; +using System.Collections.Generic; namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Models { - public class UpdateBasketRequest - { - public string BuyerId { get; set; } + public class UpdateBasketRequest + { + public string BuyerId { get; set; } - public IEnumerable Items { get; set; } - } + public IEnumerable Items { get; set; } + } - public class UpdateBasketRequestItemData - { - public string Id { get; set; } // Basket id - public int ProductId { get; set; } // Catalog item id - public int Quantity { get; set; } // Quantity - } + public class UpdateBasketRequestItemData + { + public string Id { get; set; } // Basket id + public int ProductId { get; set; } // Catalog item id + public int Quantity { get; set; } // Quantity + } } diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Program.cs b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Program.cs index 0c88fcd7d..5b70e1781 100644 --- a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Program.cs +++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Program.cs @@ -1,36 +1,31 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Threading.Tasks; -using Microsoft.AspNetCore; -using Microsoft.AspNetCore.Hosting; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.Logging; +using static Microsoft.AspNetCore.Hosting.WebHostBuilderExtensions; +using static Microsoft.AspNetCore.Hosting.WebHostExtensions; +using IWebHost = Microsoft.AspNetCore.Hosting.IWebHost; +using WebHost = Microsoft.AspNetCore.WebHost; namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator { - public class Program - { - public static void Main(string[] args) - { - BuildWebHost(args).Run(); - } + public class Program + { + public static void Main(string[] args) + { + BuildWebHost(args).Run(); + } - public static IWebHost BuildWebHost(string[] args) => - WebHost - .CreateDefaultBuilder(args) - .ConfigureAppConfiguration(cb => - { - var sources = cb.Sources; - sources.Insert(3, new Microsoft.Extensions.Configuration.Json.JsonConfigurationSource() - { - Optional = true, - Path = "appsettings.localhost.json", - ReloadOnChange = false - }); - }) - .UseStartup() - .Build(); - } + public static IWebHost BuildWebHost(string[] args) => + WebHost + .CreateDefaultBuilder(args) + .ConfigureAppConfiguration(cb => + { + var sources = cb.Sources; + sources.Insert(3, new Extensions.Configuration.Json.JsonConfigurationSource() + { + Optional = true, + Path = "appsettings.localhost.json", + ReloadOnChange = false + }); + }) + .UseStartup() + .Build(); + } } diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Services/BasketService.cs b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Services/BasketService.cs index 8339ee44b..dbef73c9c 100644 --- a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Services/BasketService.cs +++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Services/BasketService.cs @@ -1,41 +1,45 @@ -using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Config; -using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Models; -using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; -using Newtonsoft.Json; -using System.Net.Http; using System.Threading.Tasks; +using Encoding = System.Text.Encoding; +using HttpClient = System.Net.Http.HttpClient; +using JsonConvert = Newtonsoft.Json.JsonConvert; +using StringContent = System.Net.Http.StringContent; namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Services { - public class BasketService : IBasketService - { + using BasketData = Models.BasketData; + using BasketOperations = Config.UrlsConfig.BasketOperations; + using UrlsConfig = Config.UrlsConfig; - private readonly HttpClient _httpClient; - private readonly ILogger _logger; - private readonly UrlsConfig _urls; + public class BasketService : IBasketService + { - public BasketService(HttpClient httpClient, ILogger logger, IOptions config) - { - _httpClient = httpClient; - _logger = logger; - _urls = config.Value; - } + private readonly HttpClient _httpClient; + private readonly ILogger _logger; + private readonly UrlsConfig _urls; - public async Task GetById(string id) - { - var data = await _httpClient.GetStringAsync(_urls.Basket + UrlsConfig.BasketOperations.GetItemById(id)); + public BasketService(HttpClient httpClient, ILogger logger, IOptions config) + { + _httpClient = httpClient; + _logger = logger; + _urls = config.Value; + } - var basket = !string.IsNullOrEmpty(data) ? JsonConvert.DeserializeObject(data) : null; + public async Task GetById(string id) + { + var data = await _httpClient.GetStringAsync(_urls.Basket + BasketOperations.GetItemById(id)); - return basket; - } + var basket = !string.IsNullOrEmpty(data) ? JsonConvert.DeserializeObject(data) : null; - public async Task Update(BasketData currentBasket) - { - var basketContent = new StringContent(JsonConvert.SerializeObject(currentBasket), System.Text.Encoding.UTF8, "application/json"); + return basket; + } - var data = await _httpClient.PostAsync(_urls.Basket + UrlsConfig.BasketOperations.UpdateBasket(), basketContent); - } - } + public async Task Update(BasketData currentBasket) + { + var basketContent = new StringContent(JsonConvert.SerializeObject(currentBasket), Encoding.UTF8, "application/json"); + + var data = await _httpClient.PostAsync(_urls.Basket + BasketOperations.UpdateBasket(), basketContent); + } + } } diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Services/CatalogService.cs b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Services/CatalogService.cs index 6c59f0c49..c7099825e 100644 --- a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Services/CatalogService.cs +++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Services/CatalogService.cs @@ -1,41 +1,43 @@ -using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Config; -using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Models; -using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; -using Newtonsoft.Json; using System.Collections.Generic; -using System.Net.Http; using System.Threading.Tasks; +using HttpClient = System.Net.Http.HttpClient; +using JsonConvert = Newtonsoft.Json.JsonConvert; namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Services { - public class CatalogService : ICatalogService - { - private readonly HttpClient _httpClient; - private readonly ILogger _logger; - private readonly UrlsConfig _urls; + using CatalogItem = Models.CatalogItem; + using CatalogOperations = Config.UrlsConfig.CatalogOperations; + using UrlsConfig = Config.UrlsConfig; - public CatalogService(HttpClient httpClient, ILogger logger, IOptions config) - { - _httpClient = httpClient; - _logger = logger; - _urls = config.Value; - } + public class CatalogService : ICatalogService + { + private readonly HttpClient _httpClient; + private readonly ILogger _logger; + private readonly UrlsConfig _urls; - public async Task GetCatalogItem(int id) - { - var stringContent = await _httpClient.GetStringAsync(_urls.Catalog + UrlsConfig.CatalogOperations.GetItemById(id)); - var catalogItem = JsonConvert.DeserializeObject(stringContent); + public CatalogService(HttpClient httpClient, ILogger logger, IOptions config) + { + _httpClient = httpClient; + _logger = logger; + _urls = config.Value; + } - return catalogItem; - } + public async Task GetCatalogItem(int id) + { + var stringContent = await _httpClient.GetStringAsync(_urls.Catalog + CatalogOperations.GetItemById(id)); + var catalogItem = JsonConvert.DeserializeObject(stringContent); - public async Task> GetCatalogItems(IEnumerable ids) - { - var stringContent = await _httpClient.GetStringAsync(_urls.Catalog + UrlsConfig.CatalogOperations.GetItemsById(ids)); - var catalogItems = JsonConvert.DeserializeObject(stringContent); + return catalogItem; + } - return catalogItems; - } - } + public async Task> GetCatalogItems(IEnumerable ids) + { + var stringContent = await _httpClient.GetStringAsync(_urls.Catalog + CatalogOperations.GetItemsById(ids)); + var catalogItems = JsonConvert.DeserializeObject(stringContent); + + return catalogItems; + } + } } diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Services/IBasketService.cs b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Services/IBasketService.cs index 6fd6871c1..deff79a0f 100644 --- a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Services/IBasketService.cs +++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Services/IBasketService.cs @@ -1,15 +1,13 @@ -using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Models; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; +using System.Threading.Tasks; namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Services { - public interface IBasketService - { - Task GetById(string id); - Task Update(BasketData currentBasket); + using BasketData = Models.BasketData; - } + public interface IBasketService + { + Task GetById(string id); + Task Update(BasketData currentBasket); + + } } diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Services/ICatalogService.cs b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Services/ICatalogService.cs index d7e605bfa..fdfe10248 100644 --- a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Services/ICatalogService.cs +++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Services/ICatalogService.cs @@ -1,14 +1,13 @@ -using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Models; -using System; -using System.Collections.Generic; -using System.Linq; +using System.Collections.Generic; using System.Threading.Tasks; namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Services { - public interface ICatalogService - { - Task GetCatalogItem(int id); - Task> GetCatalogItems(IEnumerable ids); - } + using CatalogItem = Models.CatalogItem; + + public interface ICatalogService + { + Task GetCatalogItem(int id); + Task> GetCatalogItems(IEnumerable ids); + } } diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Services/IOrderApiClient.cs b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Services/IOrderApiClient.cs index 30ac013b9..ea4c9ed22 100644 --- a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Services/IOrderApiClient.cs +++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Services/IOrderApiClient.cs @@ -1,13 +1,12 @@ -using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Models; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; +using System.Threading.Tasks; namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Services { - public interface IOrderApiClient - { - Task GetOrderDraftFromBasket(BasketData basket); - } + using BasketData = Models.BasketData; + using OrderData = Models.OrderData; + + public interface IOrderApiClient + { + Task GetOrderDraftFromBasket(BasketData basket); + } } diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Services/OrderApiClient.cs b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Services/OrderApiClient.cs index 03644c110..31f1794e4 100644 --- a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Services/OrderApiClient.cs +++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Services/OrderApiClient.cs @@ -1,37 +1,42 @@ -using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Config; -using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Models; -using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; -using Newtonsoft.Json; -using System.Net.Http; using System.Threading.Tasks; +using Encoding = System.Text.Encoding; +using HttpClient = System.Net.Http.HttpClient; +using JsonConvert = Newtonsoft.Json.JsonConvert; +using StringContent = System.Net.Http.StringContent; namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Services { - public class OrderApiClient : IOrderApiClient - { - private readonly HttpClient _apiClient; - private readonly ILogger _logger; - private readonly UrlsConfig _urls; + using BasketData = Models.BasketData; + using OrdersOperations = Config.UrlsConfig.OrdersOperations; + using OrderData = Models.OrderData; + using UrlsConfig = Config.UrlsConfig; - public OrderApiClient(HttpClient httpClient, ILogger logger, IOptions config) - { - _apiClient = httpClient; - _logger = logger; - _urls = config.Value; - } + public class OrderApiClient : IOrderApiClient + { + private readonly HttpClient _apiClient; + private readonly ILogger _logger; + private readonly UrlsConfig _urls; - public async Task GetOrderDraftFromBasket(BasketData basket) - { - var uri = _urls.Orders + UrlsConfig.OrdersOperations.GetOrderDraft(); - var content = new StringContent(JsonConvert.SerializeObject(basket), System.Text.Encoding.UTF8, "application/json"); - var response = await _apiClient.PostAsync(uri, content); + public OrderApiClient(HttpClient httpClient, ILogger logger, IOptions config) + { + _apiClient = httpClient; + _logger = logger; + _urls = config.Value; + } - response.EnsureSuccessStatusCode(); + public async Task GetOrderDraftFromBasket(BasketData basket) + { + var uri = _urls.Orders + OrdersOperations.GetOrderDraft(); + var content = new StringContent(JsonConvert.SerializeObject(basket), Encoding.UTF8, "application/json"); + var response = await _apiClient.PostAsync(uri, content); - var ordersDraftResponse = await response.Content.ReadAsStringAsync(); + response.EnsureSuccessStatusCode(); - return JsonConvert.DeserializeObject(ordersDraftResponse); - } - } + var ordersDraftResponse = await response.Content.ReadAsStringAsync(); + + return JsonConvert.DeserializeObject(ordersDraftResponse); + } + } } diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Startup.cs b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Startup.cs index 1d24e8312..f3bad7e5f 100644 --- a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Startup.cs +++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Startup.cs @@ -19,166 +19,168 @@ using System.Net.Http; namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator { - public class Startup - { - public Startup(IConfiguration configuration) - { - Configuration = configuration; - } - - public IConfiguration Configuration { get; } - - // This method gets called by the runtime. Use this method to add services to the container. - public void ConfigureServices(IServiceCollection services) - { - services.AddCustomMvc(Configuration) - .AddCustomAuthentication(Configuration) - .AddHttpServices(); - } - - // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. - public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) - { - var pathBase = Configuration["PATH_BASE"]; - - if (!string.IsNullOrEmpty(pathBase)) - { - loggerFactory.CreateLogger("init").LogDebug($"Using PATH BASE '{pathBase}'"); - app.UsePathBase(pathBase); - } - - app.UseCors("CorsPolicy"); - - if (env.IsDevelopment()) - { - app.UseDeveloperExceptionPage(); - } - - app.UseAuthentication(); - - app.UseMvc(); - - app.UseSwagger().UseSwaggerUI(c => - { - c.SwaggerEndpoint($"{ (!string.IsNullOrEmpty(pathBase) ? pathBase : string.Empty) }/swagger/v1/swagger.json", "Purchase BFF V1"); - c.ConfigureOAuth2("Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregatorwaggerui", "", "", "Purchase BFF Swagger UI"); - }); - } - } - - public static class ServiceCollectionExtensions - { - public static IServiceCollection AddCustomMvc(this IServiceCollection services, IConfiguration configuration) - { - services.AddOptions(); - services.Configure(configuration.GetSection("urls")); - - services.AddMvc(); - - services.AddSwaggerGen(options => - { - options.DescribeAllEnumsAsStrings(); - options.SwaggerDoc("v1", new Swashbuckle.AspNetCore.Swagger.Info - { - Title = "Shopping Aggregator for Mobile Clients", - Version = "v1", - Description = "Shopping Aggregator for Mobile Clients", - TermsOfService = "Terms Of Service" - }); - - options.AddSecurityDefinition("oauth2", new OAuth2Scheme - { - Type = "oauth2", - Flow = "implicit", - AuthorizationUrl = $"{configuration.GetValue("IdentityUrlExternal")}/connect/authorize", - TokenUrl = $"{configuration.GetValue("IdentityUrlExternal")}/connect/token", - Scopes = new Dictionary() - { - { "mobileshoppingagg", "Shopping Aggregator for Mobile Clients" } - } - }); - - options.OperationFilter(); - }); - - services.AddCors(options => - { - options.AddPolicy("CorsPolicy", - builder => builder.AllowAnyOrigin() - .AllowAnyMethod() - .AllowAnyHeader() - .AllowCredentials()); - }); - - return services; - } - public static IServiceCollection AddCustomAuthentication(this IServiceCollection services, IConfiguration configuration) - { - JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear(); - var identityUrl = configuration.GetValue("urls:identity"); - services.AddAuthentication(options => - { - options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; - options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; - - }).AddJwtBearer(options => - { - options.Authority = identityUrl; - options.RequireHttpsMetadata = false; - options.Audience = "mobileshoppingagg"; - options.Events = new JwtBearerEvents() - { - OnAuthenticationFailed = async ctx => - { - int i = 0; - }, - OnTokenValidated = async ctx => - { - int i = 0; - } - }; - }); - - return services; - } - public static IServiceCollection AddHttpServices(this IServiceCollection services) - { - //register delegating handlers - services.AddTransient(); - services.AddSingleton(); - - //register http services - services.AddHttpClient() - .AddHttpMessageHandler() - .AddPolicyHandler(GetRetryPolicy()) - .AddPolicyHandler(GetCircuitBreakerPolicy()); - - services.AddHttpClient() - .AddPolicyHandler(GetRetryPolicy()) - .AddPolicyHandler(GetCircuitBreakerPolicy()); - - services.AddHttpClient() - .AddPolicyHandler(GetRetryPolicy()) - .AddPolicyHandler(GetCircuitBreakerPolicy()); - - - - return services; - } - - static IAsyncPolicy GetRetryPolicy() - { - return HttpPolicyExtensions - .HandleTransientHttpError() - .OrResult(msg => msg.StatusCode == System.Net.HttpStatusCode.NotFound) - .WaitAndRetryAsync(6, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt))); - - } - static IAsyncPolicy GetCircuitBreakerPolicy() - { - return HttpPolicyExtensions - .HandleTransientHttpError() - .CircuitBreakerAsync(5, TimeSpan.FromSeconds(30)); - } - } + public class Startup + { + public Startup(IConfiguration configuration) + { + Configuration = configuration; + } + + public IConfiguration Configuration { get; } + + // This method gets called by the runtime. Use this method to add services to the container. + public void ConfigureServices(IServiceCollection services) + { + services + .AddCustomMvc(Configuration) + .AddCustomAuthentication(Configuration) + .AddHttpServices(); + } + + // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. + public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) + { + var pathBase = Configuration["PATH_BASE"]; + + if (!string.IsNullOrEmpty(pathBase)) + { + loggerFactory.CreateLogger("init").LogDebug($"Using PATH BASE '{pathBase}'"); + app.UsePathBase(pathBase); + } + + app.UseCors("CorsPolicy"); + + if (env.IsDevelopment()) + { + app.UseDeveloperExceptionPage(); + } + + app.UseAuthentication(); + + app.UseMvc(); + + app.UseSwagger().UseSwaggerUI(c => + { + c.SwaggerEndpoint($"{ (!string.IsNullOrEmpty(pathBase) ? pathBase : string.Empty) }/swagger/v1/swagger.json", "Purchase BFF V1"); + c.ConfigureOAuth2("Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregatorwaggerui", "", "", "Purchase BFF Swagger UI"); + }); + } + } + + public static class ServiceCollectionExtensions + { + public static IServiceCollection AddCustomMvc(this IServiceCollection services, IConfiguration configuration) + { + services.AddOptions(); + services.Configure(configuration.GetSection("urls")); + + services.AddMvc(); + + services.AddSwaggerGen(options => + { + options.DescribeAllEnumsAsStrings(); + options.SwaggerDoc("v1", new Swashbuckle.AspNetCore.Swagger.Info + { + Title = "Shopping Aggregator for Mobile Clients", + Version = "v1", + Description = "Shopping Aggregator for Mobile Clients", + TermsOfService = "Terms Of Service" + }); + + options.AddSecurityDefinition("oauth2", new OAuth2Scheme + { + Type = "oauth2", + Flow = "implicit", + AuthorizationUrl = $"{configuration.GetValue("IdentityUrlExternal")}/connect/authorize", + TokenUrl = $"{configuration.GetValue("IdentityUrlExternal")}/connect/token", + Scopes = new Dictionary() + { + { "mobileshoppingagg", "Shopping Aggregator for Mobile Clients" } + } + }); + + options.OperationFilter(); + }); + + services.AddCors(options => + { + options.AddPolicy("CorsPolicy", + builder => builder.AllowAnyOrigin() + .AllowAnyMethod() + .AllowAnyHeader() + .AllowCredentials()); + }); + + return services; + } + public static IServiceCollection AddCustomAuthentication(this IServiceCollection services, IConfiguration configuration) + { + JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear(); + var identityUrl = configuration.GetValue("urls:identity"); + services + .AddAuthentication(options => + { + options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; + options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; + + }) + .AddJwtBearer(options => + { + options.Authority = identityUrl; + options.RequireHttpsMetadata = false; + options.Audience = "mobileshoppingagg"; + options.Events = new JwtBearerEvents() + { +#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously + OnAuthenticationFailed = async ctx => +#pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously + { + }, +#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously + OnTokenValidated = async ctx => +#pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously + { + } + }; + }); + + return services; + } + public static IServiceCollection AddHttpServices(this IServiceCollection services) + { + //register delegating handlers + services.AddTransient(); + services.AddSingleton(); + + //register http services + services.AddHttpClient() + .AddHttpMessageHandler() + .AddPolicyHandler(GetRetryPolicy()) + .AddPolicyHandler(GetCircuitBreakerPolicy()); + + services + .AddHttpClient() + .AddPolicyHandler(GetRetryPolicy()) + .AddPolicyHandler(GetCircuitBreakerPolicy()); + + services + .AddHttpClient() + .AddPolicyHandler(GetRetryPolicy()) + .AddPolicyHandler(GetCircuitBreakerPolicy()); + + + + return services; + } + + static IAsyncPolicy GetRetryPolicy() + => HttpPolicyExtensions + .HandleTransientHttpError() + .OrResult(msg => msg.StatusCode == System.Net.HttpStatusCode.NotFound) + .WaitAndRetryAsync(6, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt))); + static IAsyncPolicy GetCircuitBreakerPolicy() + => HttpPolicyExtensions + .HandleTransientHttpError() + .CircuitBreakerAsync(5, TimeSpan.FromSeconds(30)); + } } diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/appsettings.json b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/appsettings.json index 26bb0ac7a..b0274ef44 100644 --- a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/appsettings.json +++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/appsettings.json @@ -1,15 +1,15 @@ { - "Logging": { - "IncludeScopes": false, - "Debug": { - "LogLevel": { - "Default": "Warning" - } - }, - "Console": { - "LogLevel": { - "Default": "Warning" - } - } - } + "Logging": { + "IncludeScopes": false, + "Debug": { + "LogLevel": { + "Default": "Warning" + } + }, + "Console": { + "LogLevel": { + "Default": "Warning" + } + } + } } diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/appsettings.localhost.json b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/appsettings.localhost.json index 57b5e894d..c42a22886 100644 --- a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/appsettings.localhost.json +++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/appsettings.localhost.json @@ -1,8 +1,8 @@ { - "urls": { - "basket": "http://localhost:55105", - "catalog": "http://localhost:55101", - "orders": "http://localhost:55102", - "identity": "http://localhost:55105" - } + "urls": { + "basket": "http://localhost:55105", + "catalog": "http://localhost:55101", + "orders": "http://localhost:55102", + "identity": "http://localhost:55105" + } }