Merge pull request #1547 from borjasanes/feature/basket-api-migration
basket api net 5 migration
This commit is contained in:
		
						commit
						86e563f76e
					
				| @ -0,0 +1,43 @@ | ||||
| using Grpc.Core; | ||||
| using Grpc.Core.Interceptors; | ||||
| using Microsoft.Extensions.Logging; | ||||
| using System; | ||||
| using System.Threading.Tasks; | ||||
| 
 | ||||
| namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Infrastructure | ||||
| { | ||||
|     public class GrpcExceptionInterceptor : Interceptor | ||||
|     { | ||||
|         private readonly ILogger<GrpcExceptionInterceptor> _logger; | ||||
| 
 | ||||
|         public GrpcExceptionInterceptor(ILogger<GrpcExceptionInterceptor> logger) | ||||
|         { | ||||
|             _logger = logger; | ||||
|         } | ||||
| 
 | ||||
|         public override AsyncUnaryCall<TResponse> AsyncUnaryCall<TRequest, TResponse>( | ||||
|             TRequest request, | ||||
|             ClientInterceptorContext<TRequest, TResponse> context, | ||||
|             AsyncUnaryCallContinuation<TRequest, TResponse> continuation) | ||||
|         { | ||||
|             var call = continuation(request, context); | ||||
| 
 | ||||
|             return new AsyncUnaryCall<TResponse>(HandleResponse(call.ResponseAsync), call.ResponseHeadersAsync, call.GetStatus, call.GetTrailers, call.Dispose); | ||||
|         } | ||||
| 
 | ||||
|         private async Task<TResponse> HandleResponse<TResponse>(Task<TResponse> t) | ||||
|         { | ||||
|             try | ||||
|             { | ||||
|                 var response = await t; | ||||
|                 _logger.LogDebug($"Response received: {response}"); | ||||
|                 return response; | ||||
|             } | ||||
|             catch (RpcException e) | ||||
|             { | ||||
|                 _logger.LogError("Error calling via grpc: {Status} - {Message}", e.Status, e.Message); | ||||
|                 return default; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -20,6 +20,7 @@ | ||||
|     <PackageReference Include="Google.Protobuf" Version="3.11.2" /> | ||||
|     <PackageReference Include="Grpc.AspNetCore.Server.ClientFactory" Version="2.25.0" /> | ||||
|     <PackageReference Include="Grpc.Core" Version="2.25.0" /> | ||||
|     <PackageReference Include="Grpc.Net.ClientFactory" Version="2.25.0" /> | ||||
|     <PackageReference Include="Grpc.Tools" Version="2.25.0" PrivateAssets="All" /> | ||||
|     <PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="3.1.0" /> | ||||
|     <PackageReference Include="Microsoft.AspNetCore.Diagnostics.HealthChecks" Version="2.2.0" /> | ||||
|  | ||||
| @ -1,55 +1,29 @@ | ||||
| using Microsoft.AspNetCore; | ||||
| using Microsoft.AspNetCore.Hosting; | ||||
| using Microsoft.Extensions.Configuration; | ||||
| using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator; | ||||
| using Serilog; | ||||
| using System.IO; | ||||
| 
 | ||||
| namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator | ||||
| { | ||||
|     public class Program | ||||
|     { | ||||
|         private static IConfiguration _configuration; | ||||
| 
 | ||||
|         public static void Main(string[] args) | ||||
| BuildWebHost(args).Run(); | ||||
| IWebHost BuildWebHost(string[] args) => | ||||
|     WebHost | ||||
|         .CreateDefaultBuilder(args) | ||||
|         .ConfigureAppConfiguration(cb => | ||||
|         { | ||||
|             _configuration = GetConfiguration(); | ||||
| 
 | ||||
|             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<Startup>() | ||||
|                 .UseSerilog((builderContext, config) => | ||||
|                 { | ||||
|                     config | ||||
|                         .MinimumLevel.Information() | ||||
|                         .Enrich.FromLogContext() | ||||
|                         .WriteTo.Console(); | ||||
|                 }) | ||||
|                 .Build(); | ||||
| 
 | ||||
|         private static IConfiguration GetConfiguration() | ||||
|             var sources = cb.Sources; | ||||
|             sources.Insert(3, new Microsoft.Extensions.Configuration.Json.JsonConfigurationSource() | ||||
|             { | ||||
|                 Optional = true, | ||||
|                 Path = "appsettings.localhost.json", | ||||
|                 ReloadOnChange = false | ||||
|             }); | ||||
|         }) | ||||
|         .UseStartup<Startup>() | ||||
|         .UseSerilog((builderContext, config) => | ||||
|         { | ||||
|             var builder = new ConfigurationBuilder() | ||||
|                 .SetBasePath(Directory.GetCurrentDirectory()) | ||||
|                 .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true) | ||||
|                 .AddEnvironmentVariables(); | ||||
| 
 | ||||
|             var config = builder.Build(); | ||||
| 
 | ||||
|             return builder.Build(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|             config | ||||
|                 .MinimumLevel.Information() | ||||
|                 .Enrich.FromLogContext() | ||||
|                 .WriteTo.Console(); | ||||
|         }) | ||||
|         .Build(); | ||||
| @ -1,54 +1,40 @@ | ||||
| using Grpc.Net.Client; | ||||
| using GrpcBasket; | ||||
| using GrpcBasket; | ||||
| using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Config; | ||||
| using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Models; | ||||
| using Microsoft.Extensions.Logging; | ||||
| using Microsoft.Extensions.Options; | ||||
| using System.Linq; | ||||
| using System.Net.Http; | ||||
| using System.Threading.Tasks; | ||||
| 
 | ||||
| namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Services | ||||
| { | ||||
|     public class BasketService : IBasketService | ||||
|     { | ||||
|         private readonly HttpClient _httpClient; | ||||
|         private readonly UrlsConfig _urls; | ||||
|         private readonly Basket.BasketClient _basketClient; | ||||
|         private readonly ILogger<BasketService> _logger; | ||||
| 
 | ||||
|         public BasketService(HttpClient httpClient, IOptions<UrlsConfig> config, ILogger<BasketService> logger) | ||||
|         public BasketService(Basket.BasketClient basketClient, ILogger<BasketService> logger) | ||||
|         { | ||||
|             _httpClient = httpClient; | ||||
|             _urls = config.Value; | ||||
|             _basketClient = basketClient; | ||||
|             _logger = logger; | ||||
|         } | ||||
| 
 | ||||
|         public async Task<BasketData> GetById(string id) | ||||
|         { | ||||
|             return await GrpcCallerService.CallService(_urls.GrpcBasket, async channel => | ||||
|             { | ||||
|                  | ||||
|                 var client = new Basket.BasketClient(channel); | ||||
|                 _logger.LogDebug("grpc client created, request = {@id}", id); | ||||
|                 var response = await client.GetBasketByIdAsync(new BasketRequest { Id = id }); | ||||
|                 _logger.LogDebug("grpc response {@response}", response); | ||||
|             _logger.LogDebug("grpc client created, request = {@id}", id); | ||||
|             var response = await _basketClient.GetBasketByIdAsync(new BasketRequest { Id = id }); | ||||
|             _logger.LogDebug("grpc response {@response}", response); | ||||
| 
 | ||||
|                 return MapToBasketData(response); | ||||
|             }); | ||||
|             return MapToBasketData(response); | ||||
|         } | ||||
| 
 | ||||
|         public async Task UpdateAsync(BasketData currentBasket) | ||||
|         { | ||||
|             await GrpcCallerService.CallService(_urls.GrpcBasket, async httpClient => | ||||
|             { | ||||
|                 var channel = GrpcChannel.ForAddress(_urls.GrpcBasket); | ||||
|                 var client = new Basket.BasketClient(channel); | ||||
|                 _logger.LogDebug("Grpc update basket currentBasket {@currentBasket}", currentBasket); | ||||
|                 var request = MapToCustomerBasketRequest(currentBasket); | ||||
|                 _logger.LogDebug("Grpc update basket request {@request}", request); | ||||
|             _logger.LogDebug("Grpc update basket currentBasket {@currentBasket}", currentBasket); | ||||
|             var request = MapToCustomerBasketRequest(currentBasket); | ||||
|             _logger.LogDebug("Grpc update basket request {@request}", request); | ||||
| 
 | ||||
|                 return await client.UpdateBasketAsync(request); | ||||
|             }); | ||||
|             await _basketClient.UpdateBasketAsync(request); | ||||
|         } | ||||
| 
 | ||||
|         private BasketData MapToBasketData(CustomerBasketResponse customerBasketRequest) | ||||
|  | ||||
| @ -1,4 +1,5 @@ | ||||
| using Devspaces.Support; | ||||
| using GrpcBasket; | ||||
| using HealthChecks.UI.Client; | ||||
| using Microsoft.AspNetCore.Authentication.JwtBearer; | ||||
| using Microsoft.AspNetCore.Builder; | ||||
| @ -14,6 +15,7 @@ using Microsoft.Extensions.DependencyInjection; | ||||
| using Microsoft.Extensions.Diagnostics.HealthChecks; | ||||
| using Microsoft.Extensions.Hosting; | ||||
| using Microsoft.Extensions.Logging; | ||||
| using Microsoft.Extensions.Options; | ||||
| using Microsoft.OpenApi.Models; | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| @ -46,7 +48,8 @@ namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator | ||||
|             services.AddCustomMvc(Configuration) | ||||
|                  .AddCustomAuthentication(Configuration) | ||||
|                  .AddDevspaces() | ||||
|                  .AddHttpServices(); | ||||
|                  .AddHttpServices() | ||||
|                  .AddGrpcServices(); | ||||
|         } | ||||
| 
 | ||||
|         // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. | ||||
| @ -177,10 +180,6 @@ namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator | ||||
|             services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>(); | ||||
| 
 | ||||
|             //register http services | ||||
|             services | ||||
|                 .AddHttpClient<IBasketService, BasketService>() | ||||
|                 .AddHttpMessageHandler<HttpClientAuthorizationDelegatingHandler>() | ||||
|                 .AddDevspacesSupport(); | ||||
| 
 | ||||
|             services.AddHttpClient<ICatalogService, CatalogService>() | ||||
|                    .AddDevspacesSupport(); | ||||
| @ -194,5 +193,20 @@ namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator | ||||
|             return services; | ||||
|         } | ||||
| 
 | ||||
|         public static IServiceCollection AddGrpcServices(this IServiceCollection services) | ||||
|         { | ||||
|             services.AddSingleton<GrpcExceptionInterceptor>(); | ||||
| 
 | ||||
|             services.AddScoped<IBasketService, BasketService>(); | ||||
| 
 | ||||
|             services.AddGrpcClient<Basket.BasketClient>((services, options) => | ||||
|             { | ||||
|                 var basketApi = services.GetRequiredService<IOptions<UrlsConfig>>().Value.GrpcBasket; | ||||
|                 options.Address = new Uri(basketApi); | ||||
|             }).AddInterceptor<GrpcExceptionInterceptor>(); | ||||
| 
 | ||||
|             return services; | ||||
|         } | ||||
| 
 | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -1,8 +1,8 @@ | ||||
| FROM mcr.microsoft.com/dotnet/core/aspnet:3.1 AS base | ||||
| FROM mcr.microsoft.com/dotnet/aspnet:5.0 AS base | ||||
| WORKDIR /app | ||||
| EXPOSE 80 | ||||
| 
 | ||||
| FROM mcr.microsoft.com/dotnet/core/sdk:3.1 AS build | ||||
| FROM mcr.microsoft.com/dotnet/sdk:5.0 AS build | ||||
| WORKDIR /src | ||||
| 
 | ||||
| # It's important to keep lines from here down to "COPY . ." identical in all Dockerfiles | ||||
|  | ||||
| @ -0,0 +1,43 @@ | ||||
| using Grpc.Core; | ||||
| using Grpc.Core.Interceptors; | ||||
| using Microsoft.Extensions.Logging; | ||||
| using System; | ||||
| using System.Threading.Tasks; | ||||
| 
 | ||||
| namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Infrastructure | ||||
| { | ||||
|     public class GrpcExceptionInterceptor : Interceptor | ||||
|     { | ||||
|         private readonly ILogger<GrpcExceptionInterceptor> _logger; | ||||
| 
 | ||||
|         public GrpcExceptionInterceptor(ILogger<GrpcExceptionInterceptor> logger) | ||||
|         { | ||||
|             _logger = logger; | ||||
|         } | ||||
| 
 | ||||
|         public override AsyncUnaryCall<TResponse> AsyncUnaryCall<TRequest, TResponse>( | ||||
|             TRequest request, | ||||
|             ClientInterceptorContext<TRequest, TResponse> context, | ||||
|             AsyncUnaryCallContinuation<TRequest, TResponse> continuation) | ||||
|         { | ||||
|             var call = continuation(request, context); | ||||
| 
 | ||||
|             return new AsyncUnaryCall<TResponse>(HandleResponse(call.ResponseAsync), call.ResponseHeadersAsync, call.GetStatus, call.GetTrailers, call.Dispose); | ||||
|         } | ||||
| 
 | ||||
|         private async Task<TResponse> HandleResponse<TResponse>(Task<TResponse> t) | ||||
|         { | ||||
|             try | ||||
|             { | ||||
|                 var response = await t; | ||||
|                 _logger.LogDebug($"Response received: {response}"); | ||||
|                 return response; | ||||
|             } | ||||
|             catch (RpcException e) | ||||
|             { | ||||
|                 _logger.LogError("Error calling via grpc: {Status} - {Message}", e.Status, e.Message); | ||||
|                 return default; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -1,38 +1,29 @@ | ||||
| using Microsoft.AspNetCore; | ||||
| using Microsoft.AspNetCore.Hosting; | ||||
| using Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator; | ||||
| using Serilog; | ||||
| 
 | ||||
| namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator | ||||
| { | ||||
|     public class Program | ||||
|     { | ||||
|         public static void Main(string[] args) | ||||
| BuildWebHost(args).Run(); | ||||
| 
 | ||||
| IWebHost BuildWebHost(string[] args) => | ||||
|     WebHost | ||||
|         .CreateDefaultBuilder(args) | ||||
|         .ConfigureAppConfiguration(cb => | ||||
|         { | ||||
|             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<Startup>() | ||||
|                 .UseSerilog((builderContext, config) => | ||||
|                 { | ||||
|                     config | ||||
|                         .MinimumLevel.Information() | ||||
|                         .Enrich.FromLogContext() | ||||
|                         .WriteTo.Console(); | ||||
|                 }) | ||||
|                 .Build(); | ||||
| 
 | ||||
|     } | ||||
| } | ||||
|             var sources = cb.Sources; | ||||
|             sources.Insert(3, new Microsoft.Extensions.Configuration.Json.JsonConfigurationSource() | ||||
|             { | ||||
|                 Optional = true, | ||||
|                 Path = "appsettings.localhost.json", | ||||
|                 ReloadOnChange = false | ||||
|             }); | ||||
|         }) | ||||
|         .UseStartup<Startup>() | ||||
|         .UseSerilog((builderContext, config) => | ||||
|         { | ||||
|             config | ||||
|                 .MinimumLevel.Information() | ||||
|                 .Enrich.FromLogContext() | ||||
|                 .WriteTo.Console(); | ||||
|         }) | ||||
|         .Build(); | ||||
| @ -4,49 +4,38 @@ using Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Models; | ||||
| using Microsoft.Extensions.Logging; | ||||
| using Microsoft.Extensions.Options; | ||||
| using System.Linq; | ||||
| using System.Net.Http; | ||||
| using System.Threading.Tasks; | ||||
| 
 | ||||
| namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Services | ||||
| { | ||||
|     public class BasketService : IBasketService | ||||
|     { | ||||
|         private readonly UrlsConfig _urls; | ||||
|         public readonly HttpClient _httpClient; | ||||
|         private readonly Basket.BasketClient _basketClient; | ||||
|         private readonly ILogger<BasketService> _logger; | ||||
| 
 | ||||
|         public BasketService(HttpClient httpClient, IOptions<UrlsConfig> config, ILogger<BasketService> logger) | ||||
|         public BasketService(Basket.BasketClient basketClient, ILogger<BasketService> logger) | ||||
|         { | ||||
|             _urls = config.Value; | ||||
|             _httpClient = httpClient; | ||||
|             _basketClient = basketClient; | ||||
|             _logger = logger; | ||||
|         } | ||||
| 
 | ||||
| 
 | ||||
|         public async Task<BasketData> GetById(string id) | ||||
|         { | ||||
|             return await GrpcCallerService.CallService(_urls.GrpcBasket, async channel => | ||||
|             { | ||||
|                 var client = new Basket.BasketClient(channel); | ||||
|                 _logger.LogDebug("grpc client created, request = {@id}", id); | ||||
|                 var response = await client.GetBasketByIdAsync(new BasketRequest { Id = id }); | ||||
|                 _logger.LogDebug("grpc response {@response}", response); | ||||
|             _logger.LogDebug("grpc client created, request = {@id}", id); | ||||
|             var response = await _basketClient.GetBasketByIdAsync(new BasketRequest { Id = id }); | ||||
|             _logger.LogDebug("grpc response {@response}", response); | ||||
| 
 | ||||
|                 return MapToBasketData(response); | ||||
|             }); | ||||
|             return MapToBasketData(response); | ||||
|         } | ||||
| 
 | ||||
|         public async Task UpdateAsync(BasketData currentBasket) | ||||
|         { | ||||
|             await GrpcCallerService.CallService(_urls.GrpcBasket, async channel => | ||||
|             { | ||||
|                 var client = new Basket.BasketClient(channel); | ||||
|                 _logger.LogDebug("Grpc update basket currentBasket {@currentBasket}", currentBasket); | ||||
|                 var request = MapToCustomerBasketRequest(currentBasket); | ||||
|                 _logger.LogDebug("Grpc update basket request {@request}", request); | ||||
|             _logger.LogDebug("Grpc update basket currentBasket {@currentBasket}", currentBasket); | ||||
|             var request = MapToCustomerBasketRequest(currentBasket); | ||||
|             _logger.LogDebug("Grpc update basket request {@request}", request); | ||||
| 
 | ||||
|                 return await client.UpdateBasketAsync(request); | ||||
|             }); | ||||
|             await _basketClient.UpdateBasketAsync(request); | ||||
|         } | ||||
| 
 | ||||
|         private BasketData MapToBasketData(CustomerBasketResponse customerBasketRequest) | ||||
|  | ||||
| @ -1,4 +1,5 @@ | ||||
| using Devspaces.Support; | ||||
| using GrpcBasket; | ||||
| using HealthChecks.UI.Client; | ||||
| using Microsoft.AspNetCore.Authentication.JwtBearer; | ||||
| using Microsoft.AspNetCore.Builder; | ||||
| @ -14,6 +15,7 @@ using Microsoft.Extensions.DependencyInjection; | ||||
| using Microsoft.Extensions.Diagnostics.HealthChecks; | ||||
| using Microsoft.Extensions.Hosting; | ||||
| using Microsoft.Extensions.Logging; | ||||
| using Microsoft.Extensions.Options; | ||||
| using Microsoft.OpenApi.Models; | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| @ -42,11 +44,12 @@ namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator | ||||
|                 .AddUrlGroup(new Uri(Configuration["MarketingUrlHC"]), name: "marketingapi-check", tags: new string[] { "marketingapi" }) | ||||
|                 .AddUrlGroup(new Uri(Configuration["PaymentUrlHC"]), name: "paymentapi-check", tags: new string[] { "paymentapi" }) | ||||
|                 .AddUrlGroup(new Uri(Configuration["LocationUrlHC"]), name: "locationapi-check", tags: new string[] { "locationapi" }); | ||||
| 
 | ||||
|      | ||||
|             services.AddCustomMvc(Configuration) | ||||
|                 .AddCustomAuthentication(Configuration) | ||||
|                 .AddDevspaces() | ||||
|                 .AddApplicationServices(); | ||||
|                 .AddApplicationServices() | ||||
|                 .AddGrpcServices(); | ||||
|         } | ||||
| 
 | ||||
|         // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. | ||||
| @ -63,7 +66,7 @@ namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator | ||||
|             { | ||||
|                 app.UseDeveloperExceptionPage(); | ||||
|             } | ||||
|              | ||||
| 
 | ||||
|             app.UseHttpsRedirection(); | ||||
| 
 | ||||
|             app.UseSwagger().UseSwaggerUI(c => | ||||
| @ -139,7 +142,7 @@ namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator | ||||
|                     Version = "v1", | ||||
|                     Description = "Shopping Aggregator for Web Clients" | ||||
|                 }); | ||||
| 
 | ||||
|                  | ||||
|                 options.AddSecurityDefinition("oauth2", new OpenApiSecurityScheme | ||||
|                 { | ||||
|                     Type = SecuritySchemeType.OAuth2, | ||||
| @ -181,10 +184,6 @@ namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator | ||||
| 
 | ||||
|             //register http services | ||||
| 
 | ||||
|             services.AddHttpClient<IBasketService, BasketService>() | ||||
|                 .AddHttpMessageHandler<HttpClientAuthorizationDelegatingHandler>() | ||||
|                 .AddDevspacesSupport(); | ||||
| 
 | ||||
|             services.AddHttpClient<ICatalogService, CatalogService>() | ||||
|                 .AddDevspacesSupport(); | ||||
| 
 | ||||
| @ -199,6 +198,19 @@ namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator | ||||
|             return services; | ||||
|         } | ||||
| 
 | ||||
|         public static IServiceCollection AddGrpcServices(this IServiceCollection services) | ||||
|         { | ||||
|             services.AddSingleton<GrpcExceptionInterceptor>(); | ||||
| 
 | ||||
|             services.AddScoped<IBasketService, BasketService>(); | ||||
| 
 | ||||
|             services.AddGrpcClient<Basket.BasketClient>((services, options) => | ||||
|             { | ||||
|                 var basketApi = services.GetRequiredService<IOptions<UrlsConfig>>().Value.GrpcBasket; | ||||
|                 options.Address = new Uri(basketApi); | ||||
|             }).AddInterceptor<GrpcExceptionInterceptor>(); | ||||
| 
 | ||||
|             return services; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| <Project Sdk="Microsoft.NET.Sdk.Web"> | ||||
| 
 | ||||
|   <PropertyGroup> | ||||
|     <TargetFramework>netcoreapp3.1</TargetFramework> | ||||
|     <TargetFramework>net5.0</TargetFramework> | ||||
|     <AssemblyName>Web.Shopping.HttpAggregator</AssemblyName> | ||||
|     <RootNamespace>Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator</RootNamespace> | ||||
|     <DockerComposeProjectPath>..\..\..\docker-compose.dcproj</DockerComposeProjectPath> | ||||
| @ -15,20 +15,21 @@ | ||||
|   </ItemGroup> | ||||
| 
 | ||||
|   <ItemGroup> | ||||
|     <PackageReference Include="AspNetCore.HealthChecks.UI.Client" Version="3.0.0" /> | ||||
|     <PackageReference Include="AspNetCore.HealthChecks.Uris" Version="3.0.0" /> | ||||
|     <PackageReference Include="Google.Protobuf" Version="3.11.2" /> | ||||
|     <PackageReference Include="Grpc.AspNetCore.Server.ClientFactory" Version="2.25.0" /> | ||||
|     <PackageReference Include="Grpc.Core" Version="2.25.0" /> | ||||
|     <PackageReference Include="Grpc.Net.Client" Version="2.25.0" /> | ||||
|     <PackageReference Include="Grpc.Tools" Version="2.25.0" PrivateAssets="All" /> | ||||
|     <PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="3.1.0" /> | ||||
|     <PackageReference Include="AspNetCore.HealthChecks.UI.Client" Version="3.1.2" /> | ||||
|     <PackageReference Include="AspNetCore.HealthChecks.Uris" Version="3.1.2" /> | ||||
|     <PackageReference Include="Google.Protobuf" Version="3.14.0" /> | ||||
|     <PackageReference Include="Grpc.AspNetCore.Server.ClientFactory" Version="2.34.0" /> | ||||
|     <PackageReference Include="Grpc.Core" Version="2.34.0" /> | ||||
|     <PackageReference Include="Grpc.Net.Client" Version="2.34.0" /> | ||||
|     <PackageReference Include="Grpc.Net.ClientFactory" Version="2.34.0" /> | ||||
|     <PackageReference Include="Grpc.Tools" Version="2.34.0" PrivateAssets="All" /> | ||||
|     <PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="5.0.1" /> | ||||
|     <PackageReference Include="Microsoft.AspNetCore.Diagnostics.HealthChecks" Version="2.2.0" /> | ||||
|     <PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="3.1.0" /> | ||||
|     <PackageReference Include="Microsoft.Extensions.Diagnostics.HealthChecks" Version="3.1.0" /> | ||||
|     <PackageReference Include="Serilog.AspNetCore" Version="3.2.0" /> | ||||
|     <PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="5.0.1" /> | ||||
|     <PackageReference Include="Microsoft.Extensions.Diagnostics.HealthChecks" Version="5.0.1" /> | ||||
|     <PackageReference Include="Serilog.AspNetCore" Version="3.4.0" /> | ||||
|     <PackageReference Include="Serilog.Sinks.Console" Version="4.0.0-dev-00834" /> | ||||
|     <PackageReference Include="Swashbuckle.AspNetCore" Version="5.0.0-rc5" /> | ||||
|     <PackageReference Include="Swashbuckle.AspNetCore" Version="5.6.3" /> | ||||
|     <!--<PackageReference Include="System.Net.Http.WinHttpHandler" Version="4.6.0-rc1.19456.4" />--> | ||||
|   </ItemGroup> | ||||
| 
 | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| <Project Sdk="Microsoft.NET.Sdk.Web"> | ||||
| 
 | ||||
|   <PropertyGroup> | ||||
|     <TargetFramework>netcoreapp3.1</TargetFramework> | ||||
|     <TargetFramework>net5.0</TargetFramework> | ||||
|     <AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback> | ||||
|     <DockerComposeProjectPath>..\..\..\..\docker-compose.dcproj</DockerComposeProjectPath> | ||||
|     <GenerateErrorForMissingTargetingPacks>false</GenerateErrorForMissingTargetingPacks> | ||||
| @ -16,30 +16,30 @@ | ||||
|   </ItemGroup> | ||||
| 
 | ||||
|   <ItemGroup> | ||||
|     <PackageReference Include="AspNetCore.HealthChecks.AzureServiceBus" Version="3.0.0" /> | ||||
|     <PackageReference Include="AspNetCore.HealthChecks.Rabbitmq" Version="3.0.3" /> | ||||
|     <PackageReference Include="AspNetCore.HealthChecks.Redis" Version="3.0.0" /> | ||||
|     <PackageReference Include="AspNetCore.HealthChecks.UI.Client" Version="3.0.0" /> | ||||
|     <PackageReference Include="Autofac.Extensions.DependencyInjection" Version="5.0.1" /> | ||||
|     <PackageReference Include="Google.Protobuf" Version="3.11.2" /> | ||||
|     <PackageReference Include="Grpc.AspNetCore.Server" Version="2.25.0" /> | ||||
|     <PackageReference Include="Grpc.Tools" Version="2.25.0" PrivateAssets="All" />    | ||||
|     <PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.12.0" /> | ||||
|     <PackageReference Include="Microsoft.ApplicationInsights.DependencyCollector" Version="2.12.0" /> | ||||
|     <PackageReference Include="Microsoft.ApplicationInsights.Kubernetes" Version="1.1.1" /> | ||||
|     <PackageReference Include="AspNetCore.HealthChecks.AzureServiceBus" Version="3.2.2" /> | ||||
|     <PackageReference Include="AspNetCore.HealthChecks.Rabbitmq" Version="3.1.4" /> | ||||
|     <PackageReference Include="AspNetCore.HealthChecks.Redis" Version="3.1.2" /> | ||||
|     <PackageReference Include="AspNetCore.HealthChecks.UI.Client" Version="3.1.2" /> | ||||
|     <PackageReference Include="Autofac.Extensions.DependencyInjection" Version="7.1.0" /> | ||||
|     <PackageReference Include="Google.Protobuf" Version="3.14.0" /> | ||||
|     <PackageReference Include="Grpc.AspNetCore.Server" Version="2.34.0" /> | ||||
|     <PackageReference Include="Grpc.Tools" Version="2.34.0" PrivateAssets="All" />    | ||||
|     <PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.16.0" /> | ||||
|     <PackageReference Include="Microsoft.ApplicationInsights.DependencyCollector" Version="2.16.0" /> | ||||
|     <PackageReference Include="Microsoft.ApplicationInsights.Kubernetes" Version="1.1.3" /> | ||||
|     <PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="3.1.0" /> | ||||
|     <PackageReference Include="Microsoft.AspNetCore.Diagnostics.HealthChecks" Version="2.2.0" /> | ||||
|     <PackageReference Include="Microsoft.AspNetCore.HealthChecks" Version="1.0.0" /> | ||||
|     <PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="3.1.0" /> | ||||
|     <PackageReference Include="Microsoft.Extensions.Configuration.AzureKeyVault" Version="3.1.0" /> | ||||
|     <PackageReference Include="Microsoft.Extensions.Logging.AzureAppServices" Version="3.1.0" /> | ||||
|     <PackageReference Include="Serilog.AspNetCore" Version="3.2.0" /> | ||||
|     <PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="5.0.1" /> | ||||
|     <PackageReference Include="Microsoft.Extensions.Configuration.AzureKeyVault" Version="3.1.10" /> | ||||
|     <PackageReference Include="Microsoft.Extensions.Logging.AzureAppServices" Version="5.0.1" /> | ||||
|     <PackageReference Include="Serilog.AspNetCore" Version="3.4.0" /> | ||||
|     <PackageReference Include="Serilog.Enrichers.Environment" Version="2.1.3" /> | ||||
|     <PackageReference Include="Serilog.Settings.Configuration" Version="3.1.1-dev-00216" /> | ||||
|     <PackageReference Include="Serilog.Sinks.Console" Version="4.0.0-dev-00834" /> | ||||
|     <PackageReference Include="Serilog.Sinks.Http" Version="5.2.0" /> | ||||
|     <PackageReference Include="Serilog.Sinks.Http" Version="7.2.0" /> | ||||
|     <PackageReference Include="Serilog.Sinks.Seq" Version="4.1.0-dev-00166" /> | ||||
|     <PackageReference Include="Swashbuckle.AspNetCore" Version="5.0.0-rc5" /> | ||||
|     <PackageReference Include="Swashbuckle.AspNetCore" Version="5.6.3" /> | ||||
|   </ItemGroup> | ||||
| 
 | ||||
|   <ItemGroup> | ||||
|  | ||||
| @ -1,8 +1,8 @@ | ||||
| FROM mcr.microsoft.com/dotnet/core/aspnet:3.1 AS base | ||||
| FROM mcr.microsoft.com/dotnet/aspnet:5.0 AS base | ||||
| WORKDIR /app | ||||
| EXPOSE 80 | ||||
| 
 | ||||
| FROM mcr.microsoft.com/dotnet/core/sdk:3.1 AS build | ||||
| FROM mcr.microsoft.com/dotnet/sdk:5.0 AS build | ||||
| WORKDIR /src | ||||
| 
 | ||||
| # It's important to keep lines from here down to "COPY . ." identical in all Dockerfiles | ||||
|  | ||||
| @ -2,29 +2,29 @@ | ||||
| 
 | ||||
| namespace Basket.API.Model | ||||
| { | ||||
|     public class BasketCheckout | ||||
|     public record BasketCheckout | ||||
|     { | ||||
|         public string City { get; set; } | ||||
|         public string City { get; init; } | ||||
| 
 | ||||
|         public string Street { get; set; } | ||||
|         public string Street { get; init; } | ||||
| 
 | ||||
|         public string State { get; set; } | ||||
|         public string State { get; init; } | ||||
| 
 | ||||
|         public string Country { get; set; } | ||||
|         public string Country { get; init; } | ||||
| 
 | ||||
|         public string ZipCode { get; set; } | ||||
|         public string ZipCode { get; init; } | ||||
| 
 | ||||
|         public string CardNumber { get; set; } | ||||
|         public string CardNumber { get; init; } | ||||
| 
 | ||||
|         public string CardHolderName { get; set; } | ||||
|         public string CardHolderName { get; init; } | ||||
| 
 | ||||
|         public DateTime CardExpiration { get; set; } | ||||
|         public DateTime CardExpiration { get; init; } | ||||
| 
 | ||||
|         public string CardSecurityNumber { get; set; } | ||||
|         public string CardSecurityNumber { get; init; } | ||||
| 
 | ||||
|         public int CardTypeId { get; set; } | ||||
|         public int CardTypeId { get; init; } | ||||
| 
 | ||||
|         public string Buyer { get; set; } | ||||
|         public string Buyer { get; init; } | ||||
| 
 | ||||
|         public Guid RequestId { get; set; } | ||||
|     } | ||||
|  | ||||
| @ -3,15 +3,15 @@ using System.ComponentModel.DataAnnotations; | ||||
| 
 | ||||
| namespace Microsoft.eShopOnContainers.Services.Basket.API.Model | ||||
| { | ||||
|     public class BasketItem : IValidatableObject | ||||
|     public record BasketItem : IValidatableObject | ||||
|     { | ||||
|         public string Id { get; set; } | ||||
|         public int ProductId { get; set; } | ||||
|         public string ProductName { get; set; } | ||||
|         public string Id { get; init; } | ||||
|         public int ProductId { get; init; } | ||||
|         public string ProductName { get; init; } | ||||
|         public decimal UnitPrice { get; set; } | ||||
|         public decimal OldUnitPrice { get; set; } | ||||
|         public int Quantity { get; set; } | ||||
|         public string PictureUrl { get; set; } | ||||
|         public int Quantity { get; init; } | ||||
|         public string PictureUrl { get; init; } | ||||
|         public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) | ||||
|         { | ||||
|             var results = new List<ValidationResult>(); | ||||
|  | ||||
| @ -2,9 +2,9 @@ | ||||
| 
 | ||||
| namespace Microsoft.eShopOnContainers.Services.Basket.API.Model | ||||
| { | ||||
|     public class CustomerBasket | ||||
|     public record CustomerBasket | ||||
|     { | ||||
|         public string BuyerId { get; set; } | ||||
|         public string BuyerId { get; init; } | ||||
| 
 | ||||
|         public List<BasketItem> Items { get; set; } = new List<BasketItem>(); | ||||
| 
 | ||||
|  | ||||
| @ -3,113 +3,109 @@ using Microsoft.AspNetCore; | ||||
| using Microsoft.AspNetCore.Builder; | ||||
| using Microsoft.AspNetCore.Hosting; | ||||
| using Microsoft.AspNetCore.Server.Kestrel.Core; | ||||
| using Microsoft.eShopOnContainers.Services.Basket.API; | ||||
| using Microsoft.Extensions.Configuration; | ||||
| using Serilog; | ||||
| using System; | ||||
| using System.IO; | ||||
| using System.Net; | ||||
| 
 | ||||
| namespace Microsoft.eShopOnContainers.Services.Basket.API | ||||
| var configuration = GetConfiguration(); | ||||
| 
 | ||||
| Log.Logger = CreateSerilogLogger(configuration); | ||||
| 
 | ||||
| try | ||||
| { | ||||
|     public class Program | ||||
|     { | ||||
|         public static readonly string Namespace = typeof(Program).Namespace; | ||||
|         public static readonly string AppName = Namespace.Substring(Namespace.LastIndexOf('.', Namespace.LastIndexOf('.') - 1) + 1); | ||||
|     Log.Information("Configuring web host ({ApplicationContext})...", Program.AppName); | ||||
|     var host = BuildWebHost(configuration, args); | ||||
| 
 | ||||
|         public static int Main(string[] args) | ||||
|         { | ||||
|             var configuration = GetConfiguration(); | ||||
|     Log.Information("Starting web host ({ApplicationContext})...", Program.AppName); | ||||
|     host.Run(); | ||||
| 
 | ||||
|             Log.Logger = CreateSerilogLogger(configuration); | ||||
| 
 | ||||
|             try | ||||
|             { | ||||
|                 Log.Information("Configuring web host ({ApplicationContext})...", AppName); | ||||
|                 var host = BuildWebHost(configuration, args); | ||||
| 
 | ||||
|                 Log.Information("Starting web host ({ApplicationContext})...", AppName); | ||||
|                 host.Run(); | ||||
| 
 | ||||
|                 return 0; | ||||
|             } | ||||
|             catch (Exception ex) | ||||
|             { | ||||
|                 Log.Fatal(ex, "Program terminated unexpectedly ({ApplicationContext})!", AppName); | ||||
|                 return 1; | ||||
|             } | ||||
|             finally | ||||
|             { | ||||
|                 Log.CloseAndFlush(); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         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; | ||||
|                     }); | ||||
| 
 | ||||
|                 }) | ||||
|                 .ConfigureAppConfiguration(x => x.AddConfiguration(configuration)) | ||||
|                 .UseFailing(options => { | ||||
|                     options.ConfigPath = "/Failing"; | ||||
|                     options.NotFilteredPaths.AddRange(new[] {"/hc","/liveness"}); | ||||
|                 }) | ||||
|                 .UseStartup<Startup>() | ||||
|                 .UseContentRoot(Directory.GetCurrentDirectory()) | ||||
|                 .UseSerilog() | ||||
|                 .Build(); | ||||
| 
 | ||||
|         private static Serilog.ILogger CreateSerilogLogger(IConfiguration configuration) | ||||
|         { | ||||
|             var seqServerUrl = configuration["Serilog:SeqServerUrl"]; | ||||
|             var logstashUrl = configuration["Serilog:LogstashgUrl"]; | ||||
|             return new LoggerConfiguration() | ||||
|                 .MinimumLevel.Verbose() | ||||
|                 .Enrich.WithProperty("ApplicationContext", AppName) | ||||
|                 .Enrich.FromLogContext() | ||||
|                 .WriteTo.Console() | ||||
|                 .WriteTo.Seq(string.IsNullOrWhiteSpace(seqServerUrl) ? "http://seq" : seqServerUrl) | ||||
|                 .WriteTo.Http(string.IsNullOrWhiteSpace(logstashUrl) ? "http://logstash:8080" : logstashUrl) | ||||
|                 .ReadFrom.Configuration(configuration) | ||||
|                 .CreateLogger(); | ||||
|         } | ||||
| 
 | ||||
|         private static IConfiguration GetConfiguration() | ||||
|         { | ||||
|             var builder = new ConfigurationBuilder() | ||||
|                 .SetBasePath(Directory.GetCurrentDirectory()) | ||||
|                 .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true) | ||||
|                 .AddEnvironmentVariables(); | ||||
| 
 | ||||
|             var config = builder.Build(); | ||||
| 
 | ||||
|             if (config.GetValue<bool>("UseVault", false)) | ||||
|             { | ||||
|                 builder.AddAzureKeyVault( | ||||
|                     $"https://{config["Vault:Name"]}.vault.azure.net/", | ||||
|                     config["Vault:ClientId"], | ||||
|                     config["Vault:ClientSecret"]); | ||||
|             } | ||||
| 
 | ||||
|             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); | ||||
|         } | ||||
|     } | ||||
|     return 0; | ||||
| } | ||||
| catch (Exception ex) | ||||
| { | ||||
|     Log.Fatal(ex, "Program terminated unexpectedly ({ApplicationContext})!", Program.AppName); | ||||
|     return 1; | ||||
| } | ||||
| finally | ||||
| { | ||||
|     Log.CloseAndFlush(); | ||||
| } | ||||
| 
 | ||||
| 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; | ||||
|             }); | ||||
| 
 | ||||
|         }) | ||||
|         .ConfigureAppConfiguration(x => x.AddConfiguration(configuration)) | ||||
|         .UseFailing(options => | ||||
|         { | ||||
|             options.ConfigPath = "/Failing"; | ||||
|             options.NotFilteredPaths.AddRange(new[] { "/hc", "/liveness" }); | ||||
|         }) | ||||
|         .UseStartup<Startup>() | ||||
|         .UseContentRoot(Directory.GetCurrentDirectory()) | ||||
|         .UseSerilog() | ||||
|         .Build(); | ||||
| 
 | ||||
| ILogger CreateSerilogLogger(IConfiguration configuration) | ||||
| { | ||||
|     var seqServerUrl = configuration["Serilog:SeqServerUrl"]; | ||||
|     var logstashUrl = configuration["Serilog:LogstashgUrl"]; | ||||
|     return new LoggerConfiguration() | ||||
|         .MinimumLevel.Verbose() | ||||
|         .Enrich.WithProperty("ApplicationContext", Program.AppName) | ||||
|         .Enrich.FromLogContext() | ||||
|         .WriteTo.Console() | ||||
|         .WriteTo.Seq(string.IsNullOrWhiteSpace(seqServerUrl) ? "http://seq" : seqServerUrl) | ||||
|         .WriteTo.Http(string.IsNullOrWhiteSpace(logstashUrl) ? "http://logstash:8080" : logstashUrl) | ||||
|         .ReadFrom.Configuration(configuration) | ||||
|         .CreateLogger(); | ||||
| } | ||||
| 
 | ||||
| IConfiguration GetConfiguration() | ||||
| { | ||||
|     var builder = new ConfigurationBuilder() | ||||
|         .SetBasePath(Directory.GetCurrentDirectory()) | ||||
|         .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true) | ||||
|         .AddEnvironmentVariables(); | ||||
| 
 | ||||
|     var config = builder.Build(); | ||||
| 
 | ||||
|     if (config.GetValue<bool>("UseVault", false)) | ||||
|     { | ||||
|         builder.AddAzureKeyVault( | ||||
|             $"https://{config["Vault:Name"]}.vault.azure.net/", | ||||
|             config["Vault:ClientId"], | ||||
|             config["Vault:ClientSecret"]); | ||||
|     } | ||||
| 
 | ||||
|     return builder.Build(); | ||||
| } | ||||
| 
 | ||||
| (int httpPort, int grpcPort) GetDefinedPorts(IConfiguration config) | ||||
| { | ||||
|     var grpcPort = config.GetValue("GRPC_PORT", 5001); | ||||
|     var port = config.GetValue("PORT", 80); | ||||
|     return (port, grpcPort); | ||||
| } | ||||
| 
 | ||||
| public class Program { | ||||
| 
 | ||||
|     public static string Namespace = typeof(Startup).Namespace; | ||||
|     public static string AppName = Namespace.Substring(Namespace.LastIndexOf('.', Namespace.LastIndexOf('.') - 1) + 1); | ||||
| } | ||||
| @ -1,7 +1,7 @@ | ||||
| <Project Sdk="Microsoft.NET.Sdk"> | ||||
| 
 | ||||
|   <PropertyGroup> | ||||
|     <TargetFramework>netcoreapp3.1</TargetFramework> | ||||
|     <TargetFramework>net5.0</TargetFramework> | ||||
|     <IsPackable>false</IsPackable> | ||||
|   </PropertyGroup> | ||||
| 
 | ||||
| @ -16,11 +16,11 @@ | ||||
|   </ItemGroup> | ||||
| 
 | ||||
|   <ItemGroup> | ||||
|     <PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="3.1.0" /> | ||||
|     <PackageReference Include="Microsoft.AspNetCore.TestHost" Version="3.1.0" /> | ||||
|     <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.4.0" /> | ||||
|     <PackageReference Include="Moq" Version="4.13.1" /> | ||||
|     <PackageReference Include="xunit.runner.visualstudio" Version="2.4.1"> | ||||
|     <PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="5.0.1" /> | ||||
|     <PackageReference Include="Microsoft.AspNetCore.TestHost" Version="5.0.1" /> | ||||
|     <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.8.3" /> | ||||
|     <PackageReference Include="Moq" Version="4.15.2" /> | ||||
|     <PackageReference Include="xunit.runner.visualstudio" Version="2.4.3"> | ||||
|       <PrivateAssets>all</PrivateAssets> | ||||
|       <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets> | ||||
|     </PackageReference> | ||||
|  | ||||
| @ -1,19 +1,19 @@ | ||||
| <Project Sdk="Microsoft.NET.Sdk"> | ||||
| 
 | ||||
|   <PropertyGroup> | ||||
|     <TargetFramework>netcoreapp3.1</TargetFramework> | ||||
|     <TargetFramework>net5.0</TargetFramework> | ||||
|     <GenerateErrorForMissingTargetingPacks>false</GenerateErrorForMissingTargetingPacks> | ||||
|     <IsPackable>false</IsPackable> | ||||
|   </PropertyGroup> | ||||
| 
 | ||||
|   <ItemGroup> | ||||
|     <PackageReference Include="MediatR" Version="7.0.0" /> | ||||
|     <PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="3.1.0" /> | ||||
|     <PackageReference Include="Microsoft.Extensions.Identity.Stores" Version="3.1.0" /> | ||||
|     <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.4.0" /> | ||||
|     <PackageReference Include="Microsoft.NETCore.Platforms" Version="3.1.0" /> | ||||
|     <PackageReference Include="Moq" Version="4.13.1" /> | ||||
|     <PackageReference Include="xunit.runner.visualstudio" Version="2.4.1"> | ||||
|     <PackageReference Include="MediatR" Version="9.0.0" /> | ||||
|     <PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="5.0.1" /> | ||||
|     <PackageReference Include="Microsoft.Extensions.Identity.Stores" Version="5.0.1" /> | ||||
|     <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.8.3" /> | ||||
|     <PackageReference Include="Microsoft.NETCore.Platforms" Version="5.0.0" /> | ||||
|     <PackageReference Include="Moq" Version="4.15.2" /> | ||||
|     <PackageReference Include="xunit.runner.visualstudio" Version="2.4.3"> | ||||
|       <PrivateAssets>all</PrivateAssets> | ||||
|       <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets> | ||||
|     </PackageReference> | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| <Project Sdk="Microsoft.NET.Sdk"> | ||||
| 
 | ||||
|   <PropertyGroup> | ||||
|     <TargetFramework>netcoreapp3.1</TargetFramework> | ||||
|     <TargetFramework>net5.0</TargetFramework> | ||||
|     <GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles> | ||||
|     <GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute> | ||||
|     <GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute> | ||||
| @ -67,10 +67,10 @@ | ||||
|   </ItemGroup> | ||||
| 
 | ||||
|   <ItemGroup> | ||||
|     <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.4.0" /> | ||||
|     <PackageReference Include="Microsoft.AspNetCore.TestHost" Version="3.1.0" /> | ||||
|     <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.8.3" /> | ||||
|     <PackageReference Include="Microsoft.AspNetCore.TestHost" Version="5.0.1" /> | ||||
|     <PackageReference Include="xunit" Version="2.4.1" /> | ||||
|     <PackageReference Include="xunit.runner.visualstudio" Version="2.4.1"> | ||||
|     <PackageReference Include="xunit.runner.visualstudio" Version="2.4.3"> | ||||
|       <PrivateAssets>all</PrivateAssets> | ||||
|       <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets> | ||||
|     </PackageReference> | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user