Skip to content
This repository was archived by the owner on Nov 17, 2023. It is now read-only.

Commit 86e563f

Browse files
authored
Merge pull request #1547 from borjasanes/feature/basket-api-migration
basket api net 5 migration
2 parents a88f6c5 + e66e611 commit 86e563f

File tree

20 files changed

+355
-305
lines changed

20 files changed

+355
-305
lines changed
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
using Grpc.Core;
2+
using Grpc.Core.Interceptors;
3+
using Microsoft.Extensions.Logging;
4+
using System;
5+
using System.Threading.Tasks;
6+
7+
namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Infrastructure
8+
{
9+
public class GrpcExceptionInterceptor : Interceptor
10+
{
11+
private readonly ILogger<GrpcExceptionInterceptor> _logger;
12+
13+
public GrpcExceptionInterceptor(ILogger<GrpcExceptionInterceptor> logger)
14+
{
15+
_logger = logger;
16+
}
17+
18+
public override AsyncUnaryCall<TResponse> AsyncUnaryCall<TRequest, TResponse>(
19+
TRequest request,
20+
ClientInterceptorContext<TRequest, TResponse> context,
21+
AsyncUnaryCallContinuation<TRequest, TResponse> continuation)
22+
{
23+
var call = continuation(request, context);
24+
25+
return new AsyncUnaryCall<TResponse>(HandleResponse(call.ResponseAsync), call.ResponseHeadersAsync, call.GetStatus, call.GetTrailers, call.Dispose);
26+
}
27+
28+
private async Task<TResponse> HandleResponse<TResponse>(Task<TResponse> t)
29+
{
30+
try
31+
{
32+
var response = await t;
33+
_logger.LogDebug($"Response received: {response}");
34+
return response;
35+
}
36+
catch (RpcException e)
37+
{
38+
_logger.LogError("Error calling via grpc: {Status} - {Message}", e.Status, e.Message);
39+
return default;
40+
}
41+
}
42+
}
43+
}

src/ApiGateways/Mobile.Bff.Shopping/aggregator/Mobile.Shopping.HttpAggregator.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
<PackageReference Include="Google.Protobuf" Version="3.11.2" />
2121
<PackageReference Include="Grpc.AspNetCore.Server.ClientFactory" Version="2.25.0" />
2222
<PackageReference Include="Grpc.Core" Version="2.25.0" />
23+
<PackageReference Include="Grpc.Net.ClientFactory" Version="2.25.0" />
2324
<PackageReference Include="Grpc.Tools" Version="2.25.0" PrivateAssets="All" />
2425
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="3.1.0" />
2526
<PackageReference Include="Microsoft.AspNetCore.Diagnostics.HealthChecks" Version="2.2.0" />
Lines changed: 22 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,29 @@
11
using Microsoft.AspNetCore;
22
using Microsoft.AspNetCore.Hosting;
3-
using Microsoft.Extensions.Configuration;
3+
using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator;
44
using Serilog;
5-
using System.IO;
65

7-
namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator
8-
{
9-
public class Program
10-
{
11-
private static IConfiguration _configuration;
126

13-
public static void Main(string[] args)
7+
BuildWebHost(args).Run();
8+
IWebHost BuildWebHost(string[] args) =>
9+
WebHost
10+
.CreateDefaultBuilder(args)
11+
.ConfigureAppConfiguration(cb =>
1412
{
15-
_configuration = GetConfiguration();
16-
17-
BuildWebHost(args).Run();
18-
}
19-
20-
public static IWebHost BuildWebHost(string[] args) =>
21-
WebHost
22-
.CreateDefaultBuilder(args)
23-
.ConfigureAppConfiguration(cb =>
24-
{
25-
var sources = cb.Sources;
26-
sources.Insert(3, new Microsoft.Extensions.Configuration.Json.JsonConfigurationSource()
27-
{
28-
Optional = true,
29-
Path = "appsettings.localhost.json",
30-
ReloadOnChange = false
31-
});
32-
})
33-
.UseStartup<Startup>()
34-
.UseSerilog((builderContext, config) =>
35-
{
36-
config
37-
.MinimumLevel.Information()
38-
.Enrich.FromLogContext()
39-
.WriteTo.Console();
40-
})
41-
.Build();
42-
43-
private static IConfiguration GetConfiguration()
13+
var sources = cb.Sources;
14+
sources.Insert(3, new Microsoft.Extensions.Configuration.Json.JsonConfigurationSource()
15+
{
16+
Optional = true,
17+
Path = "appsettings.localhost.json",
18+
ReloadOnChange = false
19+
});
20+
})
21+
.UseStartup<Startup>()
22+
.UseSerilog((builderContext, config) =>
4423
{
45-
var builder = new ConfigurationBuilder()
46-
.SetBasePath(Directory.GetCurrentDirectory())
47-
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
48-
.AddEnvironmentVariables();
49-
50-
var config = builder.Build();
51-
52-
return builder.Build();
53-
}
54-
}
55-
}
24+
config
25+
.MinimumLevel.Information()
26+
.Enrich.FromLogContext()
27+
.WriteTo.Console();
28+
})
29+
.Build();

src/ApiGateways/Mobile.Bff.Shopping/aggregator/Services/BasketService.cs

Lines changed: 12 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,54 +1,40 @@
1-
using Grpc.Net.Client;
2-
using GrpcBasket;
1+
using GrpcBasket;
32
using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Config;
43
using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Models;
54
using Microsoft.Extensions.Logging;
65
using Microsoft.Extensions.Options;
76
using System.Linq;
8-
using System.Net.Http;
97
using System.Threading.Tasks;
108

119
namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Services
1210
{
1311
public class BasketService : IBasketService
1412
{
15-
private readonly HttpClient _httpClient;
16-
private readonly UrlsConfig _urls;
13+
private readonly Basket.BasketClient _basketClient;
1714
private readonly ILogger<BasketService> _logger;
1815

19-
public BasketService(HttpClient httpClient, IOptions<UrlsConfig> config, ILogger<BasketService> logger)
16+
public BasketService(Basket.BasketClient basketClient, ILogger<BasketService> logger)
2017
{
21-
_httpClient = httpClient;
22-
_urls = config.Value;
18+
_basketClient = basketClient;
2319
_logger = logger;
2420
}
2521

2622
public async Task<BasketData> GetById(string id)
2723
{
28-
return await GrpcCallerService.CallService(_urls.GrpcBasket, async channel =>
29-
{
30-
31-
var client = new Basket.BasketClient(channel);
32-
_logger.LogDebug("grpc client created, request = {@id}", id);
33-
var response = await client.GetBasketByIdAsync(new BasketRequest { Id = id });
34-
_logger.LogDebug("grpc response {@response}", response);
24+
_logger.LogDebug("grpc client created, request = {@id}", id);
25+
var response = await _basketClient.GetBasketByIdAsync(new BasketRequest { Id = id });
26+
_logger.LogDebug("grpc response {@response}", response);
3527

36-
return MapToBasketData(response);
37-
});
28+
return MapToBasketData(response);
3829
}
3930

4031
public async Task UpdateAsync(BasketData currentBasket)
4132
{
42-
await GrpcCallerService.CallService(_urls.GrpcBasket, async httpClient =>
43-
{
44-
var channel = GrpcChannel.ForAddress(_urls.GrpcBasket);
45-
var client = new Basket.BasketClient(channel);
46-
_logger.LogDebug("Grpc update basket currentBasket {@currentBasket}", currentBasket);
47-
var request = MapToCustomerBasketRequest(currentBasket);
48-
_logger.LogDebug("Grpc update basket request {@request}", request);
33+
_logger.LogDebug("Grpc update basket currentBasket {@currentBasket}", currentBasket);
34+
var request = MapToCustomerBasketRequest(currentBasket);
35+
_logger.LogDebug("Grpc update basket request {@request}", request);
4936

50-
return await client.UpdateBasketAsync(request);
51-
});
37+
await _basketClient.UpdateBasketAsync(request);
5238
}
5339

5440
private BasketData MapToBasketData(CustomerBasketResponse customerBasketRequest)

src/ApiGateways/Mobile.Bff.Shopping/aggregator/Startup.cs

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using Devspaces.Support;
2+
using GrpcBasket;
23
using HealthChecks.UI.Client;
34
using Microsoft.AspNetCore.Authentication.JwtBearer;
45
using Microsoft.AspNetCore.Builder;
@@ -14,6 +15,7 @@
1415
using Microsoft.Extensions.Diagnostics.HealthChecks;
1516
using Microsoft.Extensions.Hosting;
1617
using Microsoft.Extensions.Logging;
18+
using Microsoft.Extensions.Options;
1719
using Microsoft.OpenApi.Models;
1820
using System;
1921
using System.Collections.Generic;
@@ -46,7 +48,8 @@ public void ConfigureServices(IServiceCollection services)
4648
services.AddCustomMvc(Configuration)
4749
.AddCustomAuthentication(Configuration)
4850
.AddDevspaces()
49-
.AddHttpServices();
51+
.AddHttpServices()
52+
.AddGrpcServices();
5053
}
5154

5255
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
@@ -177,10 +180,6 @@ public static IServiceCollection AddHttpServices(this IServiceCollection service
177180
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
178181

179182
//register http services
180-
services
181-
.AddHttpClient<IBasketService, BasketService>()
182-
.AddHttpMessageHandler<HttpClientAuthorizationDelegatingHandler>()
183-
.AddDevspacesSupport();
184183

185184
services.AddHttpClient<ICatalogService, CatalogService>()
186185
.AddDevspacesSupport();
@@ -194,5 +193,20 @@ public static IServiceCollection AddHttpServices(this IServiceCollection service
194193
return services;
195194
}
196195

196+
public static IServiceCollection AddGrpcServices(this IServiceCollection services)
197+
{
198+
services.AddSingleton<GrpcExceptionInterceptor>();
199+
200+
services.AddScoped<IBasketService, BasketService>();
201+
202+
services.AddGrpcClient<Basket.BasketClient>((services, options) =>
203+
{
204+
var basketApi = services.GetRequiredService<IOptions<UrlsConfig>>().Value.GrpcBasket;
205+
options.Address = new Uri(basketApi);
206+
}).AddInterceptor<GrpcExceptionInterceptor>();
207+
208+
return services;
209+
}
210+
197211
}
198212
}

src/ApiGateways/Web.Bff.Shopping/aggregator/Dockerfile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
FROM mcr.microsoft.com/dotnet/core/aspnet:3.1 AS base
1+
FROM mcr.microsoft.com/dotnet/aspnet:5.0 AS base
22
WORKDIR /app
33
EXPOSE 80
44

5-
FROM mcr.microsoft.com/dotnet/core/sdk:3.1 AS build
5+
FROM mcr.microsoft.com/dotnet/sdk:5.0 AS build
66
WORKDIR /src
77

88
# It's important to keep lines from here down to "COPY . ." identical in all Dockerfiles
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
using Grpc.Core;
2+
using Grpc.Core.Interceptors;
3+
using Microsoft.Extensions.Logging;
4+
using System;
5+
using System.Threading.Tasks;
6+
7+
namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Infrastructure
8+
{
9+
public class GrpcExceptionInterceptor : Interceptor
10+
{
11+
private readonly ILogger<GrpcExceptionInterceptor> _logger;
12+
13+
public GrpcExceptionInterceptor(ILogger<GrpcExceptionInterceptor> logger)
14+
{
15+
_logger = logger;
16+
}
17+
18+
public override AsyncUnaryCall<TResponse> AsyncUnaryCall<TRequest, TResponse>(
19+
TRequest request,
20+
ClientInterceptorContext<TRequest, TResponse> context,
21+
AsyncUnaryCallContinuation<TRequest, TResponse> continuation)
22+
{
23+
var call = continuation(request, context);
24+
25+
return new AsyncUnaryCall<TResponse>(HandleResponse(call.ResponseAsync), call.ResponseHeadersAsync, call.GetStatus, call.GetTrailers, call.Dispose);
26+
}
27+
28+
private async Task<TResponse> HandleResponse<TResponse>(Task<TResponse> t)
29+
{
30+
try
31+
{
32+
var response = await t;
33+
_logger.LogDebug($"Response received: {response}");
34+
return response;
35+
}
36+
catch (RpcException e)
37+
{
38+
_logger.LogError("Error calling via grpc: {Status} - {Message}", e.Status, e.Message);
39+
return default;
40+
}
41+
}
42+
}
43+
}
Lines changed: 24 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,29 @@
11
using Microsoft.AspNetCore;
22
using Microsoft.AspNetCore.Hosting;
3+
using Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator;
34
using Serilog;
45

5-
namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator
6-
{
7-
public class Program
8-
{
9-
public static void Main(string[] args)
10-
{
11-
BuildWebHost(args).Run();
12-
}
13-
14-
public static IWebHost BuildWebHost(string[] args) =>
15-
WebHost
16-
.CreateDefaultBuilder(args)
17-
.ConfigureAppConfiguration(cb =>
18-
{
19-
var sources = cb.Sources;
20-
sources.Insert(3, new Microsoft.Extensions.Configuration.Json.JsonConfigurationSource()
21-
{
22-
Optional = true,
23-
Path = "appsettings.localhost.json",
24-
ReloadOnChange = false
25-
});
26-
})
27-
.UseStartup<Startup>()
28-
.UseSerilog((builderContext, config) =>
29-
{
30-
config
31-
.MinimumLevel.Information()
32-
.Enrich.FromLogContext()
33-
.WriteTo.Console();
34-
})
35-
.Build();
6+
BuildWebHost(args).Run();
367

37-
}
38-
}
8+
IWebHost BuildWebHost(string[] args) =>
9+
WebHost
10+
.CreateDefaultBuilder(args)
11+
.ConfigureAppConfiguration(cb =>
12+
{
13+
var sources = cb.Sources;
14+
sources.Insert(3, new Microsoft.Extensions.Configuration.Json.JsonConfigurationSource()
15+
{
16+
Optional = true,
17+
Path = "appsettings.localhost.json",
18+
ReloadOnChange = false
19+
});
20+
})
21+
.UseStartup<Startup>()
22+
.UseSerilog((builderContext, config) =>
23+
{
24+
config
25+
.MinimumLevel.Information()
26+
.Enrich.FromLogContext()
27+
.WriteTo.Console();
28+
})
29+
.Build();

0 commit comments

Comments
 (0)