diff --git a/docker-compose.override.yml b/docker-compose.override.yml
index 4428a9330..5c1a9082c 100644
--- a/docker-compose.override.yml
+++ b/docker-compose.override.yml
@@ -115,6 +115,7 @@ services:
- Serilog__MinimumLevel__Override__Ordering.API=Verbose
ports:
- "5102:80"
+ - "5581:5001"
ordering.backgroundtasks:
environment:
@@ -284,6 +285,8 @@ services:
- urls__catalog=http://catalog.api
- urls__orders=http://ordering.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
- OrderingUrlHC=http://ordering.api/hc
- IdentityUrlHC=http://identity.api/hc
@@ -291,7 +294,7 @@ services:
- MarketingUrlHC=http://marketing.api/hc
- PaymentUrlHC=http://payment.api/hc
- LocationUrlHC=http://locations.api/hc
- - IdentityUrlExternal=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5105
+ - IdentityUrlExternal=http://10.0.75.1:5105
ports:
- "5120:80"
diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Config/UrlsConfig.cs b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Config/UrlsConfig.cs
index e920fbbb2..7fd7cb5f3 100644
--- a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Config/UrlsConfig.cs
+++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Config/UrlsConfig.cs
@@ -27,5 +27,7 @@ namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Config
public string Basket { get; set; }
public string Catalog { get; set; }
public string Orders { get; set; }
+ public string GrpcBasket { get; set; }
+ public string GrpcOrdering { get; set; }
}
}
diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Controllers/OrderController.cs b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Controllers/OrderController.cs
index ac359b4b5..8bacc80d4 100644
--- a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Controllers/OrderController.cs
+++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Controllers/OrderController.cs
@@ -13,12 +13,12 @@ namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Controllers
public class OrderController : ControllerBase
{
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;
- _orderClient = orderClient;
+ _orderingService = orderingService;
}
[Route("draft/{basketId}")]
@@ -39,7 +39,7 @@ namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Controllers
return BadRequest($"No basket found for id {basketId}");
}
- return await _orderClient.GetOrderDraftFromBasketAsync(basket);
+ return await _orderingService.GetOrderDraftAsync(basket);
}
}
}
diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Infrastructure/HttpClientAuthorizationDelegatingHandler.cs b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Infrastructure/HttpClientAuthorizationDelegatingHandler.cs
index 4562139df..bfc705b5c 100644
--- a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Infrastructure/HttpClientAuthorizationDelegatingHandler.cs
+++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Infrastructure/HttpClientAuthorizationDelegatingHandler.cs
@@ -40,8 +40,6 @@ namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Infrastruct
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token);
}
- _logger.LogInformation("@@@@@@@@@@@@@@@@@ {@request}", request);
-
return await base.SendAsync(request, cancellationToken);
}
diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Mobile.Shopping.HttpAggregator.csproj b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Mobile.Shopping.HttpAggregator.csproj
index ca8768a66..40060ea29 100644
--- a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Mobile.Shopping.HttpAggregator.csproj
+++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Mobile.Shopping.HttpAggregator.csproj
@@ -20,7 +20,7 @@
-
+
@@ -34,10 +34,11 @@
-
+
+
diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/BasketData.cs b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/BasketData.cs
index 302f6bd32..e2888f92e 100644
--- a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/BasketData.cs
+++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/BasketData.cs
@@ -6,7 +6,7 @@ namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Models
{
public string BuyerId { get; set; }
- public List Items { get; set; }
+ public List Items { get; set; } = new List();
public BasketData()
{
@@ -16,7 +16,6 @@ namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Models
public BasketData(string buyerId)
{
BuyerId = buyerId;
- Items = new List();
}
}
diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/OrderData.cs b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/OrderData.cs
index e87cc18f0..e63b453a4 100644
--- a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/OrderData.cs
+++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/OrderData.cs
@@ -1,7 +1,5 @@
using System;
using System.Collections.Generic;
-using System.Linq;
-using System.Threading.Tasks;
namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Models
{
@@ -28,6 +26,6 @@ namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Models
public string Buyer { get; set; }
- public List OrderItems { get; } = new List();
+ public List 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..023cf20e5 100644
--- a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/OrderItemData.cs
+++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/OrderItemData.cs
@@ -1,9 +1,4 @@
-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
{
diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/UpdateBasketItemsRequest.cs b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/UpdateBasketItemsRequest.cs
index 43cc81b89..35b3e76c0 100644
--- a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/UpdateBasketItemsRequest.cs
+++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/UpdateBasketItemsRequest.cs
@@ -1,7 +1,4 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading.Tasks;
+using System.Collections.Generic;
namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Models
{
diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/UpdateBasketRequest.cs b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/UpdateBasketRequest.cs
index cb22bf55f..b377921be 100644
--- a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/UpdateBasketRequest.cs
+++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/UpdateBasketRequest.cs
@@ -1,7 +1,4 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading.Tasks;
+using System.Collections.Generic;
namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Models
{
diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Services/BasketService.cs b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Services/BasketService.cs
index 44e13dd91..fa1fc9ffe 100644
--- a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Services/BasketService.cs
+++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Services/BasketService.cs
@@ -27,9 +27,6 @@ namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Services
public async Task GetById(string id)
{
-
- _logger.LogInformation("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ GetById @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
-
AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", 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; };
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.LogInformation("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ {httpClient.BaseAddress} @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ " + httpClient.BaseAddress, httpClient.BaseAddress);
+ _logger.LogDebug("Creating grpc client for basket {@httpClient.BaseAddress} ", httpClient.BaseAddress);
var client = GrpcClient.Create(httpClient);
- _logger.LogInformation("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ client create @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
+ _logger.LogDebug("grpc client created, request = {@id}", id);
try
{
var response = await client.GetBasketByIdAsync(new BasketRequest { Id = id });
- _logger.LogInformation("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ call grpc server @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
- _logger.LogInformation("############## DATA: {@a}", response.Buyerid);
- _logger.LogInformation("############## DATA:response {@response}", response);
+ _logger.LogDebug("grpc response {@response}", response);
return MapToBasketData(response);
}
@@ -66,11 +60,7 @@ namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Services
}
}
- return null; // temp
- // var data = await _apiClient.GetStringAsync(_urls.Basket + UrlsConfig.BasketOperations.GetItemById(id));
- // var basket = !string.IsNullOrEmpty(data) ? JsonConvert.DeserializeObject(data) : null;
-
- // return basket;
+ return null;
}
public async Task UpdateAsync(BasketData currentBasket)
diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Services/IOrderingService.cs b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Services/IOrderingService.cs
new file mode 100644
index 000000000..5518a4bbf
--- /dev/null
+++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Services/IOrderingService.cs
@@ -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 GetOrderDraftAsync(BasketData basketData);
+ }
+}
\ No newline at end of file
diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Services/OrderingService.cs b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Services/OrderingService.cs
new file mode 100644
index 000000000..f1e56c2ef
--- /dev/null
+++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Services/OrderingService.cs
@@ -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 _logger;
+
+ public OrderingService(HttpClient httpClient, IOptions config, ILogger logger)
+ {
+ _httpClient = httpClient;
+ _urls = config.Value;
+ _logger = logger;
+ }
+
+ public async Task 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(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;
+ }
+
+ }
+}
diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Startup.cs b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Startup.cs
index 8d7f7dbbe..f08514177 100644
--- a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Startup.cs
+++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Startup.cs
@@ -131,11 +131,9 @@ namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator
{
Implicit = new OpenApiOAuthFlow()
{
- // AuthorizationUrl = new Uri($"{configuration.GetValue("IdentityUrlExternal")}/connect/authorize"),
- // TokenUrl = new Uri($"{configuration.GetValue("IdentityUrlExternal")}/connect/token"),
-
- AuthorizationUrl = new Uri($"http://localhost:5105/connect/authorize"),
- TokenUrl = new Uri($"http://localhost:5105/connect/token"),
+ AuthorizationUrl = new Uri($"{configuration.GetValue("IdentityUrlExternal")}/connect/authorize"),
+ TokenUrl = new Uri($"{configuration.GetValue("IdentityUrlExternal")}/connect/token"),
+
Scopes = new Dictionary()
{
{ "mobileshoppingagg", "Shopping Aggregator for Mobile Clients" }
@@ -188,7 +186,8 @@ namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator
services.AddSingleton();
//register http services
- services.AddHttpClient()
+ services
+ .AddHttpClient()
.AddHttpMessageHandler()
.AddPolicyHandler(GetRetryPolicy())
.AddPolicyHandler(GetCircuitBreakerPolicy())
@@ -204,6 +203,11 @@ namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator
.AddPolicyHandler(GetCircuitBreakerPolicy())
.AddDevspacesSupport();
+ services.AddHttpClient()
+ .AddPolicyHandler(GetRetryPolicy())
+ .AddPolicyHandler(GetCircuitBreakerPolicy())
+ .AddDevspacesSupport();
+
return services;
}
diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/appsettings.localhost.json b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/appsettings.localhost.json
index 91bbf5f87..f14ca24b9 100644
--- a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/appsettings.localhost.json
+++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/appsettings.localhost.json
@@ -3,7 +3,9 @@
"basket": "http://localhost:55105",
"catalog": "http://localhost:55101",
"orders": "http://localhost:55102",
- "identity": "http://localhost:55105"
+ "identity": "http://localhost:55105",
+ "grpcBasket": "http://localhost:5580",
+ "grpcOrdering": "http://localhost:5581"
},
"IdentityUrlExternal": "http://localhost:5105",
"IdentityUrl": "http://localhost:5105",
diff --git a/src/Services/Ordering/Ordering.API/Grpc/OrderingService.cs b/src/Services/Ordering/Ordering.API/Grpc/OrderingService.cs
new file mode 100644
index 000000000..af59420e7
--- /dev/null
+++ b/src/Services/Ordering/Ordering.API/Grpc/OrderingService.cs
@@ -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 _logger;
+
+ public OrderingService(IMediator mediator, ILogger logger)
+ {
+ _mediator = mediator;
+ _logger = logger;
+ }
+
+ public override async Task 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 MapBasketItems(RepeatedField 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,
+ });
+ }
+ }
+}
diff --git a/src/Services/Ordering/Ordering.API/Ordering.API.csproj b/src/Services/Ordering/Ordering.API/Ordering.API.csproj
index 1b3c36daa..fdd681eab 100644
--- a/src/Services/Ordering/Ordering.API/Ordering.API.csproj
+++ b/src/Services/Ordering/Ordering.API/Ordering.API.csproj
@@ -19,6 +19,13 @@
+
+
+
+
+
+
+
@@ -30,7 +37,10 @@
-
+
+
+
+
diff --git a/src/Services/Ordering/Ordering.API/Program.cs b/src/Services/Ordering/Ordering.API/Program.cs
index 50f53360c..899871b3d 100644
--- a/src/Services/Ordering/Ordering.API/Program.cs
+++ b/src/Services/Ordering/Ordering.API/Program.cs
@@ -1,5 +1,6 @@
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
+using Microsoft.AspNetCore.Server.Kestrel.Core;
using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF;
using Microsoft.eShopOnContainers.Services.Ordering.API.Infrastructure;
using Microsoft.eShopOnContainers.Services.Ordering.Infrastructure;
@@ -10,6 +11,7 @@ using Microsoft.Extensions.Options;
using Serilog;
using System;
using System.IO;
+using System.Net;
namespace Microsoft.eShopOnContainers.Services.Ordering.API
{
@@ -61,6 +63,20 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.API
private static IWebHost BuildWebHost(IConfiguration configuration, string[] args) =>
WebHost.CreateDefaultBuilder(args)
.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()
.UseApplicationInsights()
.UseContentRoot(Directory.GetCurrentDirectory())
@@ -102,5 +118,11 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.API
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);
+ }
}
}
\ No newline at end of file
diff --git a/src/Services/Ordering/Ordering.API/Proto/ordering.proto b/src/Services/Ordering/Ordering.API/Proto/ordering.proto
new file mode 100644
index 000000000..988f3465b
--- /dev/null
+++ b/src/Services/Ordering/Ordering.API/Proto/ordering.proto
@@ -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;
+}
+
diff --git a/src/Services/Ordering/Ordering.API/Startup.cs b/src/Services/Ordering/Ordering.API/Startup.cs
index fca490f28..09f4c379b 100644
--- a/src/Services/Ordering/Ordering.API/Startup.cs
+++ b/src/Services/Ordering/Ordering.API/Startup.cs
@@ -7,12 +7,14 @@
using global::Ordering.API.Application.IntegrationEvents.Events;
using global::Ordering.API.Infrastructure.Filters;
using global::Ordering.API.Infrastructure.Middlewares;
+ using GrpcOrdering;
using HealthChecks.UI.Client;
using Infrastructure.AutofacModules;
using Infrastructure.Filters;
using Infrastructure.Services;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Diagnostics.HealthChecks;
+ using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.ServiceBus;
using Microsoft.EntityFrameworkCore;
@@ -34,6 +36,7 @@
using System.Collections.Generic;
using System.Data.Common;
using System.IdentityModel.Tokens.Jwt;
+ using System.IO;
using System.Reflection;
public class Startup
@@ -47,7 +50,13 @@
public virtual IServiceProvider ConfigureServices(IServiceCollection services)
{
- services.AddApplicationInsights(Configuration)
+ services
+ .AddGrpc(options =>
+ {
+ options.EnableDetailedErrors = true;
+ })
+ .Services
+ .AddApplicationInsights(Configuration)
.AddCustomMvc()
.AddHealthChecks(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.AddApplicationInsights(app.ApplicationServices, LogLevel.Trace);
@@ -87,8 +96,23 @@
app.UseEndpoints(endpoints =>
{
+ endpoints.MapGrpcService();
endpoints.MapDefaultControllerRoute();
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()
{
Predicate = _ => true,