Browse Source

Moved "AddItemToBasket" from MVC Client to a single call in PurchaseBFF

pull/565/head^2
Eduard Tomàs 7 years ago
parent
commit
1c6431d503
23 changed files with 106 additions and 76 deletions
  1. +1
    -0
      docker-compose.override.yml
  2. +2
    -2
      src/Apigw/OcelotApiGw/Properties/launchSettings.json
  3. +9
    -0
      src/Apigw/OcelotApiGw/Startup.cs
  4. +13
    -1
      src/Apigw/OcelotApiGw/configuration/configuration.json
  5. +1
    -0
      src/BFFs/PurchaseBff/Config/UrlsConfig.cs
  6. +4
    -3
      src/BFFs/PurchaseBff/Controllers/BasketController.cs
  7. +21
    -2
      src/BFFs/PurchaseBff/Services/BasketService.cs
  8. +1
    -0
      src/BFFs/PurchaseBff/Services/IBasketService.cs
  9. +6
    -0
      src/BFFs/PurchaseBff/Startup.cs
  10. +1
    -1
      src/Services/Basket/Basket.API/Properties/launchSettings.json
  11. +1
    -1
      src/Services/Catalog/Catalog.API/Properties/launchSettings.json
  12. +3
    -3
      src/Services/Location/Locations.API/Properties/launchSettings.json
  13. +2
    -0
      src/Web/WebMVC/AppSettings.cs
  14. +3
    -11
      src/Web/WebMVC/Controllers/CartController.cs
  15. +11
    -20
      src/Web/WebMVC/Infrastructure/API.cs
  16. +18
    -16
      src/Web/WebMVC/Services/BasketService.cs
  17. +1
    -1
      src/Web/WebMVC/Services/IBasketService.cs
  18. +1
    -0
      src/Web/WebMVC/Startup.cs
  19. +1
    -1
      src/Web/WebMVC/ViewModels/CatalogItem.cs
  20. +0
    -8
      src/Web/WebMVC/Views/Catalog/_product.cshtml
  21. +1
    -1
      src/Web/WebSPA/Properties/launchSettings.json
  22. +2
    -2
      test/Services/UnitTest/Basket/Application/CartControllerTest.cs
  23. +3
    -3
      test/Services/UnitTest/Catalog/Application/CatalogControllerTest.cs

+ 1
- 0
docker-compose.override.yml View File

@ -137,6 +137,7 @@ services:
- CatalogUrl=http://catalog.api
- OrderingUrl=http://ordering.api
- BasketUrl=http://basket.api
- PurchaseUrl=http://apigw/purchase-bff
- LocationsUrl=http://locations.api
- IdentityUrl=http://10.0.75.1:5105 # Local Mac: Use http://docker.for.mac.localhost:5105 || Local Windows: Use 10.0.75.1 in a "Docker for Windows" environment, if using "localhost" from browser. || #Remote access: Use ${ESHOP_EXTERNAL_DNS_NAME_OR_IP} if using external IP or DNS name from browser.
- MarketingUrl=http://marketing.api


+ 2
- 2
src/Apigw/OcelotApiGw/Properties/launchSettings.json View File

@ -3,7 +3,7 @@
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:64020/",
"applicationUrl": "http://localhost:56755/",
"sslPort": 0
}
},
@ -24,4 +24,4 @@
"applicationUrl": "http://localhost:64021/"
}
}
}
}

+ 9
- 0
src/Apigw/OcelotApiGw/Startup.cs View File

@ -41,6 +41,15 @@ namespace OcelotApiGw
x.Events = new Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerEvents()
{
OnAuthenticationFailed = async ctx =>
{
int i = 0;
},
OnTokenValidated = async ctx =>
{
int i = 0;
},
OnMessageReceived = async ctx =>
{
int i = 0;
}


+ 13
- 1
src/Apigw/OcelotApiGw/configuration/configuration.json View File

@ -8,13 +8,25 @@
"UpstreamPathTemplate": "/purchase-bff/catalog/{everything}",
"UpstreamHttpMethod": [ "GET" ]
},
{
"DownstreamPathTemplate": "/{everything}",
"DownstreamScheme": "http",
"DownstreamHost": "basket.api",
"DownstreamPort": 80,
"UpstreamPathTemplate": "/purchase-bff/basket/{everything}",
"UpstreamHttpMethod": [ "GET" ],
"AuthenticationOptions": {
"AuthenticationProviderKey": "IdentityApiKey",
"AllowedScopes": []
}
},
{
"DownstreamPathTemplate": "/{everything}",
"DownstreamScheme": "http",
"DownstreamHost": "purchasebff",
"DownstreamPort": 80,
"UpstreamPathTemplate": "/purchase-bff/{everything}",
"UpstreamHttpMethod": [],
"UpstreamHttpMethod": ["POST"],
"AuthenticationOptions": {
"AuthenticationProviderKey": "IdentityApiKey",
"AllowedScopes": []


+ 1
- 0
src/BFFs/PurchaseBff/Config/UrlsConfig.cs View File

@ -15,6 +15,7 @@ namespace PurchaseBff.Config
public class BasketOperations
{
public static string GetItemById(string id) => $"/api/v1/basket/{id}";
public static string UpdateBasket() => $"/api/v1/basket";
}
public string Basket { get; set; }


+ 4
- 3
src/BFFs/PurchaseBff/Controllers/BasketController.cs View File

@ -32,20 +32,21 @@ namespace PurchaseBff.Controllers
// Step 1: Get the item from catalog
var item = await _catalog.GetCatalogItem(data.CatalogItemId);
// Step 2: Get current basket status
var currentBasket = await _basket.GetById(data.BasketId);
var currentBasket = (await _basket.GetById(data.BasketId)) ?? new BasketData(data.BasketId);
// Step 3: Merge current status with new product
currentBasket.Items.Add(new BasketDataItem()
{
OldUnitPrice = item.Price,
UnitPrice = item.Price,
PictureUrl = item.PictureUri,
ProductId = item.Id.ToString(),
ProductName = item.Name,
Quantity = data.Quantity,
Id = item.Id.ToString()
Id = Guid.NewGuid().ToString()
});
// Step 4: Update basket
await _basket.Update(currentBasket);
return Ok();
}


+ 21
- 2
src/BFFs/PurchaseBff/Services/BasketService.cs View File

@ -2,6 +2,8 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Http;
using Microsoft.eShopOnContainers.BuildingBlocks.Resilience.Http;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
@ -17,18 +19,35 @@ namespace PurchaseBff.Services
private readonly IHttpClient _apiClient;
private readonly ILogger<BasketService> _logger;
private readonly UrlsConfig _urls;
public BasketService(IHttpClient httpClient, ILogger<BasketService> logger, IOptionsSnapshot<UrlsConfig> config)
private readonly IHttpContextAccessor _httpContextAccessor;
public BasketService(IHttpClient httpClient, IHttpContextAccessor httpContextAccessor, ILogger<BasketService> logger, IOptionsSnapshot<UrlsConfig> config)
{
_apiClient = httpClient;
_logger = logger;
_urls = config.Value;
_httpContextAccessor = httpContextAccessor;
}
public async Task<BasketData> GetById(string id)
{
var data = await _apiClient.GetStringAsync(_urls.Basket + UrlsConfig.BasketOperations.GetItemById(id));
var token = await GetUserTokenAsync();
var data = await _apiClient.GetStringAsync(_urls.Basket + UrlsConfig.BasketOperations.GetItemById(id), token);
var basket = JsonConvert.DeserializeObject<BasketData>(data);
return basket;
}
public async Task Update(BasketData currentBasket)
{
var token = await GetUserTokenAsync();
var data = await _apiClient.PostAsync<BasketData>(_urls.Basket + UrlsConfig.BasketOperations.UpdateBasket(), currentBasket, token);
int i = 0;
}
async Task<string> GetUserTokenAsync()
{
var context = _httpContextAccessor.HttpContext;
return await context.GetTokenAsync("access_token");
}
}
}

+ 1
- 0
src/BFFs/PurchaseBff/Services/IBasketService.cs View File

@ -9,5 +9,6 @@ namespace PurchaseBff.Services
public interface IBasketService
{
Task<BasketData> GetById(string id);
Task Update(BasketData currentBasket);
}
}

+ 6
- 0
src/BFFs/PurchaseBff/Startup.cs View File

@ -92,6 +92,10 @@ namespace PurchaseBff
options.Events = new JwtBearerEvents()
{
OnAuthenticationFailed = async ctx =>
{
int i = 0;
},
OnTokenValidated = async ctx =>
{
int i = 0;
}
@ -117,6 +121,8 @@ namespace PurchaseBff
app.UseDeveloperExceptionPage();
}
app.UseAuthentication();
app.UseMvc();
app.UseSwagger().UseSwaggerUI(c =>


+ 1
- 1
src/Services/Basket/Basket.API/Properties/launchSettings.json View File

@ -3,7 +3,7 @@
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:51078/",
"applicationUrl": "http://localhost:56695/",
"sslPort": 0
}
},


+ 1
- 1
src/Services/Catalog/Catalog.API/Properties/launchSettings.json View File

@ -3,7 +3,7 @@
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:55101",
"applicationUrl": "http://localhost:56698/",
"sslPort": 0
}
},


+ 3
- 3
src/Services/Location/Locations.API/Properties/launchSettings.json View File

@ -1,9 +1,9 @@
{
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:3278/",
"applicationUrl": "http://localhost:53933/",
"sslPort": 0
}
},
@ -26,4 +26,4 @@
"applicationUrl": "http://localhost:3279"
}
}
}
}

+ 2
- 0
src/Web/WebMVC/AppSettings.cs View File

@ -13,6 +13,8 @@ namespace Microsoft.eShopOnContainers.WebMVC
public string BasketUrl { get; set; }
public string MarketingUrl { get; set; }
public string LocationsUrl { get; set; }
public string PurchaseUrl { get; set; }
public bool ActivateCampaignDetailFunction { get; set; }
public Logging Logging { get; set; }
public bool UseCustomizationData { get; set; }


+ 3
- 11
src/Web/WebMVC/Controllers/CartController.cs View File

@ -70,19 +70,11 @@ namespace Microsoft.eShopOnContainers.WebMVC.Controllers
{
try
{
if (productDetails.Id != null)
if (productDetails?.Id != null)
{
var user = _appUserParser.Parse(HttpContext.User);
var product = new BasketItem()
{
Id = Guid.NewGuid().ToString(),
Quantity = 1,
ProductName = productDetails.Name,
PictureUrl = productDetails.PictureUri,
UnitPrice = productDetails.Price,
ProductId = productDetails.Id
};
await _basketSvc.AddItemToBasket(user, product);
await _basketSvc.AddItemToBasket(user, productDetails.Id);
//await _basketSvc.AddItemToBasket(user, product);
}
return RedirectToAction("Index", "Catalog");
}


+ 11
- 20
src/Web/WebMVC/Infrastructure/API.cs View File

@ -4,27 +4,18 @@ namespace WebMVC.Infrastructure
{
public static class API
{
public static class Basket
{
public static string GetBasket(string baseUri, string basketId)
{
return $"{baseUri}/{basketId}";
}
public static string UpdateBasket(string baseUri)
{
return baseUri;
}
public static string CheckoutBasket(string baseUri)
{
return $"{baseUri}/checkout";
}
public static class Purchase
{
public static string AddItemToBasket(string baseUri) => $"{baseUri}/basket/items";
}
public static string CleanBasket(string baseUri, string basketId)
{
return $"{baseUri}/{basketId}";
}
public static class Basket
{
public static string GetBasket(string baseUri, string basketId) => $"{baseUri}/{basketId}";
public static string UpdateBasket(string baseUri) => baseUri;
public static string CheckoutBasket(string baseUri) => $"{baseUri}/checkout";
public static string CleanBasket(string baseUri, string basketId) => $"{baseUri}/{basketId}";
}
public static class Order
@ -100,7 +91,7 @@ namespace WebMVC.Infrastructure
public static string CreateOrUpdateUserLocation(string baseUri)
{
return baseUri;
}
}
}
}
}

+ 18
- 16
src/Web/WebMVC/Services/BasketService.cs View File

@ -14,14 +14,19 @@ namespace Microsoft.eShopOnContainers.WebMVC.Services
public class BasketService : IBasketService
{
private readonly IOptionsSnapshot<AppSettings> _settings;
private IHttpClient _apiClient;
private readonly IHttpClient _apiClient;
private readonly string _remoteServiceBaseUrl;
private IHttpContextAccessor _httpContextAccesor;
private readonly string _purchaseUrl;
private readonly IHttpContextAccessor _httpContextAccesor;
public BasketService(IOptionsSnapshot<AppSettings> settings, IHttpContextAccessor httpContextAccesor, IHttpClient httpClient)
private readonly string _bffUrl;
public BasketService(IOptionsSnapshot<AppSettings> settings,
IHttpContextAccessor httpContextAccesor, IHttpClient httpClient)
{
_settings = settings;
_remoteServiceBaseUrl = $"{_settings.Value.BasketUrl}/api/v1/basket";
_purchaseUrl = $"{_settings.Value.PurchaseUrl}/api/v1";
_httpContextAccesor = httpContextAccesor;
_apiClient = httpClient;
}
@ -104,23 +109,20 @@ namespace Microsoft.eShopOnContainers.WebMVC.Services
return order;
}
public async Task AddItemToBasket(ApplicationUser user, BasketItem product)
public async Task AddItemToBasket(ApplicationUser user, int productId)
{
var basket = await GetBasket(user);
var token = await GetUserTokenAsync();
var updateBasketUri = API.Purchase.AddItemToBasket(_purchaseUrl);
var userId = user.Id;
if (basket == null)
var response = await _apiClient.PostAsync(updateBasketUri, new
{
basket = new Basket()
{
BuyerId = user.Id,
Items = new List<BasketItem>()
};
}
basket.Items.Add(product);
CatalogItemId = productId,
BasketId = userId,
Quantity = 1
}, token);
await UpdateBasket(basket);
}
}
async Task<string> GetUserTokenAsync()
{


+ 1
- 1
src/Web/WebMVC/Services/IBasketService.cs View File

@ -10,7 +10,7 @@ namespace Microsoft.eShopOnContainers.WebMVC.Services
public interface IBasketService
{
Task<Basket> GetBasket(ApplicationUser user);
Task AddItemToBasket(ApplicationUser user, BasketItem product);
Task AddItemToBasket(ApplicationUser user, int productId);
Task<Basket> UpdateBasket(Basket basket);
Task Checkout(BasketDTO basket);
Task<Basket> SetQuantities(ApplicationUser user, Dictionary<string, int> quantities);


+ 1
- 0
src/Web/WebMVC/Startup.cs View File

@ -130,6 +130,7 @@ namespace Microsoft.eShopOnContainers.WebMVC
options.Scope.Add("basket");
options.Scope.Add("marketing");
options.Scope.Add("locations");
options.Scope.Add("purchasebff");
});
}


+ 1
- 1
src/Web/WebMVC/ViewModels/CatalogItem.cs View File

@ -4,7 +4,7 @@ namespace Microsoft.eShopOnContainers.WebMVC.ViewModels
{
public class CatalogItem
{
public string Id { get; set; }
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public decimal Price { get; set; }


+ 0
- 8
src/Web/WebMVC/Views/Catalog/_product.cshtml View File

@ -12,13 +12,5 @@
<div class="esh-catalog-price">
<span>@Model.Price.ToString("N2")</span>
</div>
<input type="hidden" asp-for="@Model.CatalogBrand" name="brand" />
<input type="hidden" asp-for="@Model.CatalogBrandId" name="brandId" />
<input type="hidden" asp-for="@Model.CatalogType" name="type" />
<input type="hidden" asp-for="@Model.CatalogTypeId" name="typeId" />
<input type="hidden" asp-for="@Model.Description" name="description" />
<input type="hidden" asp-for="@Model.Id" name="id" />
<input type="hidden" asp-for="@Model.Name" name="name" />
<input type="hidden" asp-for="@Model.PictureUri" name="pictureUri" />
<input type="hidden" asp-for="@Model.Price" name="price" />
</form>

+ 1
- 1
src/Web/WebSPA/Properties/launchSettings.json View File

@ -3,7 +3,7 @@
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:5104/",
"applicationUrl": "http://localhost:56727/",
"sslPort": 0
}
},


+ 2
- 2
test/Services/UnitTest/Basket/Application/CartControllerTest.cs View File

@ -92,7 +92,7 @@ namespace UnitTest.Basket.Application
//Arrange
var fakeCatalogItem = GetFakeCatalogItem();
_basketServiceMock.Setup(x => x.AddItemToBasket(It.IsAny<ApplicationUser>(), It.IsAny<BasketItem>()))
_basketServiceMock.Setup(x => x.AddItemToBasket(It.IsAny<ApplicationUser>(), It.IsAny<Int32>()))
.Returns(Task.FromResult(1));
//Act
@ -118,7 +118,7 @@ namespace UnitTest.Basket.Application
{
return new CatalogItem()
{
Id = "1",
Id = 1,
Name = "fakeName",
CatalogBrand = "fakeBrand",
CatalogType = "fakeType",


+ 3
- 3
test/Services/UnitTest/Catalog/Application/CatalogControllerTest.cs View File

@ -67,19 +67,19 @@ namespace UnitTest.Catalog.Application
{
new CatalogItem()
{
Id = "1",
Id = 1,
Name = "fakeItemA",
CatalogTypeId = 1
},
new CatalogItem()
{
Id = "2",
Id = 2,
Name = "fakeItemB",
CatalogTypeId = 1
},
new CatalogItem()
{
Id = "3",
Id = 3,
Name = "fakeItemC",
CatalogTypeId = 1
}


Loading…
Cancel
Save