fix grpc call from mobile bff to basket.api and add ordering, in ordering controller
This commit is contained in:
parent
016089fb5f
commit
3f61eb0ef9
@ -115,6 +115,7 @@ services:
|
|||||||
- Serilog__MinimumLevel__Override__Ordering.API=Verbose
|
- Serilog__MinimumLevel__Override__Ordering.API=Verbose
|
||||||
ports:
|
ports:
|
||||||
- "5102:80"
|
- "5102:80"
|
||||||
|
- "5581:5001"
|
||||||
|
|
||||||
ordering.backgroundtasks:
|
ordering.backgroundtasks:
|
||||||
environment:
|
environment:
|
||||||
@ -284,6 +285,8 @@ services:
|
|||||||
- urls__catalog=http://catalog.api
|
- urls__catalog=http://catalog.api
|
||||||
- urls__orders=http://ordering.api
|
- urls__orders=http://ordering.api
|
||||||
- urls__identity=http://identity.api
|
- urls__identity=http://identity.api
|
||||||
|
- urls__grpcBasket=http://10.0.75.1:5580
|
||||||
|
- urls__grpcOrdering=http://10.0.75.1:5581
|
||||||
- CatalogUrlHC=http://catalog.api/hc
|
- CatalogUrlHC=http://catalog.api/hc
|
||||||
- OrderingUrlHC=http://ordering.api/hc
|
- OrderingUrlHC=http://ordering.api/hc
|
||||||
- IdentityUrlHC=http://identity.api/hc
|
- IdentityUrlHC=http://identity.api/hc
|
||||||
@ -291,7 +294,7 @@ services:
|
|||||||
- MarketingUrlHC=http://marketing.api/hc
|
- MarketingUrlHC=http://marketing.api/hc
|
||||||
- PaymentUrlHC=http://payment.api/hc
|
- PaymentUrlHC=http://payment.api/hc
|
||||||
- LocationUrlHC=http://locations.api/hc
|
- LocationUrlHC=http://locations.api/hc
|
||||||
- IdentityUrlExternal=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5105
|
- IdentityUrlExternal=http://10.0.75.1:5105
|
||||||
ports:
|
ports:
|
||||||
- "5120:80"
|
- "5120:80"
|
||||||
|
|
||||||
|
@ -27,5 +27,7 @@ namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Config
|
|||||||
public string Basket { get; set; }
|
public string Basket { get; set; }
|
||||||
public string Catalog { get; set; }
|
public string Catalog { get; set; }
|
||||||
public string Orders { get; set; }
|
public string Orders { get; set; }
|
||||||
|
public string GrpcBasket { get; set; }
|
||||||
|
public string GrpcOrdering { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,12 +13,12 @@ namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Controllers
|
|||||||
public class OrderController : ControllerBase
|
public class OrderController : ControllerBase
|
||||||
{
|
{
|
||||||
private readonly IBasketService _basketService;
|
private readonly IBasketService _basketService;
|
||||||
private readonly IOrderApiClient _orderClient;
|
private readonly IOrderingService _orderingService;
|
||||||
|
|
||||||
public OrderController(IBasketService basketService, IOrderApiClient orderClient)
|
public OrderController(IBasketService basketService, IOrderingService orderingService)
|
||||||
{
|
{
|
||||||
_basketService = basketService;
|
_basketService = basketService;
|
||||||
_orderClient = orderClient;
|
_orderingService = orderingService;
|
||||||
}
|
}
|
||||||
|
|
||||||
[Route("draft/{basketId}")]
|
[Route("draft/{basketId}")]
|
||||||
@ -39,7 +39,7 @@ namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Controllers
|
|||||||
return BadRequest($"No basket found for id {basketId}");
|
return BadRequest($"No basket found for id {basketId}");
|
||||||
}
|
}
|
||||||
|
|
||||||
return await _orderClient.GetOrderDraftFromBasketAsync(basket);
|
return await _orderingService.GetOrderDraftAsync(basket);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -40,8 +40,6 @@ namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Infrastruct
|
|||||||
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token);
|
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token);
|
||||||
}
|
}
|
||||||
|
|
||||||
_logger.LogInformation("@@@@@@@@@@@@@@@@@ {@request}", request);
|
|
||||||
|
|
||||||
return await base.SendAsync(request, cancellationToken);
|
return await base.SendAsync(request, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
<PackageReference Include="Grpc.AspNetCore.Server.ClientFactory" Version="$(Grpc_AspNetCore_Server_ClientFactory)" />
|
<PackageReference Include="Grpc.AspNetCore.Server.ClientFactory" Version="$(Grpc_AspNetCore_Server_ClientFactory)" />
|
||||||
<PackageReference Include="Google.Protobuf" Version="$(Google_Protobuf)" />
|
<PackageReference Include="Google.Protobuf" Version="$(Google_Protobuf)" />
|
||||||
<PackageReference Include="Grpc.Core" Version="1.22.0" />
|
<PackageReference Include="Grpc.Core" Version="1.22.0" />
|
||||||
<PackageReference Include="Grpc.Tools" Version="$(Grpc_Tools)" PrivateAssets="All" />
|
<PackageReference Include="Grpc.Tools" Version="$(Grpc_Tools)" PrivateAssets="All" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Diagnostics.HealthChecks" Version="$(Microsoft_AspNetCore_Diagnostics_HealthChecks)" />
|
<PackageReference Include="Microsoft.AspNetCore.Diagnostics.HealthChecks" Version="$(Microsoft_AspNetCore_Diagnostics_HealthChecks)" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Diagnostics.HealthChecks" Version="$(Microsoft_Extensions_Diagnostics_HealthChecks)" />
|
<PackageReference Include="Microsoft.Extensions.Diagnostics.HealthChecks" Version="$(Microsoft_Extensions_Diagnostics_HealthChecks)" />
|
||||||
<PackageReference Include="Serilog.AspNetCore" Version="$(Serilog_AspNetCore)" />
|
<PackageReference Include="Serilog.AspNetCore" Version="$(Serilog_AspNetCore)" />
|
||||||
@ -34,10 +34,11 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\..\..\BuildingBlocks\Devspaces.Support\Devspaces.Support.csproj" />
|
<ProjectReference Include="..\..\..\BuildingBlocks\Devspaces.Support\Devspaces.Support.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Protobuf Include="..\..\..\Services\Basket\Basket.API\Proto\basket.proto" GrpcServices="Client" />
|
<Protobuf Include="..\..\..\Services\Basket\Basket.API\Proto\basket.proto" GrpcServices="Client" />
|
||||||
<Protobuf Include="..\..\..\Services\Catalog\Catalog.API\Proto\catalog.proto" GrpcServices="Client" />
|
<Protobuf Include="..\..\..\Services\Catalog\Catalog.API\Proto\catalog.proto" GrpcServices="Client" />
|
||||||
|
<Protobuf Include="..\..\..\Services\Ordering\Ordering.API\Proto\ordering.proto" GrpcServices="Client" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
@ -6,7 +6,7 @@ namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Models
|
|||||||
{
|
{
|
||||||
public string BuyerId { get; set; }
|
public string BuyerId { get; set; }
|
||||||
|
|
||||||
public List<BasketDataItem> Items { get; set; }
|
public List<BasketDataItem> Items { get; set; } = new List<BasketDataItem>();
|
||||||
|
|
||||||
public BasketData()
|
public BasketData()
|
||||||
{
|
{
|
||||||
@ -16,7 +16,6 @@ namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Models
|
|||||||
public BasketData(string buyerId)
|
public BasketData(string buyerId)
|
||||||
{
|
{
|
||||||
BuyerId = buyerId;
|
BuyerId = buyerId;
|
||||||
Items = new List<BasketDataItem>();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
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
|
||||||
{
|
{
|
||||||
@ -28,6 +26,6 @@ namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Models
|
|||||||
|
|
||||||
public string Buyer { get; set; }
|
public string Buyer { get; set; }
|
||||||
|
|
||||||
public List<OrderItemData> OrderItems { get; } = new List<OrderItemData>();
|
public List<OrderItemData> OrderItems { get; } = new List<OrderItemData>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,4 @@
|
|||||||
using System;
|
namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Models
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Models
|
|
||||||
{
|
{
|
||||||
public class OrderItemData
|
public class OrderItemData
|
||||||
{
|
{
|
||||||
|
@ -1,7 +1,4 @@
|
|||||||
using System;
|
using System.Collections.Generic;
|
||||||
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
|
||||||
{
|
{
|
||||||
|
@ -1,7 +1,4 @@
|
|||||||
using System;
|
using System.Collections.Generic;
|
||||||
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
|
||||||
{
|
{
|
||||||
|
@ -27,9 +27,6 @@ namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Services
|
|||||||
|
|
||||||
public async Task<BasketData> GetById(string id)
|
public async Task<BasketData> GetById(string id)
|
||||||
{
|
{
|
||||||
|
|
||||||
_logger.LogInformation("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ GetById @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
|
|
||||||
|
|
||||||
AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true);
|
AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true);
|
||||||
AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2Support", true);
|
AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2Support", true);
|
||||||
|
|
||||||
@ -38,24 +35,21 @@ namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Services
|
|||||||
httpClientHandler.ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => { return true; };
|
httpClientHandler.ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => { return true; };
|
||||||
using (var httpClient = new HttpClient(httpClientHandler))
|
using (var httpClient = new HttpClient(httpClientHandler))
|
||||||
{
|
{
|
||||||
_logger.LogInformation("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ Http2UnencryptedSupport disable @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
|
//httpClient.BaseAddress = new Uri("http://10.0.75.1:5580");
|
||||||
|
httpClient.BaseAddress = new Uri(_urls.GrpcBasket);
|
||||||
|
|
||||||
httpClient.BaseAddress = new Uri("http://localhost:5580");
|
_logger.LogDebug("Creating grpc client for basket {@httpClient.BaseAddress} ", httpClient.BaseAddress);
|
||||||
|
|
||||||
_logger.LogInformation("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ {httpClient.BaseAddress} @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ " + httpClient.BaseAddress, httpClient.BaseAddress);
|
|
||||||
|
|
||||||
var client = GrpcClient.Create<Basket.BasketClient>(httpClient);
|
var client = GrpcClient.Create<Basket.BasketClient>(httpClient);
|
||||||
|
|
||||||
_logger.LogInformation("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ client create @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
|
_logger.LogDebug("grpc client created, request = {@id}", id);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
||||||
var response = await client.GetBasketByIdAsync(new BasketRequest { Id = id });
|
var response = await client.GetBasketByIdAsync(new BasketRequest { Id = id });
|
||||||
_logger.LogInformation("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ call grpc server @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
|
|
||||||
|
|
||||||
_logger.LogInformation("############## DATA: {@a}", response.Buyerid);
|
_logger.LogDebug("grpc response {@response}", response);
|
||||||
_logger.LogInformation("############## DATA:response {@response}", response);
|
|
||||||
|
|
||||||
return MapToBasketData(response);
|
return MapToBasketData(response);
|
||||||
}
|
}
|
||||||
@ -66,11 +60,7 @@ namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Services
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return null; // temp
|
return null;
|
||||||
// var data = await _apiClient.GetStringAsync(_urls.Basket + UrlsConfig.BasketOperations.GetItemById(id));
|
|
||||||
// var basket = !string.IsNullOrEmpty(data) ? JsonConvert.DeserializeObject<BasketData>(data) : null;
|
|
||||||
|
|
||||||
// return basket;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task UpdateAsync(BasketData currentBasket)
|
public async Task UpdateAsync(BasketData currentBasket)
|
||||||
|
@ -0,0 +1,10 @@
|
|||||||
|
using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Models;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Services
|
||||||
|
{
|
||||||
|
public interface IOrderingService
|
||||||
|
{
|
||||||
|
Task<OrderData> GetOrderDraftAsync(BasketData basketData);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,113 @@
|
|||||||
|
using Grpc.Net.Client;
|
||||||
|
using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Config;
|
||||||
|
using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Models;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using GrpcOrdering;
|
||||||
|
using Grpc.Core;
|
||||||
|
|
||||||
|
namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Services
|
||||||
|
{
|
||||||
|
public class OrderingService : IOrderingService
|
||||||
|
{
|
||||||
|
private readonly HttpClient _httpClient;
|
||||||
|
private readonly UrlsConfig _urls;
|
||||||
|
private readonly ILogger<OrderingService> _logger;
|
||||||
|
|
||||||
|
public OrderingService(HttpClient httpClient, IOptions<UrlsConfig> config, ILogger<OrderingService> logger)
|
||||||
|
{
|
||||||
|
_httpClient = httpClient;
|
||||||
|
_urls = config.Value;
|
||||||
|
_logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<OrderData> GetOrderDraftAsync(BasketData basketData)
|
||||||
|
{
|
||||||
|
AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true);
|
||||||
|
AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2Support", true);
|
||||||
|
|
||||||
|
using (var httpClientHandler = new HttpClientHandler())
|
||||||
|
{
|
||||||
|
httpClientHandler.ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => { return true; };
|
||||||
|
using (var httpClient = new HttpClient(httpClientHandler))
|
||||||
|
{
|
||||||
|
httpClient.BaseAddress = new Uri(_urls.GrpcOrdering);
|
||||||
|
|
||||||
|
_logger.LogDebug(" Creating grpc client for ordering {@httpClient.BaseAddress}", httpClient.BaseAddress);
|
||||||
|
|
||||||
|
var client = GrpcClient.Create<OrderingGrpc.OrderingGrpcClient>(httpClient);
|
||||||
|
|
||||||
|
_logger.LogDebug(" grpc client created, basketData={@basketData}", basketData);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
|
||||||
|
var command = MapToOrderDraftCommand(basketData);
|
||||||
|
var response = await client.CreateOrderDraftFromBasketDataAsync(command);
|
||||||
|
|
||||||
|
_logger.LogDebug(" grpc response: {@response}", response);
|
||||||
|
|
||||||
|
return MapToResponse(response);
|
||||||
|
}
|
||||||
|
catch (RpcException e)
|
||||||
|
{
|
||||||
|
_logger.LogError($"Error calling via grpc to ordering: {e.Status} - {e.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private OrderData MapToResponse(GrpcOrdering.OrderDraftDTO orderDraft)
|
||||||
|
{
|
||||||
|
if (orderDraft == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var data = new OrderData
|
||||||
|
{
|
||||||
|
Total = (decimal)orderDraft.Total,
|
||||||
|
};
|
||||||
|
|
||||||
|
orderDraft.OrderItems.ToList().ForEach(o => data.OrderItems.Add(new OrderItemData
|
||||||
|
{
|
||||||
|
Discount = (decimal)o.Discount,
|
||||||
|
PictureUrl = o.PictureUrl,
|
||||||
|
ProductId = o.ProductId,
|
||||||
|
ProductName = o.ProductName,
|
||||||
|
UnitPrice = (decimal)o.UnitPrice,
|
||||||
|
Units = o.Units,
|
||||||
|
}));
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
private CreateOrderDraftCommand MapToOrderDraftCommand(BasketData basketData)
|
||||||
|
{
|
||||||
|
var command = new CreateOrderDraftCommand
|
||||||
|
{
|
||||||
|
BuyerId = basketData.BuyerId,
|
||||||
|
};
|
||||||
|
|
||||||
|
basketData.Items.ForEach(i => command.Items.Add(new BasketItem
|
||||||
|
{
|
||||||
|
Id = i.Id,
|
||||||
|
OldUnitPrice = (double)i.OldUnitPrice,
|
||||||
|
PictureUrl = i.PictureUrl,
|
||||||
|
ProductId = i.ProductId,
|
||||||
|
ProductName = i.ProductName,
|
||||||
|
Quantity = i.Quantity,
|
||||||
|
UnitPrice = (double)i.UnitPrice,
|
||||||
|
}));
|
||||||
|
|
||||||
|
return command;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -131,11 +131,9 @@ namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator
|
|||||||
{
|
{
|
||||||
Implicit = new OpenApiOAuthFlow()
|
Implicit = new OpenApiOAuthFlow()
|
||||||
{
|
{
|
||||||
// AuthorizationUrl = new Uri($"{configuration.GetValue<string>("IdentityUrlExternal")}/connect/authorize"),
|
AuthorizationUrl = new Uri($"{configuration.GetValue<string>("IdentityUrlExternal")}/connect/authorize"),
|
||||||
// TokenUrl = new Uri($"{configuration.GetValue<string>("IdentityUrlExternal")}/connect/token"),
|
TokenUrl = new Uri($"{configuration.GetValue<string>("IdentityUrlExternal")}/connect/token"),
|
||||||
|
|
||||||
AuthorizationUrl = new Uri($"http://localhost:5105/connect/authorize"),
|
|
||||||
TokenUrl = new Uri($"http://localhost:5105/connect/token"),
|
|
||||||
Scopes = new Dictionary<string, string>()
|
Scopes = new Dictionary<string, string>()
|
||||||
{
|
{
|
||||||
{ "mobileshoppingagg", "Shopping Aggregator for Mobile Clients" }
|
{ "mobileshoppingagg", "Shopping Aggregator for Mobile Clients" }
|
||||||
@ -188,7 +186,8 @@ namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator
|
|||||||
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
|
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
|
||||||
|
|
||||||
//register http services
|
//register http services
|
||||||
services.AddHttpClient<IBasketService, BasketService>()
|
services
|
||||||
|
.AddHttpClient<IBasketService, BasketService>()
|
||||||
.AddHttpMessageHandler<HttpClientAuthorizationDelegatingHandler>()
|
.AddHttpMessageHandler<HttpClientAuthorizationDelegatingHandler>()
|
||||||
.AddPolicyHandler(GetRetryPolicy())
|
.AddPolicyHandler(GetRetryPolicy())
|
||||||
.AddPolicyHandler(GetCircuitBreakerPolicy())
|
.AddPolicyHandler(GetCircuitBreakerPolicy())
|
||||||
@ -204,6 +203,11 @@ namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator
|
|||||||
.AddPolicyHandler(GetCircuitBreakerPolicy())
|
.AddPolicyHandler(GetCircuitBreakerPolicy())
|
||||||
.AddDevspacesSupport();
|
.AddDevspacesSupport();
|
||||||
|
|
||||||
|
services.AddHttpClient<IOrderingService, OrderingService>()
|
||||||
|
.AddPolicyHandler(GetRetryPolicy())
|
||||||
|
.AddPolicyHandler(GetCircuitBreakerPolicy())
|
||||||
|
.AddDevspacesSupport();
|
||||||
|
|
||||||
return services;
|
return services;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,7 +3,9 @@
|
|||||||
"basket": "http://localhost:55105",
|
"basket": "http://localhost:55105",
|
||||||
"catalog": "http://localhost:55101",
|
"catalog": "http://localhost:55101",
|
||||||
"orders": "http://localhost:55102",
|
"orders": "http://localhost:55102",
|
||||||
"identity": "http://localhost:55105"
|
"identity": "http://localhost:55105",
|
||||||
|
"grpcBasket": "http://localhost:5580",
|
||||||
|
"grpcOrdering": "http://localhost:5581"
|
||||||
},
|
},
|
||||||
"IdentityUrlExternal": "http://localhost:5105",
|
"IdentityUrlExternal": "http://localhost:5105",
|
||||||
"IdentityUrl": "http://localhost:5105",
|
"IdentityUrl": "http://localhost:5105",
|
||||||
|
92
src/Services/Ordering/Ordering.API/Grpc/OrderingService.cs
Normal file
92
src/Services/Ordering/Ordering.API/Grpc/OrderingService.cs
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands;
|
||||||
|
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Extensions;
|
||||||
|
using MediatR;
|
||||||
|
using Grpc.Core;
|
||||||
|
using AppCommand = Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands;
|
||||||
|
using ApiModels = Ordering.API.Application.Models;
|
||||||
|
using Google.Protobuf.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace GrpcOrdering
|
||||||
|
{
|
||||||
|
public class OrderingService : OrderingGrpc.OrderingGrpcBase
|
||||||
|
{
|
||||||
|
private readonly IMediator _mediator;
|
||||||
|
private readonly ILogger<OrderingService> _logger;
|
||||||
|
|
||||||
|
public OrderingService(IMediator mediator, ILogger<OrderingService> logger)
|
||||||
|
{
|
||||||
|
_mediator = mediator;
|
||||||
|
_logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task<OrderDraftDTO> CreateOrderDraftFromBasketData(CreateOrderDraftCommand createOrderDraftCommand, ServerCallContext context)
|
||||||
|
{
|
||||||
|
_logger.LogInformation($"Begin grpc call from method {context.Method} for ordering get order draft {createOrderDraftCommand}");
|
||||||
|
_logger.LogInformation(
|
||||||
|
"----- Sending command: {CommandName} - {IdProperty}: {CommandId} ({@Command})",
|
||||||
|
createOrderDraftCommand.GetGenericTypeName(),
|
||||||
|
nameof(createOrderDraftCommand.BuyerId),
|
||||||
|
createOrderDraftCommand.BuyerId,
|
||||||
|
createOrderDraftCommand);
|
||||||
|
|
||||||
|
var command = new AppCommand.CreateOrderDraftCommand(
|
||||||
|
createOrderDraftCommand.BuyerId,
|
||||||
|
this.MapBasketItems(createOrderDraftCommand.Items));
|
||||||
|
|
||||||
|
|
||||||
|
var data = await _mediator.Send(command);
|
||||||
|
|
||||||
|
if (data != null)
|
||||||
|
{
|
||||||
|
context.Status = new Status(StatusCode.OK, $" ordering get order draft {createOrderDraftCommand} do exist");
|
||||||
|
|
||||||
|
return this.MapResponse(data);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
context.Status = new Status(StatusCode.NotFound, $" ordering get order draft {createOrderDraftCommand} do not exist");
|
||||||
|
}
|
||||||
|
|
||||||
|
return new OrderDraftDTO();
|
||||||
|
}
|
||||||
|
|
||||||
|
public OrderDraftDTO MapResponse(AppCommand.OrderDraftDTO order)
|
||||||
|
{
|
||||||
|
var result = new OrderDraftDTO()
|
||||||
|
{
|
||||||
|
Total = (double)order.Total,
|
||||||
|
};
|
||||||
|
|
||||||
|
order.OrderItems.ToList().ForEach(i => result.OrderItems.Add(new OrderItemDTO()
|
||||||
|
{
|
||||||
|
Discount = (double)i.Discount,
|
||||||
|
PictureUrl = i.PictureUrl,
|
||||||
|
ProductId = i.ProductId,
|
||||||
|
ProductName = i.ProductName,
|
||||||
|
UnitPrice = (double)i.UnitPrice,
|
||||||
|
Units = i.Units,
|
||||||
|
}));
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<ApiModels.BasketItem> MapBasketItems(RepeatedField<BasketItem> items)
|
||||||
|
{
|
||||||
|
return items.Select(x => new ApiModels.BasketItem()
|
||||||
|
{
|
||||||
|
Id = x.Id,
|
||||||
|
ProductId = x.ProductId,
|
||||||
|
ProductName = x.ProductName,
|
||||||
|
UnitPrice = (decimal)x.UnitPrice,
|
||||||
|
OldUnitPrice = (decimal)x.OldUnitPrice,
|
||||||
|
Quantity = x.Quantity,
|
||||||
|
PictureUrl = x.PictureUrl,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -19,6 +19,13 @@
|
|||||||
</Content>
|
</Content>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Protobuf Include="Proto\ordering.proto" GrpcServices="Server" Generator="MSBuild:Compile" />
|
||||||
|
<Content Include="Proto\ordering.proto" />
|
||||||
|
<None Remove="@(Protobuf)" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\..\..\BuildingBlocks\EventBus\EventBusRabbitMQ\EventBusRabbitMQ.csproj" />
|
<ProjectReference Include="..\..\..\BuildingBlocks\EventBus\EventBusRabbitMQ\EventBusRabbitMQ.csproj" />
|
||||||
<ProjectReference Include="..\..\..\BuildingBlocks\EventBus\EventBusServiceBus\EventBusServiceBus.csproj" />
|
<ProjectReference Include="..\..\..\BuildingBlocks\EventBus\EventBusServiceBus\EventBusServiceBus.csproj" />
|
||||||
@ -30,7 +37,10 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="$(Microsoft_AspNetCore_Mvc_NewtonsoftJson)"/>
|
<PackageReference Include="Grpc.AspNetCore.Server" Version="$(Grpc_AspNetCore_Server)" />
|
||||||
|
<PackageReference Include="Google.Protobuf" Version="$(Google_Protobuf)" />
|
||||||
|
<PackageReference Include="Grpc.Tools" Version="$(Grpc_Tools)" PrivateAssets="All" />
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="$(Microsoft_AspNetCore_Mvc_NewtonsoftJson)" />
|
||||||
<PackageReference Include="AspNetCore.HealthChecks.AzureServiceBus" Version="$(AspNetCore_HealthChecks_AzureServiceBus)" />
|
<PackageReference Include="AspNetCore.HealthChecks.AzureServiceBus" Version="$(AspNetCore_HealthChecks_AzureServiceBus)" />
|
||||||
<PackageReference Include="AspNetCore.HealthChecks.Rabbitmq" Version="$(AspNetCore_HealthChecks_Rabbitmq)" />
|
<PackageReference Include="AspNetCore.HealthChecks.Rabbitmq" Version="$(AspNetCore_HealthChecks_Rabbitmq)" />
|
||||||
<PackageReference Include="AspNetCore.HealthChecks.SqlServer" Version="$(AspNetCore_HealthChecks_SqlServer)" />
|
<PackageReference Include="AspNetCore.HealthChecks.SqlServer" Version="$(AspNetCore_HealthChecks_SqlServer)" />
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
using Microsoft.AspNetCore;
|
using Microsoft.AspNetCore;
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
|
using Microsoft.AspNetCore.Server.Kestrel.Core;
|
||||||
using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF;
|
using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF;
|
||||||
using Microsoft.eShopOnContainers.Services.Ordering.API.Infrastructure;
|
using Microsoft.eShopOnContainers.Services.Ordering.API.Infrastructure;
|
||||||
using Microsoft.eShopOnContainers.Services.Ordering.Infrastructure;
|
using Microsoft.eShopOnContainers.Services.Ordering.Infrastructure;
|
||||||
@ -10,6 +11,7 @@ using Microsoft.Extensions.Options;
|
|||||||
using Serilog;
|
using Serilog;
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Net;
|
||||||
|
|
||||||
namespace Microsoft.eShopOnContainers.Services.Ordering.API
|
namespace Microsoft.eShopOnContainers.Services.Ordering.API
|
||||||
{
|
{
|
||||||
@ -61,6 +63,20 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.API
|
|||||||
private static IWebHost BuildWebHost(IConfiguration configuration, string[] args) =>
|
private static IWebHost BuildWebHost(IConfiguration configuration, string[] args) =>
|
||||||
WebHost.CreateDefaultBuilder(args)
|
WebHost.CreateDefaultBuilder(args)
|
||||||
.CaptureStartupErrors(false)
|
.CaptureStartupErrors(false)
|
||||||
|
.ConfigureKestrel(options =>
|
||||||
|
{
|
||||||
|
var ports = GetDefinedPorts(configuration);
|
||||||
|
options.Listen(IPAddress.Any, ports.httpPort, listenOptions =>
|
||||||
|
{
|
||||||
|
listenOptions.Protocols = HttpProtocols.Http1AndHttp2;
|
||||||
|
});
|
||||||
|
|
||||||
|
options.Listen(IPAddress.Any, ports.grpcPort, listenOptions =>
|
||||||
|
{
|
||||||
|
listenOptions.Protocols = HttpProtocols.Http2;
|
||||||
|
});
|
||||||
|
|
||||||
|
})
|
||||||
.UseStartup<Startup>()
|
.UseStartup<Startup>()
|
||||||
.UseApplicationInsights()
|
.UseApplicationInsights()
|
||||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
.UseContentRoot(Directory.GetCurrentDirectory())
|
||||||
@ -102,5 +118,11 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.API
|
|||||||
|
|
||||||
return builder.Build();
|
return builder.Build();
|
||||||
}
|
}
|
||||||
|
private static (int httpPort, int grpcPort) GetDefinedPorts(IConfiguration config)
|
||||||
|
{
|
||||||
|
var grpcPort = config.GetValue("GRPC_PORT", 5001);
|
||||||
|
var port = config.GetValue("PORT", 80);
|
||||||
|
return (port, grpcPort);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
39
src/Services/Ordering/Ordering.API/Proto/ordering.proto
Normal file
39
src/Services/Ordering/Ordering.API/Proto/ordering.proto
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
option csharp_namespace = "GrpcOrdering";
|
||||||
|
|
||||||
|
package OrderingApi;
|
||||||
|
|
||||||
|
service OrderingGrpc {
|
||||||
|
rpc CreateOrderDraftFromBasketData(CreateOrderDraftCommand) returns (OrderDraftDTO) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
message CreateOrderDraftCommand {
|
||||||
|
string buyerId = 1;
|
||||||
|
repeated BasketItem items = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
message BasketItem {
|
||||||
|
string id = 1;
|
||||||
|
string productId = 2;
|
||||||
|
string productName = 3;
|
||||||
|
double unitPrice = 4;
|
||||||
|
double oldUnitPrice = 5;
|
||||||
|
int32 quantity = 6;
|
||||||
|
string pictureUrl = 7;
|
||||||
|
}
|
||||||
|
|
||||||
|
message OrderDraftDTO {
|
||||||
|
double total = 1;
|
||||||
|
repeated OrderItemDTO orderItems = 2;
|
||||||
|
}
|
||||||
|
message OrderItemDTO {
|
||||||
|
int32 productId = 1;
|
||||||
|
string productName = 2;
|
||||||
|
double unitPrice = 3;
|
||||||
|
double discount = 4;
|
||||||
|
int32 units = 5;
|
||||||
|
string pictureUrl = 6;
|
||||||
|
}
|
||||||
|
|
@ -7,12 +7,14 @@
|
|||||||
using global::Ordering.API.Application.IntegrationEvents.Events;
|
using global::Ordering.API.Application.IntegrationEvents.Events;
|
||||||
using global::Ordering.API.Infrastructure.Filters;
|
using global::Ordering.API.Infrastructure.Filters;
|
||||||
using global::Ordering.API.Infrastructure.Middlewares;
|
using global::Ordering.API.Infrastructure.Middlewares;
|
||||||
|
using GrpcOrdering;
|
||||||
using HealthChecks.UI.Client;
|
using HealthChecks.UI.Client;
|
||||||
using Infrastructure.AutofacModules;
|
using Infrastructure.AutofacModules;
|
||||||
using Infrastructure.Filters;
|
using Infrastructure.Filters;
|
||||||
using Infrastructure.Services;
|
using Infrastructure.Services;
|
||||||
using Microsoft.AspNetCore.Builder;
|
using Microsoft.AspNetCore.Builder;
|
||||||
using Microsoft.AspNetCore.Diagnostics.HealthChecks;
|
using Microsoft.AspNetCore.Diagnostics.HealthChecks;
|
||||||
|
using Microsoft.AspNetCore.Hosting;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.Azure.ServiceBus;
|
using Microsoft.Azure.ServiceBus;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
@ -34,6 +36,7 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Data.Common;
|
using System.Data.Common;
|
||||||
using System.IdentityModel.Tokens.Jwt;
|
using System.IdentityModel.Tokens.Jwt;
|
||||||
|
using System.IO;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
|
||||||
public class Startup
|
public class Startup
|
||||||
@ -47,7 +50,13 @@
|
|||||||
|
|
||||||
public virtual IServiceProvider ConfigureServices(IServiceCollection services)
|
public virtual IServiceProvider ConfigureServices(IServiceCollection services)
|
||||||
{
|
{
|
||||||
services.AddApplicationInsights(Configuration)
|
services
|
||||||
|
.AddGrpc(options =>
|
||||||
|
{
|
||||||
|
options.EnableDetailedErrors = true;
|
||||||
|
})
|
||||||
|
.Services
|
||||||
|
.AddApplicationInsights(Configuration)
|
||||||
.AddCustomMvc()
|
.AddCustomMvc()
|
||||||
.AddHealthChecks(Configuration)
|
.AddHealthChecks(Configuration)
|
||||||
.AddCustomDbContext(Configuration)
|
.AddCustomDbContext(Configuration)
|
||||||
@ -68,7 +77,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory)
|
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory)
|
||||||
{
|
{
|
||||||
//loggerFactory.AddAzureWebAppDiagnostics();
|
//loggerFactory.AddAzureWebAppDiagnostics();
|
||||||
//loggerFactory.AddApplicationInsights(app.ApplicationServices, LogLevel.Trace);
|
//loggerFactory.AddApplicationInsights(app.ApplicationServices, LogLevel.Trace);
|
||||||
@ -87,8 +96,23 @@
|
|||||||
|
|
||||||
app.UseEndpoints(endpoints =>
|
app.UseEndpoints(endpoints =>
|
||||||
{
|
{
|
||||||
|
endpoints.MapGrpcService<OrderingService>();
|
||||||
endpoints.MapDefaultControllerRoute();
|
endpoints.MapDefaultControllerRoute();
|
||||||
endpoints.MapControllers();
|
endpoints.MapControllers();
|
||||||
|
endpoints.MapGet("/_proto/", async ctx =>
|
||||||
|
{
|
||||||
|
ctx.Response.ContentType = "text/plain";
|
||||||
|
using var fs = new FileStream(Path.Combine(env.ContentRootPath, "Proto", "basket.proto"), FileMode.Open, FileAccess.Read);
|
||||||
|
using var sr = new StreamReader(fs);
|
||||||
|
while (!sr.EndOfStream)
|
||||||
|
{
|
||||||
|
var line = await sr.ReadLineAsync();
|
||||||
|
if (line != "/* >>" || line != "<< */")
|
||||||
|
{
|
||||||
|
await ctx.Response.WriteAsync(line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
endpoints.MapHealthChecks("/hc", new HealthCheckOptions()
|
endpoints.MapHealthChecks("/hc", new HealthCheckOptions()
|
||||||
{
|
{
|
||||||
Predicate = _ => true,
|
Predicate = _ => true,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user