Merge pull request #2 from sicsbd/dev-asp.netcore2.1enhancements

Update to ASP.NET Core 2.1.3
This commit is contained in:
Rafsanul Hasan 2018-09-01 05:19:21 +06:00 committed by GitHub
commit 9d9d85efa4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
88 changed files with 5448 additions and 5213 deletions

Binary file not shown.

Binary file not shown.

View File

@ -3,7 +3,7 @@
<PropertyGroup Label="Globals"> <PropertyGroup Label="Globals">
<ProjectGuid>fea0c318-ffed-4d39-8781-265718ca43dd</ProjectGuid> <ProjectGuid>fea0c318-ffed-4d39-8781-265718ca43dd</ProjectGuid>
<DockerLaunchBrowser>True</DockerLaunchBrowser> <DockerLaunchBrowser>True</DockerLaunchBrowser>
<DockerServiceUrl>http://localhost:5100</DockerServiceUrl> <DockerServiceUrl>https://localhost:4100</DockerServiceUrl>
<DockerServiceName>webmvc</DockerServiceName> <DockerServiceName>webmvc</DockerServiceName>
<DockerTargetOS>Linux</DockerTargetOS> <DockerTargetOS>Linux</DockerTargetOS>
<ProjectVersion>2.1</ProjectVersion> <ProjectVersion>2.1</ProjectVersion>

View File

@ -30,11 +30,11 @@ services:
identity.api: identity.api:
environment: environment:
- ASPNETCORE_ENVIRONMENT=Development - ASPNETCORE_ENVIRONMENT=Development
- ASPNETCORE_URLS=http://0.0.0.0:80 - ASPNETCORE_URLS=http://0.0.0.0:80;https://+:443
- SpaClient=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5104 - SpaClient=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5104;https://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:4104
- XamarinCallback=http://${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}:5105/xamarincallback #localhost do not work for UWP login, so we have to use "external" IP always - XamarinCallback=http://${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}:5105/xamarincallback #localhost do not work for UWP login, so we have to use "external" IP always
- ConnectionString=${ESHOP_AZURE_IDENTITY_DB:-Server=sql.data;Database=Microsoft.eShopOnContainers.Service.IdentityDb;User Id=sa;Password=Pass@word} - ConnectionString=${ESHOP_AZURE_IDENTITY_DB:-Server=sql.data;Database=Microsoft.eShopOnContainers.Service.IdentityDb;User Id=sa;Password=Pass@word}
- MvcClient=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5100 #Local: You need to open your local dev-machine firewall at range 5100-5110. - MvcClient=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5100;https://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:4100 #Local: You need to open your local dev-machine firewall at range 5100-5110.
- LocationApiClient=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5109 - LocationApiClient=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5109
- MarketingApiClient=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5110 - MarketingApiClient=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5110
- BasketApiClient=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5103 - BasketApiClient=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5103
@ -45,7 +45,11 @@ services:
- ApplicationInsights__InstrumentationKey=${INSTRUMENTATION_KEY} - ApplicationInsights__InstrumentationKey=${INSTRUMENTATION_KEY}
- OrchestratorType=${ORCHESTRATOR_TYPE} - OrchestratorType=${ORCHESTRATOR_TYPE}
ports: ports:
- "5105:80" - "5105:80"
- "4105:443"
volumes:
- ${APPDATA}/ASP.NET/Https:/root/.aspnet/https:rw
- ${APPDATA}/Microsoft/UserSecrets:/root/.microsoft/usersecrets:rw
basket.api: basket.api:
environment: environment:
@ -188,7 +192,7 @@ services:
- ASPNETCORE_ENVIRONMENT=Development - ASPNETCORE_ENVIRONMENT=Development
- IdentityUrl=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5110. - IdentityUrl=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5110.
ports: ports:
- "5200:80" - "5200:80"
volumes: volumes:
- ./src/ApiGateways/Mobile.Bff.Shopping/apigw:${ESHOP_OCELOT_VOLUME_SPEC:-/app/configuration} - ./src/ApiGateways/Mobile.Bff.Shopping/apigw:${ESHOP_OCELOT_VOLUME_SPEC:-/app/configuration}
@ -206,7 +210,7 @@ services:
- ASPNETCORE_ENVIRONMENT=Development - ASPNETCORE_ENVIRONMENT=Development
- IdentityUrl=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5110. - IdentityUrl=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5110.
ports: ports:
- "5202:80" - "5202:80"
volumes: volumes:
- ./src/ApiGateways/Web.Bff.Shopping/apigw:${ESHOP_OCELOT_VOLUME_SPEC:-/app/configuration} - ./src/ApiGateways/Web.Bff.Shopping/apigw:${ESHOP_OCELOT_VOLUME_SPEC:-/app/configuration}
@ -277,7 +281,7 @@ services:
webspa: webspa:
environment: environment:
- ASPNETCORE_ENVIRONMENT=Development - ASPNETCORE_ENVIRONMENT=Development
- ASPNETCORE_URLS=http://0.0.0.0:80 - ASPNETCORE_URLS=http://+:80;https://+:443
- IdentityUrl=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5105 #Local: You need to open your local dev-machine firewall at range 5100-5105. at range 5100-5105. - IdentityUrl=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5105 #Local: You need to open your local dev-machine firewall at range 5100-5105. at range 5100-5105.
- PurchaseUrl=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5202 - PurchaseUrl=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5202
- MarketingUrl=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5203 - MarketingUrl=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5203
@ -293,11 +297,15 @@ services:
- SignalrHubUrl=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5202 - SignalrHubUrl=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5202
ports: ports:
- "5104:80" - "5104:80"
- "4104:443"
volumes:
- ${APPDATA}/ASP.NET/Https:/root/.aspnet/https:rw
- ${APPDATA}/Microsoft/UserSecrets:/root/.microsoft/usersecrets:rw
webmvc: webmvc:
environment: environment:
- ASPNETCORE_ENVIRONMENT=Development - ASPNETCORE_ENVIRONMENT=Development
- ASPNETCORE_URLS=http://0.0.0.0:80 - ASPNETCORE_URLS=http://+:80;https://+:443
- PurchaseUrl=http://webshoppingapigw - PurchaseUrl=http://webshoppingapigw
- IdentityUrl=http://10.0.75.1:5105 # Local Mac: Use http://docker.for.mac.localhost:5105 || Local Windows: Use 10.0.75.1 in a "Docker for Windows" environment, if using "localhost" from browser. || #Remote access: Use ${ESHOP_EXTERNAL_DNS_NAME_OR_IP} if using external IP or DNS name from browser. - IdentityUrl=http://10.0.75.1:5105 # Local Mac: Use http://docker.for.mac.localhost:5105 || Local Windows: Use 10.0.75.1 in a "Docker for Windows" environment, if using "localhost" from browser. || #Remote access: Use ${ESHOP_EXTERNAL_DNS_NAME_OR_IP} if using external IP or DNS name from browser.
- MarketingUrl=http://webmarketingapigw - MarketingUrl=http://webmarketingapigw
@ -314,4 +322,7 @@ services:
- UseLoadTest=${USE_LOADTEST:-False} - UseLoadTest=${USE_LOADTEST:-False}
ports: ports:
- "5100:80" - "5100:80"
- "4100:443"
volumes:
- ${APPDATA}/ASP.NET/Https:/root/.aspnet/https:rw
- ${APPDATA}/Microsoft/UserSecrets:/root/.microsoft/usersecrets:rw

View File

@ -1,8 +1,8 @@
FROM microsoft/dotnet:2.1-aspnetcore-runtime AS base FROM microsoft/dotnet:2.1.3-aspnetcore-runtime AS base
WORKDIR /app WORKDIR /app
EXPOSE 80 EXPOSE 80
FROM microsoft/dotnet:2.1-sdk AS build FROM microsoft/dotnet:2.1.401-sdk AS build
WORKDIR /src WORKDIR /src
COPY src/ApiGateways/ApiGw-Base/OcelotApiGw.csproj src/ApiGateways/ApiGw-Base/ COPY src/ApiGateways/ApiGw-Base/OcelotApiGw.csproj src/ApiGateways/ApiGw-Base/
RUN dotnet restore src/ApiGateways/ApiGw-Base/ RUN dotnet restore src/ApiGateways/ApiGw-Base/

View File

@ -1,15 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk.Web"> <Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup> <PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework> <TargetFramework>netcoreapp2.1</TargetFramework>
</PropertyGroup> <RuntimeFrameworkVersion>2.1.3</RuntimeFrameworkVersion>
</PropertyGroup>
<ItemGroup> <ItemGroup>
<Folder Include="wwwroot\" /> <Folder Include="wwwroot\" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.App" /> <PackageReference Include="Microsoft.AspNetCore.App" Version="2.1.3" />
<PackageReference Include="Ocelot" Version="3.0.0" /> <PackageReference Include="Ocelot" Version="3.0.0" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -13,7 +13,8 @@
"launchBrowser": true, "launchBrowser": true,
"environmentVariables": { "environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development" "ASPNETCORE_ENVIRONMENT": "Development"
} },
"use64Bit": true
}, },
"OcelotApiGw": { "OcelotApiGw": {
"commandName": "Project", "commandName": "Project",

View File

@ -1,8 +1,8 @@
FROM microsoft/dotnet:2.1-aspnetcore-runtime AS base FROM microsoft/dotnet:2.1.3-aspnetcore-runtime AS base
WORKDIR /app WORKDIR /app
EXPOSE 80 EXPOSE 80
FROM microsoft/dotnet:2.1-sdk AS build FROM microsoft/dotnet:2.1.401-sdk AS build
WORKDIR /src WORKDIR /src
COPY . . COPY . .
WORKDIR /src/src/ApiGateways/Mobile.Bff.Shopping/aggregator WORKDIR /src/src/ApiGateways/Mobile.Bff.Shopping/aggregator

View File

@ -1,20 +1,21 @@
<Project Sdk="Microsoft.NET.Sdk.Web"> <Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup> <PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework> <TargetFramework>netcoreapp2.1</TargetFramework>
<AssemblyName>Mobile.Shopping.HttpAggregator</AssemblyName> <RuntimeFrameworkVersion>2.1.3</RuntimeFrameworkVersion>
<RootNamespace>Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator</RootNamespace> <AssemblyName>Mobile.Shopping.HttpAggregator</AssemblyName>
<DockerComposeProjectPath>..\..\..\docker-compose.dcproj</DockerComposeProjectPath> <RootNamespace>Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator</RootNamespace>
</PropertyGroup> <DockerComposeProjectPath>..\..\..\docker-compose.dcproj</DockerComposeProjectPath>
</PropertyGroup>
<ItemGroup> <ItemGroup>
<Folder Include="wwwroot\" /> <Folder Include="wwwroot\" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.App" /> <PackageReference Include="Microsoft.AspNetCore.App" Version="2.1.3" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="1.1.0" /> <PackageReference Include="Swashbuckle.AspNetCore" Version="1.1.0" />
<PackageReference Include="Microsoft.Extensions.Http.Polly" Version="2.1.0" /> <PackageReference Include="Microsoft.Extensions.Http.Polly" Version="2.1.1" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -14,7 +14,8 @@
"launchUrl": "api/values", "launchUrl": "api/values",
"environmentVariables": { "environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development" "ASPNETCORE_ENVIRONMENT": "Development"
} },
"use64Bit": true
}, },
"PurchaseForMvc": { "PurchaseForMvc": {
"commandName": "Project", "commandName": "Project",

View File

@ -19,166 +19,176 @@ using System.Net.Http;
namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator
{ {
public class Startup public class Startup
{ {
public Startup(IConfiguration configuration) public Startup(IConfiguration configuration)
{ {
Configuration = configuration; Configuration = configuration;
} }
public IConfiguration Configuration { get; } public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container. // This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services) public void ConfigureServices(IServiceCollection services)
{ {
services.AddCustomMvc(Configuration) services
.AddCustomAuthentication(Configuration) .AddCustomMvc(Configuration)
.AddHttpServices(); .AddCustomAuthentication(Configuration)
} .AddHttpServices();
//services.AddHttpsRedirection(opts =>
//{
// opts.HttpsPort = 4120;
//});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline. // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{ {
var pathBase = Configuration["PATH_BASE"]; string pathBase = Configuration["PATH_BASE"];
if (!string.IsNullOrEmpty(pathBase)) if (!string.IsNullOrEmpty(pathBase))
{ {
loggerFactory.CreateLogger("init").LogDebug($"Using PATH BASE '{pathBase}'"); loggerFactory.CreateLogger("init").LogDebug($"Using PATH BASE '{pathBase}'");
app.UsePathBase(pathBase); app.UsePathBase(pathBase);
} }
app.UseCors("CorsPolicy"); app.UseCors("CorsPolicy");
if (env.IsDevelopment()) if (env.IsDevelopment())
{ {
app.UseDeveloperExceptionPage(); app.UseDeveloperExceptionPage();
} }
app.UseAuthentication(); app.UseAuthentication();
app.UseMvc(); app.UseMvc();
app.UseSwagger().UseSwaggerUI(c => app.UseSwagger().UseSwaggerUI(c =>
{ {
c.SwaggerEndpoint($"{ (!string.IsNullOrEmpty(pathBase) ? pathBase : string.Empty) }/swagger/v1/swagger.json", "Purchase BFF V1"); c.SwaggerEndpoint($"{ (!string.IsNullOrEmpty(pathBase) ? pathBase : string.Empty) }/swagger/v1/swagger.json", "Purchase BFF V1");
c.ConfigureOAuth2("Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregatorwaggerui", "", "", "Purchase BFF Swagger UI"); c.ConfigureOAuth2("Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregatorwaggerui", "", "", "Purchase BFF Swagger UI");
}); });
} }
} }
public static class ServiceCollectionExtensions public static class ServiceCollectionExtensions
{ {
public static IServiceCollection AddCustomMvc(this IServiceCollection services, IConfiguration configuration) public static IServiceCollection AddCustomMvc(this IServiceCollection services, IConfiguration configuration)
{ {
services.AddOptions(); services.AddOptions();
services.Configure<UrlsConfig>(configuration.GetSection("urls")); services.Configure<UrlsConfig>(configuration.GetSection("urls"));
services.AddMvc(); services
.AddMvc()
.SetCompatibilityVersion(AspNetCore.Mvc.CompatibilityVersion.Version_2_1)
;
services.AddSwaggerGen(options => services.AddSwaggerGen(options =>
{ {
options.DescribeAllEnumsAsStrings(); options.DescribeAllEnumsAsStrings();
options.SwaggerDoc("v1", new Swashbuckle.AspNetCore.Swagger.Info options.SwaggerDoc("v1", new Swashbuckle.AspNetCore.Swagger.Info
{ {
Title = "Shopping Aggregator for Mobile Clients", Title = "Shopping Aggregator for Mobile Clients",
Version = "v1", Version = "v1",
Description = "Shopping Aggregator for Mobile Clients", Description = "Shopping Aggregator for Mobile Clients",
TermsOfService = "Terms Of Service" TermsOfService = "Terms Of Service"
}); });
options.AddSecurityDefinition("oauth2", new OAuth2Scheme options.AddSecurityDefinition("oauth2", new OAuth2Scheme
{ {
Type = "oauth2", Type = "oauth2",
Flow = "implicit", Flow = "implicit",
AuthorizationUrl = $"{configuration.GetValue<string>("IdentityUrlExternal")}/connect/authorize", AuthorizationUrl = $"{configuration.GetValue<string>("IdentityUrlExternal")}/connect/authorize",
TokenUrl = $"{configuration.GetValue<string>("IdentityUrlExternal")}/connect/token", TokenUrl = $"{configuration.GetValue<string>("IdentityUrlExternal")}/connect/token",
Scopes = new Dictionary<string, string>() Scopes = new Dictionary<string, string>()
{ {
{ "mobileshoppingagg", "Shopping Aggregator for Mobile Clients" } { "mobileshoppingagg", "Shopping Aggregator for Mobile Clients" }
} }
}); });
options.OperationFilter<AuthorizeCheckOperationFilter>(); options.OperationFilter<AuthorizeCheckOperationFilter>();
}); });
services.AddCors(options => services.AddCors(options =>
{ {
options.AddPolicy("CorsPolicy", options.AddPolicy("CorsPolicy",
builder => builder.AllowAnyOrigin() builder => builder.AllowAnyOrigin()
.AllowAnyMethod() .AllowAnyMethod()
.AllowAnyHeader() .AllowAnyHeader()
.AllowCredentials()); .AllowCredentials());
}); });
return services; return services;
} }
public static IServiceCollection AddCustomAuthentication(this IServiceCollection services, IConfiguration configuration) public static IServiceCollection AddCustomAuthentication(this IServiceCollection services, IConfiguration configuration)
{ {
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear(); JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
var identityUrl = configuration.GetValue<string>("urls:identity"); var identityUrl = configuration.GetValue<string>("urls:identity");
services.AddAuthentication(options => services.AddAuthentication(options =>
{ {
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(options => }).AddJwtBearer(options =>
{ {
options.Authority = identityUrl; options.Authority = identityUrl;
options.RequireHttpsMetadata = false; options.RequireHttpsMetadata = false;
options.Audience = "mobileshoppingagg"; options.Audience = "mobileshoppingagg";
options.Events = new JwtBearerEvents() options.Events = new JwtBearerEvents()
{ {
OnAuthenticationFailed = async ctx => #pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously
{ OnAuthenticationFailed = async ctx =>
int i = 0; #pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously
}, {
OnTokenValidated = async ctx => },
{ #pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously
int i = 0; OnTokenValidated = async ctx =>
} #pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously
}; {
}); }
};
});
return services; return services;
} }
public static IServiceCollection AddHttpServices(this IServiceCollection services) public static IServiceCollection AddHttpServices(this IServiceCollection services)
{ {
//register delegating handlers //register delegating handlers
services.AddTransient<HttpClientAuthorizationDelegatingHandler>(); services.AddTransient<HttpClientAuthorizationDelegatingHandler>();
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());
services.AddHttpClient<ICatalogService, CatalogService>() services.AddHttpClient<ICatalogService, CatalogService>()
.AddPolicyHandler(GetRetryPolicy()) .AddPolicyHandler(GetRetryPolicy())
.AddPolicyHandler(GetCircuitBreakerPolicy()); .AddPolicyHandler(GetCircuitBreakerPolicy());
services.AddHttpClient<IOrderApiClient, OrderApiClient>() services.AddHttpClient<IOrderApiClient, OrderApiClient>()
.AddPolicyHandler(GetRetryPolicy()) .AddPolicyHandler(GetRetryPolicy())
.AddPolicyHandler(GetCircuitBreakerPolicy()); .AddPolicyHandler(GetCircuitBreakerPolicy());
return services; return services;
} }
static IAsyncPolicy<HttpResponseMessage> GetRetryPolicy() static IAsyncPolicy<HttpResponseMessage> GetRetryPolicy()
{ {
return HttpPolicyExtensions return HttpPolicyExtensions
.HandleTransientHttpError() .HandleTransientHttpError()
.OrResult(msg => msg.StatusCode == System.Net.HttpStatusCode.NotFound) .OrResult(msg => msg.StatusCode == System.Net.HttpStatusCode.NotFound)
.WaitAndRetryAsync(6, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt))); .WaitAndRetryAsync(6, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)));
} }
static IAsyncPolicy<HttpResponseMessage> GetCircuitBreakerPolicy() static IAsyncPolicy<HttpResponseMessage> GetCircuitBreakerPolicy()
{ {
return HttpPolicyExtensions return HttpPolicyExtensions
.HandleTransientHttpError() .HandleTransientHttpError()
.CircuitBreakerAsync(5, TimeSpan.FromSeconds(30)); .CircuitBreakerAsync(5, TimeSpan.FromSeconds(30));
} }
} }
} }

View File

@ -1,15 +1,23 @@
{ {
"Logging": { "Logging": {
"IncludeScopes": false, "IncludeScopes": false,
"Debug": { "Debug": {
"LogLevel": { "LogLevel": {
"Default": "Warning" "Default": "Warning"
} }
}, },
"Console": { "Console": {
"LogLevel": { "LogLevel": {
"Default": "Warning" "Default": "Warning"
} }
} }
} },
"Kestrel": {
"Certificates": {
"Default": {
"Path": "./synergydev.pfx",
"Password": "RH@ssl2018"
}
}
}
} }

View File

@ -1,8 +1,8 @@
FROM microsoft/dotnet:2.1-aspnetcore-runtime AS base FROM microsoft/dotnet:2.1.3-aspnetcore-runtime AS base
WORKDIR /app WORKDIR /app
EXPOSE 80 EXPOSE 80
FROM microsoft/dotnet:2.1-sdk AS build FROM microsoft/dotnet:2.1.401-sdk AS build
WORKDIR /src WORKDIR /src
COPY . . COPY . .
WORKDIR /src/src/ApiGateways/Web.Bff.Shopping/aggregator WORKDIR /src/src/ApiGateways/Web.Bff.Shopping/aggregator

View File

@ -14,7 +14,8 @@
"launchUrl": "api/values", "launchUrl": "api/values",
"environmentVariables": { "environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development" "ASPNETCORE_ENVIRONMENT": "Development"
} },
"use64Bit": true
}, },
"PurchaseForMvc": { "PurchaseForMvc": {
"commandName": "Project", "commandName": "Project",

View File

@ -11,7 +11,6 @@ using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Polly; using Polly;
using Polly.Extensions.Http; using Polly.Extensions.Http;
using Polly.Timeout;
using Swashbuckle.AspNetCore.Swagger; using Swashbuckle.AspNetCore.Swagger;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
@ -20,168 +19,178 @@ using System.Net.Http;
namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator
{ {
public class Startup public class Startup
{ {
public Startup(IConfiguration configuration) public Startup(IConfiguration configuration)
{ {
Configuration = configuration; Configuration = configuration;
} }
public IConfiguration Configuration { get; } public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container. // This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services) public void ConfigureServices(IServiceCollection services)
{ {
services.AddCustomMvc(Configuration) services
.AddCustomAuthentication(Configuration) .AddCustomMvc(Configuration)
.AddApplicationServices(); .AddCustomAuthentication(Configuration)
} .AddApplicationServices();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline. // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{ {
var pathBase = Configuration["PATH_BASE"]; var pathBase = Configuration["PATH_BASE"];
if (!string.IsNullOrEmpty(pathBase)) if (!string.IsNullOrEmpty(pathBase))
{ {
loggerFactory.CreateLogger("init").LogDebug($"Using PATH BASE '{pathBase}'"); loggerFactory.CreateLogger("init").LogDebug($"Using PATH BASE '{pathBase}'");
app.UsePathBase(pathBase); app.UsePathBase(pathBase);
} }
app.UseCors("CorsPolicy"); app.UseCors("CorsPolicy");
if (env.IsDevelopment()) if (env.IsDevelopment())
{ {
app.UseDeveloperExceptionPage(); app.UseDeveloperExceptionPage();
} }
app.UseAuthentication();
app.UseAuthentication(); app.UseMvc();
app.UseMvc(); app.UseSwagger().UseSwaggerUI(c =>
{
app.UseSwagger().UseSwaggerUI(c => c.SwaggerEndpoint($"{ (!string.IsNullOrEmpty(pathBase) ? pathBase : string.Empty) }/swagger/v1/swagger.json", "Purchase BFF V1");
{ //c.ConfigureOAuth2("Microsoft.eShopOnContainers.Web.Shopping.HttpAggregatorwaggerui", "", "", "Purchase BFF Swagger UI");
c.SwaggerEndpoint($"{ (!string.IsNullOrEmpty(pathBase) ? pathBase : string.Empty) }/swagger/v1/swagger.json", "Purchase BFF V1"); });
//c.ConfigureOAuth2("Microsoft.eShopOnContainers.Web.Shopping.HttpAggregatorwaggerui", "", "", "Purchase BFF Swagger UI");
});
} }
} }
public static class ServiceCollectionExtensions public static class ServiceCollectionExtensions
{ {
public static IServiceCollection AddCustomAuthentication(this IServiceCollection services, IConfiguration configuration) public static IServiceCollection AddCustomAuthentication(this IServiceCollection services, IConfiguration configuration)
{ {
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear(); JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
var identityUrl = configuration.GetValue<string>("urls:identity"); string identityUrl = configuration.GetValue<string>("urls:identity");
services.AddAuthentication(options => services.AddAuthentication(options =>
{ {
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(options => })
{ .AddJwtBearer(options =>
options.Authority = identityUrl; {
options.RequireHttpsMetadata = false; options.Authority = identityUrl;
options.Audience = "webshoppingagg"; options.RequireHttpsMetadata = false;
options.Events = new JwtBearerEvents() options.Audience = "webshoppingagg";
{ options.Events = new JwtBearerEvents()
OnAuthenticationFailed = async ctx => {
{ #pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously
int i = 0; OnAuthenticationFailed = async ctx =>
}, #pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously
OnTokenValidated = async ctx => {
{ },
int i = 0; #pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously
} OnTokenValidated = async ctx =>
}; #pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously
}); {
}
};
});
return services; return services;
} }
public static IServiceCollection AddCustomMvc(this IServiceCollection services, IConfiguration configuration) public static IServiceCollection AddCustomMvc(this IServiceCollection services, IConfiguration configuration)
{ {
services.AddOptions(); services.AddOptions();
services.Configure<UrlsConfig>(configuration.GetSection("urls")); services.Configure<UrlsConfig>(configuration.GetSection("urls"));
services.AddMvc(); services
.AddMvc()
.SetCompatibilityVersion(AspNetCore.Mvc.CompatibilityVersion.Version_2_1)
;
services.AddSwaggerGen(options => services.AddSwaggerGen(options =>
{ {
options.DescribeAllEnumsAsStrings(); options.DescribeAllEnumsAsStrings();
options.SwaggerDoc("v1", new Swashbuckle.AspNetCore.Swagger.Info options.SwaggerDoc("v1", new Info
{ {
Title = "Shopping Aggregator for Web Clients", Title = "Shopping Aggregator for Web Clients",
Version = "v1", Version = "v1",
Description = "Shopping Aggregator for Web Clients", Description = "Shopping Aggregator for Web Clients",
TermsOfService = "Terms Of Service" TermsOfService = "Terms Of Service"
}); });
options.AddSecurityDefinition("oauth2", new OAuth2Scheme options.AddSecurityDefinition("oauth2", new OAuth2Scheme
{ {
Type = "oauth2", Type = "oauth2",
Flow = "implicit", Flow = "implicit",
AuthorizationUrl = $"{configuration.GetValue<string>("IdentityUrlExternal")}/connect/authorize", AuthorizationUrl = $"{configuration.GetValue<string>("IdentityUrlExternal")}/connect/authorize",
TokenUrl = $"{configuration.GetValue<string>("IdentityUrlExternal")}/connect/token", TokenUrl = $"{configuration.GetValue<string>("IdentityUrlExternal")}/connect/token",
Scopes = new Dictionary<string, string>() Scopes = new Dictionary<string, string>()
{ {
{ "webshoppingagg", "Shopping Aggregator for Web Clients" } { "webshoppingagg", "Shopping Aggregator for Web Clients" }
} }
}); });
options.OperationFilter<AuthorizeCheckOperationFilter>(); options.OperationFilter<AuthorizeCheckOperationFilter>();
}); });
services.AddCors(options => services.AddCors(options =>
{ {
options.AddPolicy("CorsPolicy", options
builder => builder.AllowAnyOrigin() .AddPolicy(
.AllowAnyMethod() "CorsPolicy",
.AllowAnyHeader() builder =>
.AllowCredentials()); builder
}); .AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials());
});
return services; return services;
} }
public static IServiceCollection AddApplicationServices(this IServiceCollection services) public static IServiceCollection AddApplicationServices(this IServiceCollection services)
{ {
//register delegating handlers //register delegating handlers
services.AddTransient<HttpClientAuthorizationDelegatingHandler>(); services.AddTransient<HttpClientAuthorizationDelegatingHandler>();
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>(); services.AddHttpContextAccessor();
//register http services //register http services
services.AddHttpClient<IBasketService, BasketService>()
.AddHttpMessageHandler<HttpClientAuthorizationDelegatingHandler>()
.AddPolicyHandler(GetRetryPolicy())
.AddPolicyHandler(GetCircuitBreakerPolicy());
services.AddHttpClient<ICatalogService, CatalogService>() services.AddHttpClient<IBasketService, BasketService>()
.AddPolicyHandler(GetRetryPolicy()) .AddHttpMessageHandler<HttpClientAuthorizationDelegatingHandler>()
.AddPolicyHandler(GetCircuitBreakerPolicy()); .AddPolicyHandler(GetRetryPolicy())
.AddPolicyHandler(GetCircuitBreakerPolicy());
services.AddHttpClient<IOrderApiClient, OrderApiClient>() services.AddHttpClient<ICatalogService, CatalogService>()
.AddHttpMessageHandler<HttpClientAuthorizationDelegatingHandler>() .AddPolicyHandler(GetRetryPolicy())
.AddPolicyHandler(GetRetryPolicy()) .AddPolicyHandler(GetCircuitBreakerPolicy());
.AddPolicyHandler(GetCircuitBreakerPolicy());
services.AddHttpClient<IOrderApiClient, OrderApiClient>()
.AddHttpMessageHandler<HttpClientAuthorizationDelegatingHandler>()
.AddPolicyHandler(GetRetryPolicy())
.AddPolicyHandler(GetCircuitBreakerPolicy());
return services; return services;
} }
static IAsyncPolicy<HttpResponseMessage> GetRetryPolicy() static IAsyncPolicy<HttpResponseMessage> GetRetryPolicy()
{ {
return HttpPolicyExtensions return HttpPolicyExtensions
.HandleTransientHttpError() .HandleTransientHttpError()
.OrResult(msg => msg.StatusCode == System.Net.HttpStatusCode.NotFound) .OrResult(msg => msg.StatusCode == System.Net.HttpStatusCode.NotFound)
.WaitAndRetryAsync(6, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt))); .WaitAndRetryAsync(6, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)));
} }
static IAsyncPolicy<HttpResponseMessage> GetCircuitBreakerPolicy() static IAsyncPolicy<HttpResponseMessage> GetCircuitBreakerPolicy()
{ {
return HttpPolicyExtensions return HttpPolicyExtensions
.HandleTransientHttpError() .HandleTransientHttpError()
.CircuitBreakerAsync(5, TimeSpan.FromSeconds(30)); .CircuitBreakerAsync(5, TimeSpan.FromSeconds(30));
} }
} }
} }

View File

@ -1,21 +1,23 @@
<Project Sdk="Microsoft.NET.Sdk.Web"> <Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup> <PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework> <TargetFramework>netcoreapp2.1</TargetFramework>
<AssemblyName>Web.Shopping.HttpAggregator</AssemblyName> <RuntimeFrameworkVersion>2.1.3</RuntimeFrameworkVersion>
<RootNamespace>Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator</RootNamespace> <AssemblyName>Web.Shopping.HttpAggregator</AssemblyName>
<DockerComposeProjectPath>..\..\..\docker-compose.dcproj</DockerComposeProjectPath> <RootNamespace>Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator</RootNamespace>
</PropertyGroup> <DockerComposeProjectPath>..\..\..\docker-compose.dcproj</DockerComposeProjectPath>
<UserSecretsId>0890cb23-79b5-408d-9aeb-13e6ff218d71</UserSecretsId>
</PropertyGroup>
<ItemGroup> <ItemGroup>
<Folder Include="wwwroot\" /> <Folder Include="wwwroot\" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.App" Version="2.1.0" /> <PackageReference Include="Microsoft.AspNetCore.App" Version="2.1.3" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="2.4.0" /> <PackageReference Include="Swashbuckle.AspNetCore" Version="2.4.0" />
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerUi" Version="2.4.0" /> <PackageReference Include="Swashbuckle.AspNetCore.SwaggerUi" Version="2.4.0" />
<PackageReference Include="Microsoft.Extensions.Http.Polly" Version="2.1.0" /> <PackageReference Include="Microsoft.Extensions.Http.Polly" Version="2.1.1" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -6,10 +6,10 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="2.1.0" /> <PackageReference Include="Microsoft.EntityFrameworkCore" Version="2.1.2" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="2.1.0" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="2.1.2" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="2.1.0" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="2.1.2" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="2.1.0" /> <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="2.1.2" />
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" /> <PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@ -13,7 +13,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Hosting" Version="2.1.0" /> <PackageReference Include="Microsoft.AspNetCore.Hosting" Version="2.1.1" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -16,11 +16,11 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Hosting" Version="2.1.0" /> <PackageReference Include="Microsoft.AspNetCore.Hosting" Version="2.1.1" />
<PackageReference Include="System.Threading.Tasks.Parallel" Version="4.3.0" /> <PackageReference Include="System.Threading.Tasks.Parallel" Version="4.3.0" />
<PackageReference Include="System.Threading.Thread" Version="4.3.0" /> <PackageReference Include="System.Threading.Thread" Version="4.3.0" />
<PackageReference Include="System.Threading.Tasks.Extensions" Version="4.5.0" /> <PackageReference Include="System.Threading.Tasks.Extensions" Version="4.5.1" />
<PackageReference Include="WindowsAzure.Storage" Version="9.1.0" /> <PackageReference Include="WindowsAzure.Storage" Version="9.3.1" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -9,12 +9,12 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.Extensions.Logging" Version="2.1.0" /> <PackageReference Include="Microsoft.Extensions.Logging" Version="2.1.1" />
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" /> <PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
<PackageReference Include="System.Diagnostics.Process" Version="4.3.0" /> <PackageReference Include="System.Diagnostics.Process" Version="4.3.0" />
<PackageReference Include="System.Threading.Tasks.Parallel" Version="4.3.0" /> <PackageReference Include="System.Threading.Tasks.Parallel" Version="4.3.0" />
<PackageReference Include="System.Threading.Thread" Version="4.3.0" /> <PackageReference Include="System.Threading.Thread" Version="4.3.0" />
<PackageReference Include="System.Threading.Tasks.Extensions" Version="4.5.0" /> <PackageReference Include="System.Threading.Tasks.Extensions" Version="4.5.1" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -6,7 +6,7 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="Polly" Version="6.0.1" /> <PackageReference Include="Polly" Version="6.0.1" />
<PackageReference Include="Microsoft.AspNetCore.App" Version="2.1.0" /> <PackageReference Include="Microsoft.AspNetCore.App" Version="2.1.3" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -1,36 +1,37 @@
<Project Sdk="Microsoft.NET.Sdk.Web"> <Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup> <PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework> <TargetFramework>netcoreapp2.1</TargetFramework>
<AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback> <RuntimeFrameworkVersion>2.1.3</RuntimeFrameworkVersion>
<DockerComposeProjectPath>..\..\..\..\docker-compose.dcproj</DockerComposeProjectPath> <AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback>
</PropertyGroup> <DockerComposeProjectPath>..\..\..\..\docker-compose.dcproj</DockerComposeProjectPath>
</PropertyGroup>
<ItemGroup> <ItemGroup>
<Content Update="web.config"> <Content Update="web.config">
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory> <CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
</Content> </Content>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.2.1" /> <PackageReference Include="Autofac.Extensions.DependencyInjection" Version="4.2.1" />
<PackageReference Include="Microsoft.ApplicationInsights.DependencyCollector" Version="2.6.1" /> <PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.4.1" />
<PackageReference Include="Microsoft.ApplicationInsights.Kubernetes" Version="1.0.0-beta8" /> <PackageReference Include="Microsoft.ApplicationInsights.DependencyCollector" Version="2.7.2" />
<PackageReference Include="Microsoft.ApplicationInsights.ServiceFabric" Version="2.1.1-beta1" /> <PackageReference Include="Microsoft.ApplicationInsights.Kubernetes" Version="1.0.0-beta9" />
<PackageReference Include="Microsoft.Extensions.Configuration.AzureKeyVault" Version="2.1.0" /> <PackageReference Include="Microsoft.ApplicationInsights.ServiceFabric" Version="2.1.1" />
<PackageReference Include="Microsoft.AspNetCore.App" Version="2.1.0" /> <PackageReference Include="Microsoft.Extensions.Configuration.AzureKeyVault" Version="2.1.1" />
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="4.2.1" /> <PackageReference Include="Microsoft.AspNetCore.App" Version="2.1.3" />
<PackageReference Include="Microsoft.Extensions.Logging.AzureAppServices" Version="2.1.0" /> <PackageReference Include="Microsoft.Extensions.Logging.AzureAppServices" Version="2.1.1" />
<PackageReference Include="StackExchange.Redis.StrongName" Version="1.2.4" /> <PackageReference Include="StackExchange.Redis.StrongName" Version="1.2.4" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="2.4.0" /> <PackageReference Include="Swashbuckle.AspNetCore" Version="2.4.0" />
</ItemGroup> </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" />
<ProjectReference Include="..\..\..\BuildingBlocks\EventBus\EventBus\EventBus.csproj" /> <ProjectReference Include="..\..\..\BuildingBlocks\EventBus\EventBus\EventBus.csproj" />
<ProjectReference Include="..\..\..\BuildingBlocks\HealthChecks\src\Microsoft.AspNetCore.HealthChecks\Microsoft.AspNetCore.HealthChecks.csproj" /> <ProjectReference Include="..\..\..\BuildingBlocks\HealthChecks\src\Microsoft.AspNetCore.HealthChecks\Microsoft.AspNetCore.HealthChecks.csproj" />
<ProjectReference Include="..\..\..\BuildingBlocks\HealthChecks\src\Microsoft.Extensions.HealthChecks\Microsoft.Extensions.HealthChecks.csproj" /> <ProjectReference Include="..\..\..\BuildingBlocks\HealthChecks\src\Microsoft.Extensions.HealthChecks\Microsoft.Extensions.HealthChecks.csproj" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -1,8 +1,8 @@
FROM microsoft/dotnet:2.1-aspnetcore-runtime AS base FROM microsoft/dotnet:2.1.3-aspnetcore-runtime AS base
WORKDIR /app WORKDIR /app
EXPOSE 80 EXPOSE 80
FROM microsoft/dotnet:2.1-sdk AS build FROM microsoft/dotnet:2.1.401-sdk AS build
WORKDIR /src WORKDIR /src
COPY . . COPY . .
WORKDIR /src/src/Services/Basket/Basket.API WORKDIR /src/src/Services/Basket/Basket.API

View File

@ -14,7 +14,8 @@
"launchUrl": "swagger", "launchUrl": "swagger",
"environmentVariables": { "environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development" "ASPNETCORE_ENVIRONMENT": "Development"
} },
"use64Bit": true
}, },
"Microsoft.eShopOnContainers.Services.Basket.API": { "Microsoft.eShopOnContainers.Services.Basket.API": {
"commandName": "Project", "commandName": "Project",

View File

@ -34,281 +34,283 @@ using System.Threading.Tasks;
namespace Microsoft.eShopOnContainers.Services.Basket.API namespace Microsoft.eShopOnContainers.Services.Basket.API
{ {
public class Startup public class Startup
{ {
public Startup(IConfiguration configuration) public Startup(IConfiguration configuration)
{ {
Configuration = configuration; Configuration = configuration;
} }
public IConfiguration Configuration { get; } public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container. // This method gets called by the runtime. Use this method to add services to the container.
public IServiceProvider ConfigureServices(IServiceCollection services) public IServiceProvider ConfigureServices(IServiceCollection services)
{ {
RegisterAppInsights(services); RegisterAppInsights(services);
// Add framework services. // Add framework services.
services.AddMvc(options => services.AddMvc(options =>
{ {
options.Filters.Add(typeof(HttpGlobalExceptionFilter)); options.Filters.Add(typeof(HttpGlobalExceptionFilter));
options.Filters.Add(typeof(ValidateModelStateFilter)); options.Filters.Add(typeof(ValidateModelStateFilter));
})
.AddControllersAsServices()
.SetCompatibilityVersion(AspNetCore.Mvc.CompatibilityVersion.Version_2_1)
;
}).AddControllersAsServices(); ConfigureAuthService(services);
ConfigureAuthService(services); services.AddHealthChecks(checks =>
{
checks.AddValueTaskCheck("HTTP Endpoint", () => new ValueTask<IHealthCheckResult>(HealthCheckResult.Healthy("Ok")),
TimeSpan.Zero //No cache for this HealthCheck, better just for demos
);
});
services.AddHealthChecks(checks => services.Configure<BasketSettings>(Configuration);
{
checks.AddValueTaskCheck("HTTP Endpoint", () => new ValueTask<IHealthCheckResult>(HealthCheckResult.Healthy("Ok")),
TimeSpan.Zero //No cache for this HealthCheck, better just for demos
);
});
services.Configure<BasketSettings>(Configuration); //By connecting here we are making sure that our service
//cannot start until redis is ready. This might slow down startup,
//but given that there is a delay on resolving the ip address
//and then creating the connection it seems reasonable to move
//that cost to startup instead of having the first request pay the
//penalty.
services.AddSingleton(sp =>
{
var settings = sp.GetRequiredService<IOptions<BasketSettings>>().Value;
var configuration = ConfigurationOptions.Parse(settings.ConnectionString, true);
//By connecting here we are making sure that our service configuration.ResolveDns = true;
//cannot start until redis is ready. This might slow down startup,
//but given that there is a delay on resolving the ip address
//and then creating the connection it seems reasonable to move
//that cost to startup instead of having the first request pay the
//penalty.
services.AddSingleton<ConnectionMultiplexer>(sp =>
{
var settings = sp.GetRequiredService<IOptions<BasketSettings>>().Value;
var configuration = ConfigurationOptions.Parse(settings.ConnectionString, true);
configuration.ResolveDns = true; return ConnectionMultiplexer.Connect(configuration);
});
return ConnectionMultiplexer.Connect(configuration);
});
if (Configuration.GetValue<bool>("AzureServiceBusEnabled")) if (Configuration.GetValue<bool>("AzureServiceBusEnabled"))
{ {
services.AddSingleton<IServiceBusPersisterConnection>(sp => services.AddSingleton<IServiceBusPersisterConnection>(sp =>
{ {
var logger = sp.GetRequiredService<ILogger<DefaultServiceBusPersisterConnection>>(); var logger = sp.GetRequiredService<ILogger<DefaultServiceBusPersisterConnection>>();
var serviceBusConnectionString = Configuration["EventBusConnection"]; var serviceBusConnectionString = Configuration["EventBusConnection"];
var serviceBusConnection = new ServiceBusConnectionStringBuilder(serviceBusConnectionString); var serviceBusConnection = new ServiceBusConnectionStringBuilder(serviceBusConnectionString);
return new DefaultServiceBusPersisterConnection(serviceBusConnection, logger); return new DefaultServiceBusPersisterConnection(serviceBusConnection, logger);
}); });
} }
else else
{ {
services.AddSingleton<IRabbitMQPersistentConnection>(sp => services.AddSingleton<IRabbitMQPersistentConnection>(sp =>
{ {
var logger = sp.GetRequiredService<ILogger<DefaultRabbitMQPersistentConnection>>(); var logger = sp.GetRequiredService<ILogger<DefaultRabbitMQPersistentConnection>>();
var factory = new ConnectionFactory() var factory = new ConnectionFactory()
{ {
HostName = Configuration["EventBusConnection"] HostName = Configuration["EventBusConnection"]
}; };
if (!string.IsNullOrEmpty(Configuration["EventBusUserName"])) if (!string.IsNullOrEmpty(Configuration["EventBusUserName"]))
{ {
factory.UserName = Configuration["EventBusUserName"]; factory.UserName = Configuration["EventBusUserName"];
} }
if (!string.IsNullOrEmpty(Configuration["EventBusPassword"])) if (!string.IsNullOrEmpty(Configuration["EventBusPassword"]))
{ {
factory.Password = Configuration["EventBusPassword"]; factory.Password = Configuration["EventBusPassword"];
} }
var retryCount = 5; var retryCount = 5;
if (!string.IsNullOrEmpty(Configuration["EventBusRetryCount"])) if (!string.IsNullOrEmpty(Configuration["EventBusRetryCount"]))
{ {
retryCount = int.Parse(Configuration["EventBusRetryCount"]); retryCount = int.Parse(Configuration["EventBusRetryCount"]);
} }
return new DefaultRabbitMQPersistentConnection(factory, logger, retryCount); return new DefaultRabbitMQPersistentConnection(factory, logger, retryCount);
}); });
} }
RegisterEventBus(services); RegisterEventBus(services);
services.AddSwaggerGen(options => services.AddSwaggerGen(options =>
{ {
options.DescribeAllEnumsAsStrings(); options.DescribeAllEnumsAsStrings();
options.SwaggerDoc("v1", new Info options.SwaggerDoc("v1", new Info
{ {
Title = "Basket HTTP API", Title = "Basket HTTP API",
Version = "v1", Version = "v1",
Description = "The Basket Service HTTP API", Description = "The Basket Service HTTP API",
TermsOfService = "Terms Of Service" TermsOfService = "Terms Of Service"
}); });
options.AddSecurityDefinition("oauth2", new OAuth2Scheme options.AddSecurityDefinition("oauth2", new OAuth2Scheme
{ {
Type = "oauth2", Type = "oauth2",
Flow = "implicit", Flow = "implicit",
AuthorizationUrl = $"{Configuration.GetValue<string>("IdentityUrlExternal")}/connect/authorize", AuthorizationUrl = $"{Configuration.GetValue<string>("IdentityUrlExternal")}/connect/authorize",
TokenUrl = $"{Configuration.GetValue<string>("IdentityUrlExternal")}/connect/token", TokenUrl = $"{Configuration.GetValue<string>("IdentityUrlExternal")}/connect/token",
Scopes = new Dictionary<string, string>() Scopes = new Dictionary<string, string>()
{ {
{ "basket", "Basket API" } { "basket", "Basket API" }
} }
}); });
options.OperationFilter<AuthorizeCheckOperationFilter>(); options.OperationFilter<AuthorizeCheckOperationFilter>();
}); });
services.AddCors(options => services.AddCors(options =>
{ {
options.AddPolicy("CorsPolicy", options.AddPolicy("CorsPolicy",
builder => builder.AllowAnyOrigin() builder => builder.AllowAnyOrigin()
.AllowAnyMethod() .AllowAnyMethod()
.AllowAnyHeader() .AllowAnyHeader()
.AllowCredentials()); .AllowCredentials());
}); });
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>(); services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.AddTransient<IBasketRepository, RedisBasketRepository>(); services.AddTransient<IBasketRepository, RedisBasketRepository>();
services.AddTransient<IIdentityService, IdentityService>(); services.AddTransient<IIdentityService, IdentityService>();
services.AddOptions(); services.AddOptions();
var container = new ContainerBuilder(); var container = new ContainerBuilder();
container.Populate(services); container.Populate(services);
return new AutofacServiceProvider(container.Build()); return new AutofacServiceProvider(container.Build());
} }
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
loggerFactory.AddAzureWebAppDiagnostics();
loggerFactory.AddApplicationInsights(app.ApplicationServices, LogLevel.Trace);
var pathBase = Configuration["PATH_BASE"]; // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
if (!string.IsNullOrEmpty(pathBase)) public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{ {
app.UsePathBase(pathBase); loggerFactory.AddAzureWebAppDiagnostics();
} loggerFactory.AddApplicationInsights(app.ApplicationServices, LogLevel.Trace);
var pathBase = Configuration["PATH_BASE"];
if (!string.IsNullOrEmpty(pathBase))
{
app.UsePathBase(pathBase);
}
#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously #pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously
app.Map("/liveness", lapp => lapp.Run(async ctx => ctx.Response.StatusCode = 200)); app.Map("/liveness", lapp => lapp.Run(async ctx => ctx.Response.StatusCode = 200));
#pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously #pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously
app.UseStaticFiles(); app.UseStaticFiles();
app.UseCors("CorsPolicy"); app.UseCors("CorsPolicy");
ConfigureAuth(app); ConfigureAuth(app);
app.UseMvcWithDefaultRoute(); app.UseMvcWithDefaultRoute();
app.UseSwagger() app.UseSwagger()
.UseSwaggerUI(c => .UseSwaggerUI(c =>
{ {
c.SwaggerEndpoint($"{ (!string.IsNullOrEmpty(pathBase) ? pathBase : string.Empty) }/swagger/v1/swagger.json", "Basket.API V1"); c.SwaggerEndpoint($"{ (!string.IsNullOrEmpty(pathBase) ? pathBase : string.Empty) }/swagger/v1/swagger.json", "Basket.API V1");
c.OAuthClientId ("basketswaggerui"); c.OAuthClientId("basketswaggerui");
c.OAuthAppName("Basket Swagger UI"); c.OAuthAppName("Basket Swagger UI");
}); });
ConfigureEventBus(app); ConfigureEventBus(app);
} }
private void RegisterAppInsights(IServiceCollection services) private void RegisterAppInsights(IServiceCollection services)
{ {
services.AddApplicationInsightsTelemetry(Configuration); services.AddApplicationInsightsTelemetry(Configuration);
var orchestratorType = Configuration.GetValue<string>("OrchestratorType"); var orchestratorType = Configuration.GetValue<string>("OrchestratorType");
if (orchestratorType?.ToUpper() == "K8S")
{
// Enable K8s telemetry initializer
services.EnableKubernetes();
}
if (orchestratorType?.ToUpper() == "SF")
{
// Enable SF telemetry initializer
services.AddSingleton<ITelemetryInitializer>((serviceProvider) =>
new FabricTelemetryInitializer());
}
}
private void ConfigureAuthService(IServiceCollection services) if (orchestratorType?.ToUpper() == "K8S")
{ {
// prevent from mapping "sub" claim to nameidentifier. // Enable K8s telemetry initializer
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear(); services.EnableKubernetes();
}
if (orchestratorType?.ToUpper() == "SF")
{
// Enable SF telemetry initializer
services.AddSingleton<ITelemetryInitializer>((serviceProvider) =>
new FabricTelemetryInitializer());
}
}
var identityUrl = Configuration.GetValue<string>("IdentityUrl"); private void ConfigureAuthService(IServiceCollection services)
{
services.AddAuthentication(options => // prevent from mapping "sub" claim to nameidentifier.
{ JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(options => var identityUrl = Configuration.GetValue<string>("IdentityUrl");
{
options.Authority = identityUrl;
options.RequireHttpsMetadata = false;
options.Audience = "basket";
});
}
protected virtual void ConfigureAuth(IApplicationBuilder app) services.AddAuthentication(options =>
{ {
if (Configuration.GetValue<bool>("UseLoadTest")) options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
{ options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
app.UseMiddleware<ByPassAuthMiddleware>();
}
app.UseAuthentication(); }).AddJwtBearer(options =>
} {
options.Authority = identityUrl;
options.RequireHttpsMetadata = false;
options.Audience = "basket";
});
}
private void RegisterEventBus(IServiceCollection services) protected virtual void ConfigureAuth(IApplicationBuilder app)
{ {
var subscriptionClientName = Configuration["SubscriptionClientName"]; if (Configuration.GetValue<bool>("UseLoadTest"))
{
app.UseMiddleware<ByPassAuthMiddleware>();
}
if (Configuration.GetValue<bool>("AzureServiceBusEnabled")) app.UseAuthentication();
{ }
services.AddSingleton<IEventBus, EventBusServiceBus>(sp =>
{
var serviceBusPersisterConnection = sp.GetRequiredService<IServiceBusPersisterConnection>();
var iLifetimeScope = sp.GetRequiredService<ILifetimeScope>();
var logger = sp.GetRequiredService<ILogger<EventBusServiceBus>>();
var eventBusSubcriptionsManager = sp.GetRequiredService<IEventBusSubscriptionsManager>();
return new EventBusServiceBus(serviceBusPersisterConnection, logger, private void RegisterEventBus(IServiceCollection services)
eventBusSubcriptionsManager, subscriptionClientName, iLifetimeScope); {
}); var subscriptionClientName = Configuration["SubscriptionClientName"];
}
else
{
services.AddSingleton<IEventBus, EventBusRabbitMQ>(sp =>
{
var rabbitMQPersistentConnection = sp.GetRequiredService<IRabbitMQPersistentConnection>();
var iLifetimeScope = sp.GetRequiredService<ILifetimeScope>();
var logger = sp.GetRequiredService<ILogger<EventBusRabbitMQ>>();
var eventBusSubcriptionsManager = sp.GetRequiredService<IEventBusSubscriptionsManager>();
var retryCount = 5; if (Configuration.GetValue<bool>("AzureServiceBusEnabled"))
if (!string.IsNullOrEmpty(Configuration["EventBusRetryCount"])) {
{ services.AddSingleton<IEventBus, EventBusServiceBus>(sp =>
retryCount = int.Parse(Configuration["EventBusRetryCount"]); {
} var serviceBusPersisterConnection = sp.GetRequiredService<IServiceBusPersisterConnection>();
var iLifetimeScope = sp.GetRequiredService<ILifetimeScope>();
var logger = sp.GetRequiredService<ILogger<EventBusServiceBus>>();
var eventBusSubcriptionsManager = sp.GetRequiredService<IEventBusSubscriptionsManager>();
return new EventBusRabbitMQ(rabbitMQPersistentConnection, logger, iLifetimeScope, eventBusSubcriptionsManager, subscriptionClientName, retryCount); return new EventBusServiceBus(serviceBusPersisterConnection, logger,
}); eventBusSubcriptionsManager, subscriptionClientName, iLifetimeScope);
} });
}
else
{
services.AddSingleton<IEventBus, EventBusRabbitMQ>(sp =>
{
var rabbitMQPersistentConnection = sp.GetRequiredService<IRabbitMQPersistentConnection>();
var iLifetimeScope = sp.GetRequiredService<ILifetimeScope>();
var logger = sp.GetRequiredService<ILogger<EventBusRabbitMQ>>();
var eventBusSubcriptionsManager = sp.GetRequiredService<IEventBusSubscriptionsManager>();
services.AddSingleton<IEventBusSubscriptionsManager, InMemoryEventBusSubscriptionsManager>(); var retryCount = 5;
if (!string.IsNullOrEmpty(Configuration["EventBusRetryCount"]))
{
retryCount = int.Parse(Configuration["EventBusRetryCount"]);
}
services.AddTransient<ProductPriceChangedIntegrationEventHandler>(); return new EventBusRabbitMQ(rabbitMQPersistentConnection, logger, iLifetimeScope, eventBusSubcriptionsManager, subscriptionClientName, retryCount);
services.AddTransient<OrderStartedIntegrationEventHandler>(); });
} }
private void ConfigureEventBus(IApplicationBuilder app) services.AddSingleton<IEventBusSubscriptionsManager, InMemoryEventBusSubscriptionsManager>();
{
var eventBus = app.ApplicationServices.GetRequiredService<IEventBus>();
eventBus.Subscribe<ProductPriceChangedIntegrationEvent, ProductPriceChangedIntegrationEventHandler>(); services.AddTransient<ProductPriceChangedIntegrationEventHandler>();
eventBus.Subscribe<OrderStartedIntegrationEvent, OrderStartedIntegrationEventHandler>(); services.AddTransient<OrderStartedIntegrationEventHandler>();
} }
}
private void ConfigureEventBus(IApplicationBuilder app)
{
var eventBus = app.ApplicationServices.GetRequiredService<IEventBus>();
eventBus.Subscribe<ProductPriceChangedIntegrationEvent, ProductPriceChangedIntegrationEventHandler>();
eventBus.Subscribe<OrderStartedIntegrationEvent, OrderStartedIntegrationEventHandler>();
}
}
} }

View File

@ -1,24 +1,24 @@
{ {
"Logging": { "Logging": {
"IncludeScopes": false, "IncludeScopes": false,
"LogLevel": { "LogLevel": {
"Default": "Debug", "Default": "Debug",
"System": "Information", "System": "Information",
"Microsoft": "Information" "Microsoft": "Information"
} }
}, },
"IdentityUrl": "http://localhost:5105", "IdentityUrl": "https://localhost:4105",
"ConnectionString": "127.0.0.1", "ConnectionString": "127.0.0.1",
"AzureServiceBusEnabled": false, "AzureServiceBusEnabled": false,
"SubscriptionClientName": "Basket", "SubscriptionClientName": "Basket",
"ApplicationInsights": { "ApplicationInsights": {
"InstrumentationKey": "" "InstrumentationKey": ""
}, },
"EventBusRetryCount": 5, "EventBusRetryCount": 5,
"UseVault": false, "UseVault": false,
"Vault": { "Vault": {
"Name": "eshop", "Name": "eshop",
"ClientId": "your-clien-id", "ClientId": "your-clien-id",
"ClientSecret": "your-client-secret" "ClientSecret": "your-client-secret"
} }
} }

View File

@ -35,13 +35,13 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="4.2.1" /> <PackageReference Include="Autofac.Extensions.DependencyInjection" Version="4.2.1" />
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.2.1" /> <PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.4.1" />
<PackageReference Include="Microsoft.ApplicationInsights.DependencyCollector" Version="2.6.1" /> <PackageReference Include="Microsoft.ApplicationInsights.DependencyCollector" Version="2.7.2" />
<PackageReference Include="Microsoft.ApplicationInsights.Kubernetes" Version="1.0.0-beta8" /> <PackageReference Include="Microsoft.ApplicationInsights.Kubernetes" Version="1.0.0-beta8" />
<PackageReference Include="Microsoft.ApplicationInsights.ServiceFabric" Version="2.1.1-beta1" /> <PackageReference Include="Microsoft.ApplicationInsights.ServiceFabric" Version="2.1.1" />
<PackageReference Include="Microsoft.Extensions.Configuration.AzureKeyVault" Version="2.1.0" /> <PackageReference Include="Microsoft.Extensions.Configuration.AzureKeyVault" Version="2.1.1" />
<PackageReference Include="Microsoft.Extensions.Logging.AzureAppServices" Version="2.1.0" /> <PackageReference Include="Microsoft.Extensions.Logging.AzureAppServices" Version="2.1.1" />
<PackageReference Include="Microsoft.AspNetCore.App" Version="2.1.0" /> <PackageReference Include="Microsoft.AspNetCore.App" Version="2.1.3" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="2.4.0" /> <PackageReference Include="Swashbuckle.AspNetCore" Version="2.4.0" />
<PackageReference Include="System.IO.Compression.ZipFile" Version="4.3.0" /> <PackageReference Include="System.IO.Compression.ZipFile" Version="4.3.0" />
</ItemGroup> </ItemGroup>

View File

@ -1,8 +1,8 @@
FROM microsoft/dotnet:2.1-aspnetcore-runtime AS base FROM microsoft/dotnet:2.1.3-aspnetcore-runtime AS base
WORKDIR /app WORKDIR /app
EXPOSE 80 EXPOSE 80
FROM microsoft/dotnet:2.1-sdk AS build FROM microsoft/dotnet:2.1.401-sdk AS build
WORKDIR /src WORKDIR /src
COPY . . COPY . .
WORKDIR /src/src/Services/Catalog/Catalog.API WORKDIR /src/src/Services/Catalog/Catalog.API

View File

@ -14,7 +14,8 @@
"launchUrl": "/swagger", "launchUrl": "/swagger",
"environmentVariables": { "environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development" "ASPNETCORE_ENVIRONMENT": "Development"
} },
"use64Bit": true
}, },
"Microsoft.eShopOnContainers.Services.Catalog.API": { "Microsoft.eShopOnContainers.Services.Catalog.API": {
"commandName": "Project", "commandName": "Project",

View File

@ -32,299 +32,302 @@ using System.Reflection;
namespace Microsoft.eShopOnContainers.Services.Catalog.API namespace Microsoft.eShopOnContainers.Services.Catalog.API
{ {
public class Startup public class Startup
{ {
public Startup(IConfiguration configuration) public Startup(IConfiguration configuration)
{ {
Configuration = configuration; Configuration = configuration;
} }
public IConfiguration Configuration { get; } public IConfiguration Configuration { get; }
public IServiceProvider ConfigureServices(IServiceCollection services) public IServiceProvider ConfigureServices(IServiceCollection services)
{ {
services.AddAppInsight(Configuration) services.AddAppInsight(Configuration)
.AddCustomMVC(Configuration) .AddCustomMVC(Configuration)
.AddCustomDbContext(Configuration) .AddCustomDbContext(Configuration)
.AddCustomOptions(Configuration) .AddCustomOptions(Configuration)
.AddIntegrationServices(Configuration) .AddIntegrationServices(Configuration)
.AddEventBus(Configuration) .AddEventBus(Configuration)
.AddSwagger(); .AddSwagger();
var container = new ContainerBuilder(); var container = new ContainerBuilder();
container.Populate(services); container.Populate(services);
return new AutofacServiceProvider(container.Build()); return new AutofacServiceProvider(container.Build());
} }
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{ {
//Configure logs //Configure logs
loggerFactory.AddAzureWebAppDiagnostics(); loggerFactory.AddAzureWebAppDiagnostics();
loggerFactory.AddApplicationInsights(app.ApplicationServices, LogLevel.Trace); loggerFactory.AddApplicationInsights(app.ApplicationServices, LogLevel.Trace);
var pathBase = Configuration["PATH_BASE"]; var pathBase = Configuration["PATH_BASE"];
if (!string.IsNullOrEmpty(pathBase)) if (!string.IsNullOrEmpty(pathBase))
{ {
loggerFactory.CreateLogger("init").LogDebug($"Using PATH BASE '{pathBase}'"); loggerFactory.CreateLogger("init").LogDebug($"Using PATH BASE '{pathBase}'");
app.UsePathBase(pathBase); app.UsePathBase(pathBase);
} }
#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously #pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously
app.Map("/liveness", lapp => lapp.Run(async ctx => ctx.Response.StatusCode = 200)); app.Map("/liveness", lapp => lapp.Run(async ctx => ctx.Response.StatusCode = 200));
#pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously #pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously
app.UseCors("CorsPolicy"); app.UseCors("CorsPolicy");
app.UseMvcWithDefaultRoute(); app.UseMvcWithDefaultRoute();
app.UseSwagger() app.UseSwagger()
.UseSwaggerUI(c => .UseSwaggerUI(c =>
{ {
c.SwaggerEndpoint($"{ (!string.IsNullOrEmpty(pathBase) ? pathBase : string.Empty) }/swagger/v1/swagger.json", "Catalog.API V1"); c.SwaggerEndpoint($"{ (!string.IsNullOrEmpty(pathBase) ? pathBase : string.Empty) }/swagger/v1/swagger.json", "Catalog.API V1");
}); });
ConfigureEventBus(app); ConfigureEventBus(app);
} }
protected virtual void ConfigureEventBus(IApplicationBuilder app) protected virtual void ConfigureEventBus(IApplicationBuilder app)
{ {
var eventBus = app.ApplicationServices.GetRequiredService<IEventBus>(); var eventBus = app.ApplicationServices.GetRequiredService<IEventBus>();
eventBus.Subscribe<OrderStatusChangedToAwaitingValidationIntegrationEvent, OrderStatusChangedToAwaitingValidationIntegrationEventHandler>(); eventBus.Subscribe<OrderStatusChangedToAwaitingValidationIntegrationEvent, OrderStatusChangedToAwaitingValidationIntegrationEventHandler>();
eventBus.Subscribe<OrderStatusChangedToPaidIntegrationEvent, OrderStatusChangedToPaidIntegrationEventHandler>(); eventBus.Subscribe<OrderStatusChangedToPaidIntegrationEvent, OrderStatusChangedToPaidIntegrationEventHandler>();
} }
} }
public static class CustomExtensionMethods public static class CustomExtensionMethods
{ {
public static IServiceCollection AddAppInsight(this IServiceCollection services, IConfiguration configuration) public static IServiceCollection AddAppInsight(this IServiceCollection services, IConfiguration configuration)
{ {
services.AddApplicationInsightsTelemetry(configuration); services.AddApplicationInsightsTelemetry(configuration);
var orchestratorType = configuration.GetValue<string>("OrchestratorType"); var orchestratorType = configuration.GetValue<string>("OrchestratorType");
if (orchestratorType?.ToUpper() == "K8S") if (orchestratorType?.ToUpper() == "K8S")
{ {
// Enable K8s telemetry initializer // Enable K8s telemetry initializer
services.EnableKubernetes(); services.EnableKubernetes();
} }
if (orchestratorType?.ToUpper() == "SF") if (orchestratorType?.ToUpper() == "SF")
{ {
// Enable SF telemetry initializer // Enable SF telemetry initializer
services.AddSingleton<ITelemetryInitializer>((serviceProvider) => services.AddSingleton<ITelemetryInitializer>((serviceProvider) =>
new FabricTelemetryInitializer()); new FabricTelemetryInitializer());
} }
return services; return services;
} }
public static IServiceCollection AddCustomMVC(this IServiceCollection services, IConfiguration configuration) public static IServiceCollection AddCustomMVC(this IServiceCollection services, IConfiguration configuration)
{ {
services.AddHealthChecks(checks => services.AddHealthChecks(checks =>
{ {
var minutes = 1; var minutes = 1;
if (int.TryParse(configuration["HealthCheck:Timeout"], out var minutesParsed)) if (int.TryParse(configuration["HealthCheck:Timeout"], out int minutesParsed))
{ {
minutes = minutesParsed; minutes = minutesParsed;
} }
checks.AddSqlCheck("CatalogDb", configuration["ConnectionString"], TimeSpan.FromMinutes(minutes)); checks.AddSqlCheck("CatalogDb", configuration["ConnectionString"], TimeSpan.FromMinutes(minutes));
var accountName = configuration.GetValue<string>("AzureStorageAccountName"); var accountName = configuration.GetValue<string>("AzureStorageAccountName");
var accountKey = configuration.GetValue<string>("AzureStorageAccountKey"); var accountKey = configuration.GetValue<string>("AzureStorageAccountKey");
if (!string.IsNullOrEmpty(accountName) && !string.IsNullOrEmpty(accountKey)) if (!string.IsNullOrEmpty(accountName) && !string.IsNullOrEmpty(accountKey))
{ {
checks.AddAzureBlobStorageCheck(accountName, accountKey); checks.AddAzureBlobStorageCheck(accountName, accountKey);
} }
}); });
services.AddMvc(options => services.AddMvc(options =>
{ {
options.Filters.Add(typeof(HttpGlobalExceptionFilter)); options.Filters.Add(typeof(HttpGlobalExceptionFilter));
}).AddControllersAsServices(); })
.AddControllersAsServices()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_1)
;
services.AddCors(options => services.AddCors(options =>
{ {
options.AddPolicy("CorsPolicy", options.AddPolicy("CorsPolicy",
builder => builder.AllowAnyOrigin() builder => builder.AllowAnyOrigin()
.AllowAnyMethod() .AllowAnyMethod()
.AllowAnyHeader() .AllowAnyHeader()
.AllowCredentials()); .AllowCredentials());
}); });
return services; return services;
} }
public static IServiceCollection AddCustomDbContext(this IServiceCollection services, IConfiguration configuration) public static IServiceCollection AddCustomDbContext(this IServiceCollection services, IConfiguration configuration)
{ {
services.AddDbContext<CatalogContext>(options => services.AddDbContext<CatalogContext>(options =>
{ {
options.UseSqlServer(configuration["ConnectionString"], options.UseSqlServer(configuration["ConnectionString"],
sqlServerOptionsAction: sqlOptions => sqlServerOptionsAction: sqlOptions =>
{ {
sqlOptions.MigrationsAssembly(typeof(Startup).GetTypeInfo().Assembly.GetName().Name); sqlOptions.MigrationsAssembly(typeof(Startup).GetTypeInfo().Assembly.GetName().Name);
//Configuring Connection Resiliency: https://docs.microsoft.com/en-us/ef/core/miscellaneous/connection-resiliency //Configuring Connection Resiliency: https://docs.microsoft.com/en-us/ef/core/miscellaneous/connection-resiliency
sqlOptions.EnableRetryOnFailure(maxRetryCount: 10, maxRetryDelay: TimeSpan.FromSeconds(30), errorNumbersToAdd: null); sqlOptions.EnableRetryOnFailure(maxRetryCount: 10, maxRetryDelay: TimeSpan.FromSeconds(30), errorNumbersToAdd: null);
}); });
// Changing default behavior when client evaluation occurs to throw. // Changing default behavior when client evaluation occurs to throw.
// Default in EF Core would be to log a warning when client evaluation is performed. // Default in EF Core would be to log a warning when client evaluation is performed.
options.ConfigureWarnings(warnings => warnings.Throw(RelationalEventId.QueryClientEvaluationWarning)); options.ConfigureWarnings(warnings => warnings.Throw(RelationalEventId.QueryClientEvaluationWarning));
//Check Client vs. Server evaluation: https://docs.microsoft.com/en-us/ef/core/querying/client-eval //Check Client vs. Server evaluation: https://docs.microsoft.com/en-us/ef/core/querying/client-eval
}); });
services.AddDbContext<IntegrationEventLogContext>(options => services.AddDbContext<IntegrationEventLogContext>(options =>
{ {
options.UseSqlServer(configuration["ConnectionString"], options.UseSqlServer(configuration["ConnectionString"],
sqlServerOptionsAction: sqlOptions => sqlServerOptionsAction: sqlOptions =>
{ {
sqlOptions.MigrationsAssembly(typeof(Startup).GetTypeInfo().Assembly.GetName().Name); sqlOptions.MigrationsAssembly(typeof(Startup).GetTypeInfo().Assembly.GetName().Name);
//Configuring Connection Resiliency: https://docs.microsoft.com/en-us/ef/core/miscellaneous/connection-resiliency //Configuring Connection Resiliency: https://docs.microsoft.com/en-us/ef/core/miscellaneous/connection-resiliency
sqlOptions.EnableRetryOnFailure(maxRetryCount: 10, maxRetryDelay: TimeSpan.FromSeconds(30), errorNumbersToAdd: null); sqlOptions.EnableRetryOnFailure(maxRetryCount: 10, maxRetryDelay: TimeSpan.FromSeconds(30), errorNumbersToAdd: null);
}); });
}); });
return services; return services;
} }
public static IServiceCollection AddCustomOptions(this IServiceCollection services, IConfiguration configuration) public static IServiceCollection AddCustomOptions(this IServiceCollection services, IConfiguration configuration)
{ {
services.Configure<CatalogSettings>(configuration); services.Configure<CatalogSettings>(configuration);
services.Configure<ApiBehaviorOptions>(options => services.Configure<ApiBehaviorOptions>(options =>
{ {
options.InvalidModelStateResponseFactory = context => options.InvalidModelStateResponseFactory = context =>
{ {
var problemDetails = new ValidationProblemDetails(context.ModelState) var problemDetails = new ValidationProblemDetails(context.ModelState)
{ {
Instance = context.HttpContext.Request.Path, Instance = context.HttpContext.Request.Path,
Status = StatusCodes.Status400BadRequest, Status = StatusCodes.Status400BadRequest,
Detail = "Please refer to the errors property for additional details." Detail = "Please refer to the errors property for additional details."
}; };
return new BadRequestObjectResult(problemDetails) return new BadRequestObjectResult(problemDetails)
{ {
ContentTypes = { "application/problem+json", "application/problem+xml" } ContentTypes = { "application/problem+json", "application/problem+xml" }
}; };
}; };
}); });
return services; return services;
} }
public static IServiceCollection AddSwagger(this IServiceCollection services) public static IServiceCollection AddSwagger(this IServiceCollection services)
{ {
services.AddSwaggerGen(options => services.AddSwaggerGen(options =>
{ {
options.DescribeAllEnumsAsStrings(); options.DescribeAllEnumsAsStrings();
options.SwaggerDoc("v1", new Swashbuckle.AspNetCore.Swagger.Info options.SwaggerDoc("v1", new Swashbuckle.AspNetCore.Swagger.Info
{ {
Title = "eShopOnContainers - Catalog HTTP API", Title = "eShopOnContainers - Catalog HTTP API",
Version = "v1", Version = "v1",
Description = "The Catalog Microservice HTTP API. This is a Data-Driven/CRUD microservice sample", Description = "The Catalog Microservice HTTP API. This is a Data-Driven/CRUD microservice sample",
TermsOfService = "Terms Of Service" TermsOfService = "Terms Of Service"
}); });
}); });
return services; return services;
} }
public static IServiceCollection AddIntegrationServices(this IServiceCollection services, IConfiguration configuration) public static IServiceCollection AddIntegrationServices(this IServiceCollection services, IConfiguration configuration)
{ {
services.AddTransient<Func<DbConnection, IIntegrationEventLogService>>( services.AddTransient<Func<DbConnection, IIntegrationEventLogService>>(
sp => (DbConnection c) => new IntegrationEventLogService(c)); sp => (DbConnection c) => new IntegrationEventLogService(c));
services.AddTransient<ICatalogIntegrationEventService, CatalogIntegrationEventService>(); services.AddTransient<ICatalogIntegrationEventService, CatalogIntegrationEventService>();
if (configuration.GetValue<bool>("AzureServiceBusEnabled")) if (configuration.GetValue<bool>("AzureServiceBusEnabled"))
{ {
services.AddSingleton<IServiceBusPersisterConnection>(sp => services.AddSingleton<IServiceBusPersisterConnection>(sp =>
{ {
var settings = sp.GetRequiredService<IOptions<CatalogSettings>>().Value; var settings = sp.GetRequiredService<IOptions<CatalogSettings>>().Value;
var logger = sp.GetRequiredService<ILogger<DefaultServiceBusPersisterConnection>>(); var logger = sp.GetRequiredService<ILogger<DefaultServiceBusPersisterConnection>>();
var serviceBusConnection = new ServiceBusConnectionStringBuilder(settings.EventBusConnection); var serviceBusConnection = new ServiceBusConnectionStringBuilder(settings.EventBusConnection);
return new DefaultServiceBusPersisterConnection(serviceBusConnection, logger); return new DefaultServiceBusPersisterConnection(serviceBusConnection, logger);
}); });
} }
else else
{ {
services.AddSingleton<IRabbitMQPersistentConnection>(sp => services.AddSingleton<IRabbitMQPersistentConnection>(sp =>
{ {
var settings = sp.GetRequiredService<IOptions<CatalogSettings>>().Value; var settings = sp.GetRequiredService<IOptions<CatalogSettings>>().Value;
var logger = sp.GetRequiredService<ILogger<DefaultRabbitMQPersistentConnection>>(); var logger = sp.GetRequiredService<ILogger<DefaultRabbitMQPersistentConnection>>();
var factory = new ConnectionFactory() var factory = new ConnectionFactory()
{ {
HostName = configuration["EventBusConnection"] HostName = configuration["EventBusConnection"]
}; };
if (!string.IsNullOrEmpty(configuration["EventBusUserName"])) if (!string.IsNullOrEmpty(configuration["EventBusUserName"]))
{ {
factory.UserName = configuration["EventBusUserName"]; factory.UserName = configuration["EventBusUserName"];
} }
if (!string.IsNullOrEmpty(configuration["EventBusPassword"])) if (!string.IsNullOrEmpty(configuration["EventBusPassword"]))
{ {
factory.Password = configuration["EventBusPassword"]; factory.Password = configuration["EventBusPassword"];
} }
var retryCount = 5; var retryCount = 5;
if (!string.IsNullOrEmpty(configuration["EventBusRetryCount"])) if (!string.IsNullOrEmpty(configuration["EventBusRetryCount"]))
{ {
retryCount = int.Parse(configuration["EventBusRetryCount"]); retryCount = int.Parse(configuration["EventBusRetryCount"]);
} }
return new DefaultRabbitMQPersistentConnection(factory, logger, retryCount); return new DefaultRabbitMQPersistentConnection(factory, logger, retryCount);
}); });
} }
return services; return services;
} }
public static IServiceCollection AddEventBus(this IServiceCollection services, IConfiguration configuration) public static IServiceCollection AddEventBus(this IServiceCollection services, IConfiguration configuration)
{ {
var subscriptionClientName = configuration["SubscriptionClientName"]; var subscriptionClientName = configuration["SubscriptionClientName"];
if (configuration.GetValue<bool>("AzureServiceBusEnabled")) if (configuration.GetValue<bool>("AzureServiceBusEnabled"))
{ {
services.AddSingleton<IEventBus, EventBusServiceBus>(sp => services.AddSingleton<IEventBus, EventBusServiceBus>(sp =>
{ {
var serviceBusPersisterConnection = sp.GetRequiredService<IServiceBusPersisterConnection>(); var serviceBusPersisterConnection = sp.GetRequiredService<IServiceBusPersisterConnection>();
var iLifetimeScope = sp.GetRequiredService<ILifetimeScope>(); var iLifetimeScope = sp.GetRequiredService<ILifetimeScope>();
var logger = sp.GetRequiredService<ILogger<EventBusServiceBus>>(); var logger = sp.GetRequiredService<ILogger<EventBusServiceBus>>();
var eventBusSubcriptionsManager = sp.GetRequiredService<IEventBusSubscriptionsManager>(); var eventBusSubcriptionsManager = sp.GetRequiredService<IEventBusSubscriptionsManager>();
return new EventBusServiceBus(serviceBusPersisterConnection, logger, return new EventBusServiceBus(serviceBusPersisterConnection, logger,
eventBusSubcriptionsManager, subscriptionClientName, iLifetimeScope); eventBusSubcriptionsManager, subscriptionClientName, iLifetimeScope);
}); });
} }
else else
{ {
services.AddSingleton<IEventBus, EventBusRabbitMQ>(sp => services.AddSingleton<IEventBus, EventBusRabbitMQ>(sp =>
{ {
var rabbitMQPersistentConnection = sp.GetRequiredService<IRabbitMQPersistentConnection>(); var rabbitMQPersistentConnection = sp.GetRequiredService<IRabbitMQPersistentConnection>();
var iLifetimeScope = sp.GetRequiredService<ILifetimeScope>(); var iLifetimeScope = sp.GetRequiredService<ILifetimeScope>();
var logger = sp.GetRequiredService<ILogger<EventBusRabbitMQ>>(); var logger = sp.GetRequiredService<ILogger<EventBusRabbitMQ>>();
var eventBusSubcriptionsManager = sp.GetRequiredService<IEventBusSubscriptionsManager>(); var eventBusSubcriptionsManager = sp.GetRequiredService<IEventBusSubscriptionsManager>();
var retryCount = 5; var retryCount = 5;
if (!string.IsNullOrEmpty(configuration["EventBusRetryCount"])) if (!string.IsNullOrEmpty(configuration["EventBusRetryCount"]))
{ {
retryCount = int.Parse(configuration["EventBusRetryCount"]); retryCount = int.Parse(configuration["EventBusRetryCount"]);
} }
return new EventBusRabbitMQ(rabbitMQPersistentConnection, logger, iLifetimeScope, eventBusSubcriptionsManager, subscriptionClientName, retryCount); return new EventBusRabbitMQ(rabbitMQPersistentConnection, logger, iLifetimeScope, eventBusSubcriptionsManager, subscriptionClientName, retryCount);
}); });
} }
services.AddSingleton<IEventBusSubscriptionsManager, InMemoryEventBusSubscriptionsManager>(); services.AddSingleton<IEventBusSubscriptionsManager, InMemoryEventBusSubscriptionsManager>();
services.AddTransient<OrderStatusChangedToAwaitingValidationIntegrationEventHandler>(); services.AddTransient<OrderStatusChangedToAwaitingValidationIntegrationEventHandler>();
services.AddTransient<OrderStatusChangedToPaidIntegrationEventHandler>(); services.AddTransient<OrderStatusChangedToPaidIntegrationEventHandler>();
return services; return services;
} }
} }
} }

View File

@ -1,9 +1,10 @@
ARG NODE_IMAGE=node:8.11 ARG NODE_IMAGE=node:8.11
FROM microsoft/dotnet:2.1-aspnetcore-runtime AS base FROM microsoft/dotnet:2.1.3-aspnetcore-runtime AS base
WORKDIR /app WORKDIR /app
EXPOSE 80 EXPOSE 80
EXPOSE 443
FROM microsoft/dotnet:2.1-sdk as dotnet-build FROM microsoft/dotnet:2.1.401-sdk as dotnet-build
WORKDIR /src WORKDIR /src
FROM ${NODE_IMAGE} as node-build FROM ${NODE_IMAGE} as node-build
@ -16,6 +17,7 @@ FROM dotnet-build as build
WORKDIR /src/src/Services/Identity/Identity.API/wwwroot WORKDIR /src/src/Services/Identity/Identity.API/wwwroot
COPY --from=node-build /web/wwwroot . COPY --from=node-build /web/wwwroot .
WORKDIR /src WORKDIR /src
COPY src/Services/Identity/Identity.API/Setup/eShopOnContainers.pfx /root/.aspnet/https/
COPY . . COPY . .
WORKDIR /src/src/Services/Identity/Identity.API WORKDIR /src/src/Services/Identity/Identity.API
RUN dotnet restore -nowarn:msb3202,nu1503 RUN dotnet restore -nowarn:msb3202,nu1503

View File

@ -1,60 +1,66 @@
<Project Sdk="Microsoft.NET.Sdk.Web"> <Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup> <PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework> <TargetFramework>netcoreapp2.1</TargetFramework>
<UserSecretsId>aspnet-eShopOnContainers.Identity-90487118-103c-4ff0-b9da-e5e26f7ab0c5</UserSecretsId> <RuntimeFrameworkVersion>2.1.3</RuntimeFrameworkVersion>
<DockerComposeProjectPath>..\..\..\..\docker-compose.dcproj</DockerComposeProjectPath> <UserSecretsId>aspnet-eShopOnContainers.Identity-90487118-103c-4ff0-b9da-e5e26f7ab0c5</UserSecretsId>
</PropertyGroup> <DockerComposeProjectPath>..\..\..\..\docker-compose.dcproj</DockerComposeProjectPath>
</PropertyGroup>
<ItemGroup> <ItemGroup>
<Content Include="Setup\**\*;"> <Content Include="Setup\**\*;">
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory> <CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
</Content> </Content>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="4.2.1" /> <None Remove="Setup\DotNet Foundation CA.pfx" />
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.2.1" /> <None Remove="Setup\eShopOnContainers.pfx" />
<PackageReference Include="Microsoft.ApplicationInsights.DependencyCollector" Version="2.6.1" /> </ItemGroup>
<PackageReference Include="Microsoft.ApplicationInsights.Kubernetes" Version="1.0.0-beta8" />
<PackageReference Include="Microsoft.ApplicationInsights.ServiceFabric" Version="2.1.1-beta1" />
<PackageReference Include="Microsoft.Extensions.Logging.AzureAppServices" Version="2.1.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.AzureKeyVault" Version="2.1.0" />
<PackageReference Include="Microsoft.AspNetCore.App" Version="2.1.0" />
<PackageReference Include="IdentityServer4.AspNetIdentity" Version="2.1.0" />
<PackageReference Include="IdentityServer4.EntityFramework" Version="2.1.1" />
<PackageReference Include="Microsoft.AspNetCore.DataProtection.Redis" Version="0.3.3" />
<PackageReference Include="Microsoft.Web.LibraryManager.Build" Version="1.0.113" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="2.4.0" />
</ItemGroup>
<Target Name="PrepublishScript" BeforeTargets="PrepareForPublish"> <ItemGroup>
<Exec Command="dotnet bundle" Condition="'$(ASPNETCORE_ENVIRONMENT)'!='Development'" /> <PackageReference Include="Autofac.Extensions.DependencyInjection" Version="4.2.1" />
</Target> <PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.4.1" />
<PackageReference Include="Microsoft.ApplicationInsights.DependencyCollector" Version="2.7.2" />
<PackageReference Include="Microsoft.ApplicationInsights.Kubernetes" Version="1.0.0-beta8" />
<PackageReference Include="Microsoft.ApplicationInsights.ServiceFabric" Version="2.1.1" />
<PackageReference Include="Microsoft.Extensions.Logging.AzureAppServices" Version="2.1.1" />
<PackageReference Include="Microsoft.Extensions.Configuration.AzureKeyVault" Version="2.1.1" />
<PackageReference Include="Microsoft.AspNetCore.App" Version="2.1.3" />
<PackageReference Include="IdentityServer4.AspNetIdentity" Version="2.1.0" />
<PackageReference Include="IdentityServer4.EntityFramework" Version="2.1.1" />
<PackageReference Include="Microsoft.AspNetCore.DataProtection.Redis" Version="0.3.3" />
<PackageReference Include="Microsoft.Web.LibraryManager.Build" Version="1.0.113" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="2.4.0" />
</ItemGroup>
<ItemGroup> <Target Name="PrepublishScript" BeforeTargets="PrepareForPublish">
<DotNetCliToolReference Include="BundlerMinifier.Core" Version="2.7.385" /> <Exec Command="dotnet bundle" Condition="'$(ASPNETCORE_ENVIRONMENT)'!='Development'" />
</ItemGroup> </Target>
<ItemGroup> <ItemGroup>
<EmbeddedResource Include="Certificate\idsrv3test.pfx" /> <DotNetCliToolReference Include="BundlerMinifier.Core" Version="2.7.385" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\..\..\BuildingBlocks\HealthChecks\src\Microsoft.AspNetCore.HealthChecks\Microsoft.AspNetCore.HealthChecks.csproj" /> <EmbeddedResource Include="Certificate\idsrv3test.pfx" />
<ProjectReference Include="..\..\..\BuildingBlocks\HealthChecks\src\Microsoft.Extensions.HealthChecks.SqlServer\Microsoft.Extensions.HealthChecks.SqlServer.csproj" /> </ItemGroup>
<ProjectReference Include="..\..\..\BuildingBlocks\HealthChecks\src\Microsoft.Extensions.HealthChecks\Microsoft.Extensions.HealthChecks.csproj" />
<ProjectReference Include="..\..\..\BuildingBlocks\WebHostCustomization\WebHost.Customization\WebHost.Customization.csproj" />
</ItemGroup>
<ItemGroup> <ItemGroup>
<None Update="Setup\*"> <ProjectReference Include="..\..\..\BuildingBlocks\HealthChecks\src\Microsoft.AspNetCore.HealthChecks\Microsoft.AspNetCore.HealthChecks.csproj" />
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <ProjectReference Include="..\..\..\BuildingBlocks\HealthChecks\src\Microsoft.Extensions.HealthChecks.SqlServer\Microsoft.Extensions.HealthChecks.SqlServer.csproj" />
</None> <ProjectReference Include="..\..\..\BuildingBlocks\HealthChecks\src\Microsoft.Extensions.HealthChecks\Microsoft.Extensions.HealthChecks.csproj" />
</ItemGroup> <ProjectReference Include="..\..\..\BuildingBlocks\WebHostCustomization\WebHost.Customization\WebHost.Customization.csproj" />
</ItemGroup>
<ItemGroup> <ItemGroup>
<Folder Include="Extensions\" /> <None Update="Setup\*">
</ItemGroup> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
<ItemGroup>
<Folder Include="Extensions\" />
</ItemGroup>
</Project> </Project>

View File

@ -3,8 +3,8 @@
"windowsAuthentication": false, "windowsAuthentication": false,
"anonymousAuthentication": true, "anonymousAuthentication": true,
"iisExpress": { "iisExpress": {
"applicationUrl": "http://localhost:54010/", "applicationUrl": "http://localhost:5105/",
"sslPort": 0 "sslPort": 4105
} }
}, },
"profiles": { "profiles": {
@ -14,7 +14,8 @@
"launchUrl": "http://localhost:55105", "launchUrl": "http://localhost:55105",
"environmentVariables": { "environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development" "ASPNETCORE_ENVIRONMENT": "Development"
} },
"use64Bit": true
}, },
"eShopOnContainers.Identity": { "eShopOnContainers.Identity": {
"commandName": "Project", "commandName": "Project",

View File

@ -22,163 +22,177 @@ using System.Reflection;
namespace Microsoft.eShopOnContainers.Services.Identity.API namespace Microsoft.eShopOnContainers.Services.Identity.API
{ {
public class Startup public class Startup
{ {
public Startup(IConfiguration configuration) public Startup(IConfiguration configuration)
{ {
Configuration = configuration; Configuration = configuration;
} }
public IConfiguration Configuration { get; } public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container. // This method gets called by the runtime. Use this method to add services to the container.
public IServiceProvider ConfigureServices(IServiceCollection services) public IServiceProvider ConfigureServices(IServiceCollection services)
{ {
RegisterAppInsights(services); RegisterAppInsights(services);
// Add framework services. // Add framework services.
services.AddDbContext<ApplicationDbContext>(options => services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(Configuration["ConnectionString"], options.UseSqlServer(Configuration["ConnectionString"],
sqlServerOptionsAction: sqlOptions => sqlServerOptionsAction: sqlOptions =>
{ {
sqlOptions.MigrationsAssembly(typeof(Startup).GetTypeInfo().Assembly.GetName().Name); sqlOptions.MigrationsAssembly(typeof(Startup).GetTypeInfo().Assembly.GetName().Name);
//Configuring Connection Resiliency: https://docs.microsoft.com/en-us/ef/core/miscellaneous/connection-resiliency //Configuring Connection Resiliency: https://docs.microsoft.com/en-us/ef/core/miscellaneous/connection-resiliency
sqlOptions.EnableRetryOnFailure(maxRetryCount: 15, maxRetryDelay: TimeSpan.FromSeconds(30), errorNumbersToAdd: null); sqlOptions.EnableRetryOnFailure(maxRetryCount: 15, maxRetryDelay: TimeSpan.FromSeconds(30), errorNumbersToAdd: null);
})); }));
services.AddIdentity<ApplicationUser, IdentityRole>() services.AddIdentity<ApplicationUser, IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>() .AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders(); .AddDefaultTokenProviders();
services.Configure<AppSettings>(Configuration); services.Configure<AppSettings>(Configuration);
services.AddMvc(); services
.AddMvc(opts=>
{
opts.SslPort = 4105;
opts.RequireHttpsPermanent = true;
})
.SetCompatibilityVersion(AspNetCore.Mvc.CompatibilityVersion.Version_2_1)
;
if (Configuration.GetValue<string>("IsClusterEnv") == bool.TrueString) if (Configuration.GetValue<string>("IsClusterEnv") == bool.TrueString)
{ {
services.AddDataProtection(opts => services.AddDataProtection(opts =>
{ {
opts.ApplicationDiscriminator = "eshop.identity"; opts.ApplicationDiscriminator = "eshop.identity";
}) })
.PersistKeysToRedis(ConnectionMultiplexer.Connect(Configuration["DPConnectionString"]), "DataProtection-Keys"); .PersistKeysToRedis(ConnectionMultiplexer.Connect(Configuration["DPConnectionString"]), "DataProtection-Keys");
} }
services.AddHealthChecks(checks => services.AddHealthChecks(checks =>
{ {
var minutes = 1; int minutes = 1;
if (int.TryParse(Configuration["HealthCheck:Timeout"], out var minutesParsed)) if (int.TryParse(Configuration["HealthCheck:Timeout"], out int minutesParsed))
{ {
minutes = minutesParsed; minutes = minutesParsed;
} }
checks.AddSqlCheck("Identity_Db", Configuration["ConnectionString"], TimeSpan.FromMinutes(minutes)); checks.AddSqlCheck("Identity_Db", Configuration["ConnectionString"], TimeSpan.FromMinutes(minutes));
}); });
services.AddTransient<ILoginService<ApplicationUser>, EFLoginService>(); services.AddTransient<ILoginService<ApplicationUser>, EFLoginService>();
services.AddTransient<IRedirectService, RedirectService>(); services.AddTransient<IRedirectService, RedirectService>();
var connectionString = Configuration["ConnectionString"]; string connectionString = Configuration["ConnectionString"];
var migrationsAssembly = typeof(Startup).GetTypeInfo().Assembly.GetName().Name; string migrationsAssembly = typeof(Startup).GetTypeInfo().Assembly.GetName().Name;
// Adds IdentityServer // Adds IdentityServer
services.AddIdentityServer(x => x.IssuerUri = "null") services.AddIdentityServer(x => x.IssuerUri = "null")
.AddSigningCredential(Certificate.Get()) .AddSigningCredential(Certificate.Get())
.AddAspNetIdentity<ApplicationUser>() .AddAspNetIdentity<ApplicationUser>()
.AddConfigurationStore(options => .AddConfigurationStore(options =>
{ {
options.ConfigureDbContext = builder => builder.UseSqlServer(connectionString, options.ConfigureDbContext = builder => builder.UseSqlServer(connectionString,
sqlServerOptionsAction: sqlOptions => sqlServerOptionsAction: sqlOptions =>
{ {
sqlOptions.MigrationsAssembly(migrationsAssembly); sqlOptions.MigrationsAssembly(migrationsAssembly);
//Configuring Connection Resiliency: https://docs.microsoft.com/en-us/ef/core/miscellaneous/connection-resiliency //Configuring Connection Resiliency: https://docs.microsoft.com/en-us/ef/core/miscellaneous/connection-resiliency
sqlOptions.EnableRetryOnFailure(maxRetryCount: 15, maxRetryDelay: TimeSpan.FromSeconds(30), errorNumbersToAdd: null); sqlOptions.EnableRetryOnFailure(maxRetryCount: 15, maxRetryDelay: TimeSpan.FromSeconds(30), errorNumbersToAdd: null);
}); });
}) })
.AddOperationalStore(options => .AddOperationalStore(options =>
{ {
options.ConfigureDbContext = builder => builder.UseSqlServer(connectionString, options.ConfigureDbContext = builder => builder.UseSqlServer(connectionString,
sqlServerOptionsAction: sqlOptions => sqlServerOptionsAction: sqlOptions =>
{ {
sqlOptions.MigrationsAssembly(migrationsAssembly); sqlOptions.MigrationsAssembly(migrationsAssembly);
//Configuring Connection Resiliency: https://docs.microsoft.com/en-us/ef/core/miscellaneous/connection-resiliency //Configuring Connection Resiliency: https://docs.microsoft.com/en-us/ef/core/miscellaneous/connection-resiliency
sqlOptions.EnableRetryOnFailure(maxRetryCount: 15, maxRetryDelay: TimeSpan.FromSeconds(30), errorNumbersToAdd: null); sqlOptions.EnableRetryOnFailure(maxRetryCount: 15, maxRetryDelay: TimeSpan.FromSeconds(30), errorNumbersToAdd: null);
}); });
}) })
.Services.AddTransient<IProfileService, ProfileService>(); .Services.AddTransient<IProfileService, ProfileService>();
var container = new ContainerBuilder(); services.AddHttpsRedirection(opts =>
container.Populate(services); {
opts.HttpsPort = 4105;
});
return new AutofacServiceProvider(container.Build()); ContainerBuilder container = new ContainerBuilder();
} container.Populate(services);
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline. return new AutofacServiceProvider(container.Build());
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) }
{
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
loggerFactory.AddDebug();
loggerFactory.AddAzureWebAppDiagnostics();
loggerFactory.AddApplicationInsights(app.ApplicationServices, LogLevel.Trace);
if (env.IsDevelopment()) // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
{ public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
app.UseDeveloperExceptionPage(); {
app.UseDatabaseErrorPage(); loggerFactory.AddConsole(Configuration.GetSection("Logging"));
} loggerFactory.AddDebug();
else loggerFactory.AddAzureWebAppDiagnostics();
{ loggerFactory.AddApplicationInsights(app.ApplicationServices, LogLevel.Trace);
app.UseExceptionHandler("/Home/Error");
}
var pathBase = Configuration["PATH_BASE"]; if (env.IsDevelopment())
if (!string.IsNullOrEmpty(pathBase)) {
{ app.UseDeveloperExceptionPage();
loggerFactory.CreateLogger("init").LogDebug($"Using PATH BASE '{pathBase}'"); app.UseDatabaseErrorPage();
app.UsePathBase(pathBase); }
} else
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
string pathBase = Configuration["PATH_BASE"];
if (!string.IsNullOrEmpty(pathBase))
{
loggerFactory.CreateLogger("init").LogDebug($"Using PATH BASE '{pathBase}'");
app.UsePathBase(pathBase);
}
#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously #pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously
app.Map("/liveness", lapp => lapp.Run(async ctx => ctx.Response.StatusCode = 200)); app.Map("/liveness", lapp => lapp.Run(async ctx => ctx.Response.StatusCode = 200));
#pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously #pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously
app.UseStaticFiles(); app.UseStaticFiles();
// Make work identity server redirections in Edge and lastest versions of browers. WARN: Not valid in a production environment. // Make work identity server redirections in Edge and lastest versions of browers. WARN: Not valid in a production environment.
app.Use(async (context, next) => app.Use(async (context, next) =>
{ {
context.Response.Headers.Add("Content-Security-Policy", "script-src 'unsafe-inline'"); context.Response.Headers.Add("Content-Security-Policy", "script-src 'unsafe-inline'");
await next(); await next();
}); });
app.UseForwardedHeaders(); app.UseForwardedHeaders();
// Adds IdentityServer // Adds IdentityServer
app.UseIdentityServer(); app.UseIdentityServer();
app.UseMvc(routes => app.UseMvc(routes =>
{ {
routes.MapRoute( routes.MapRoute(
name: "default", name: "default",
template: "{controller=Home}/{action=Index}/{id?}"); template: "{controller=Home}/{action=Index}/{id?}");
}); });
} }
private void RegisterAppInsights(IServiceCollection services) private void RegisterAppInsights(IServiceCollection services)
{ {
services.AddApplicationInsightsTelemetry(Configuration); services.AddApplicationInsightsTelemetry(Configuration);
var orchestratorType = Configuration.GetValue<string>("OrchestratorType"); string orchestratorType = Configuration.GetValue<string>("OrchestratorType");
if (orchestratorType?.ToUpper() == "K8S") if (orchestratorType?.ToUpper() == "K8S")
{ {
// Enable K8s telemetry initializer // Enable K8s telemetry initializer
services.EnableKubernetes(); services.EnableKubernetes();
} }
if (orchestratorType?.ToUpper() == "SF") if (orchestratorType?.ToUpper() == "SF")
{ {
// Enable SF telemetry initializer // Enable SF telemetry initializer
services.AddSingleton<ITelemetryInitializer>((serviceProvider) => services.AddSingleton<ITelemetryInitializer>((serviceProvider) =>
new FabricTelemetryInitializer()); new FabricTelemetryInitializer());
} }
} }
} }
} }

View File

@ -1,25 +1,33 @@
{ {
"ConnectionString": "Server=tcp:127.0.0.1,5433;Database=Microsoft.eShopOnContainers.Services.IdentityDb;User Id=sa;Password=Pass@word;", "ConnectionString": "Server=tcp:127.0.0.1,5433;Database=Microsoft.eShopOnContainers.Services.IdentityDb;User Id=sa;Password=Pass@word;",
"IsClusterEnv": "False", "IsClusterEnv": "False",
"MvcClient": "http://localhost:5100", "MvcClient": "https://localhost:4100",
"SpaClient": "http://localhost:5104", "SpaClient": "https://localhost:4104",
"XamarinCallback": "http://localhost:5105/xamarincallback", "XamarinCallback": "https://localhost:4105/xamarincallback",
"UseCustomizationData": false, "UseCustomizationData": false,
"Logging": { "Logging": {
"IncludeScopes": false, "IncludeScopes": false,
"LogLevel": { "LogLevel": {
"Default": "Trace", "Default": "Trace",
"System": "Information", "System": "Information",
"Microsoft": "Information" "Microsoft": "Information"
} }
}, },
"ApplicationInsights": { "ApplicationInsights": {
"InstrumentationKey": "" "InstrumentationKey": ""
}, },
"UseVault": false, "UseVault": false,
"Vault": { "Vault": {
"Name": "eshop", "Name": "eshop",
"ClientId": "your-clien-id", "ClientId": "your-clien-id",
"ClientSecret": "your-client-secret" "ClientSecret": "your-client-secret"
} },
"Kestrel": {
"Certificates": {
"Default": {
"Path": "./Setup/eshopOnContainers.pfx",
"Password": "D0tNet@"
}
}
}
} }

View File

@ -1,8 +1,8 @@
FROM microsoft/dotnet:2.1-aspnetcore-runtime AS base FROM microsoft/dotnet:2.1.3-aspnetcore-runtime AS base
WORKDIR /app WORKDIR /app
EXPOSE 80 EXPOSE 80
FROM microsoft/dotnet:2.1-sdk AS build FROM microsoft/dotnet:2.1.401-sdk AS build
WORKDIR /src WORKDIR /src
COPY . . COPY . .
WORKDIR /src/src/Services/Location/Locations.API WORKDIR /src/src/Services/Location/Locations.API

View File

@ -1,32 +1,33 @@
<Project Sdk="Microsoft.NET.Sdk.Web"> <Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup> <PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework> <TargetFramework>netcoreapp2.1</TargetFramework>
<DockerComposeProjectPath>..\..\..\..\docker-compose.dcproj</DockerComposeProjectPath> <RuntimeFrameworkVersion>2.1.3</RuntimeFrameworkVersion>
<UserSecretsId>aspnet-Locations.API-20161122013619</UserSecretsId> <DockerComposeProjectPath>..\..\..\..\docker-compose.dcproj</DockerComposeProjectPath>
</PropertyGroup> <UserSecretsId>aspnet-Locations.API-20161122013619</UserSecretsId>
<ItemGroup> </PropertyGroup>
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="4.2.1" /> <ItemGroup>
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.2.1" /> <PackageReference Include="Autofac.Extensions.DependencyInjection" Version="4.2.1" />
<PackageReference Include="Microsoft.ApplicationInsights.DependencyCollector" Version="2.6.1" /> <PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.4.1" />
<PackageReference Include="Microsoft.ApplicationInsights.Kubernetes" Version="1.0.0-beta8" /> <PackageReference Include="Microsoft.ApplicationInsights.DependencyCollector" Version="2.7.2" />
<PackageReference Include="Microsoft.ApplicationInsights.ServiceFabric" Version="2.1.1-beta1" /> <PackageReference Include="Microsoft.ApplicationInsights.Kubernetes" Version="1.0.0-beta9" />
<PackageReference Include="Microsoft.Extensions.Logging.AzureAppServices" Version="2.1.0" /> <PackageReference Include="Microsoft.ApplicationInsights.ServiceFabric" Version="2.1.1" />
<PackageReference Include="Microsoft.Extensions.Configuration.AzureKeyVault" Version="2.1.0" /> <PackageReference Include="Microsoft.Extensions.Logging.AzureAppServices" Version="2.1.1" />
<PackageReference Include="Microsoft.AspNetCore.App" Version="2.1.0" /> <PackageReference Include="Microsoft.Extensions.Configuration.AzureKeyVault" Version="2.1.1" />
<PackageReference Include="mongocsharpdriver" Version="2.5.0" /> <PackageReference Include="Microsoft.AspNetCore.App" Version="2.1.3" />
<PackageReference Include="MongoDB.Bson" Version="2.5.0" /> <PackageReference Include="mongocsharpdriver" Version="2.5.0" />
<PackageReference Include="MongoDB.Driver" Version="2.5.0" /> <PackageReference Include="MongoDB.Bson" Version="2.5.0" />
<PackageReference Include="MongoDB.Driver.Core" Version="2.5.0" /> <PackageReference Include="MongoDB.Driver" Version="2.5.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="2.4.0" /> <PackageReference Include="MongoDB.Driver.Core" Version="2.5.0" />
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerUi" Version="2.4.0" /> <PackageReference Include="Swashbuckle.AspNetCore" Version="2.4.0" />
</ItemGroup> <PackageReference Include="Swashbuckle.AspNetCore.SwaggerUi" Version="2.4.0" />
<ItemGroup> </ItemGroup>
<ProjectReference Include="..\..\..\BuildingBlocks\EventBus\EventBusRabbitMQ\EventBusRabbitMQ.csproj" /> <ItemGroup>
<ProjectReference Include="..\..\..\BuildingBlocks\EventBus\EventBusServiceBus\EventBusServiceBus.csproj" /> <ProjectReference Include="..\..\..\BuildingBlocks\EventBus\EventBusRabbitMQ\EventBusRabbitMQ.csproj" />
<ProjectReference Include="..\..\..\BuildingBlocks\EventBus\EventBus\EventBus.csproj" /> <ProjectReference Include="..\..\..\BuildingBlocks\EventBus\EventBusServiceBus\EventBusServiceBus.csproj" />
<ProjectReference Include="..\..\..\BuildingBlocks\HealthChecks\src\Microsoft.AspNetCore.HealthChecks\Microsoft.AspNetCore.HealthChecks.csproj" /> <ProjectReference Include="..\..\..\BuildingBlocks\EventBus\EventBus\EventBus.csproj" />
<ProjectReference Include="..\..\..\BuildingBlocks\HealthChecks\src\Microsoft.Extensions.HealthChecks\Microsoft.Extensions.HealthChecks.csproj" /> <ProjectReference Include="..\..\..\BuildingBlocks\HealthChecks\src\Microsoft.AspNetCore.HealthChecks\Microsoft.AspNetCore.HealthChecks.csproj" />
</ItemGroup> <ProjectReference Include="..\..\..\BuildingBlocks\HealthChecks\src\Microsoft.Extensions.HealthChecks\Microsoft.Extensions.HealthChecks.csproj" />
</ItemGroup>
</Project> </Project>

View File

@ -14,7 +14,8 @@
"launchUrl": "api/values", "launchUrl": "api/values",
"environmentVariables": { "environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development" "ASPNETCORE_ENVIRONMENT": "Development"
} },
"use64Bit": true
}, },
"Locations.API": { "Locations.API": {
"commandName": "Project", "commandName": "Project",

View File

@ -1,8 +1,8 @@
FROM microsoft/dotnet:2.1-aspnetcore-runtime AS base FROM microsoft/dotnet:2.1.3-aspnetcore-runtime AS base
WORKDIR /app WORKDIR /app
EXPOSE 80 EXPOSE 80
FROM microsoft/dotnet:2.1-sdk AS build FROM microsoft/dotnet:2.1.401-sdk AS build
WORKDIR /src WORKDIR /src
COPY . . COPY . .
WORKDIR /src/src/Services/Marketing/Marketing.API WORKDIR /src/src/Services/Marketing/Marketing.API

View File

@ -1,55 +1,56 @@
<Project Sdk="Microsoft.NET.Sdk.Web"> <Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup> <PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework> <TargetFramework>netcoreapp2.1</TargetFramework>
<DockerComposeProjectPath>..\..\..\..\docker-compose.dcproj</DockerComposeProjectPath> <RuntimeFrameworkVersion>2.1.3</RuntimeFrameworkVersion>
<RootNamespace>Microsoft.eShopOnContainers.Services.Marketing.API</RootNamespace> <DockerComposeProjectPath>..\..\..\..\docker-compose.dcproj</DockerComposeProjectPath>
<AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback> <RootNamespace>Microsoft.eShopOnContainers.Services.Marketing.API</RootNamespace>
<UserSecretsId>aspnet-Marketing.API-20161122013619</UserSecretsId> <AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback>
<AssemblyName /> <UserSecretsId>aspnet-Marketing.API-20161122013619</UserSecretsId>
<ApplicationInsightsResourceId>/subscriptions/6c22bb55-0221-4ce4-9bf1-3c4a10a7294c/resourcegroups/eshop-log/providers/microsoft.insights/components/eshopappinsights</ApplicationInsightsResourceId> <AssemblyName />
<ApplicationInsightsAnnotationResourceId>/subscriptions/6c22bb55-0221-4ce4-9bf1-3c4a10a7294c/resourcegroups/eshop-log/providers/microsoft.insights/components/eshopappinsights</ApplicationInsightsAnnotationResourceId> <ApplicationInsightsResourceId>/subscriptions/6c22bb55-0221-4ce4-9bf1-3c4a10a7294c/resourcegroups/eshop-log/providers/microsoft.insights/components/eshopappinsights</ApplicationInsightsResourceId>
</PropertyGroup> <ApplicationInsightsAnnotationResourceId>/subscriptions/6c22bb55-0221-4ce4-9bf1-3c4a10a7294c/resourcegroups/eshop-log/providers/microsoft.insights/components/eshopappinsights</ApplicationInsightsAnnotationResourceId>
</PropertyGroup>
<ItemGroup> <ItemGroup>
<Folder Include="Connected Services\" /> <Folder Include="Connected Services\" />
<Folder Include="Infrastructure\MarketingMigrations\" /> <Folder Include="Infrastructure\MarketingMigrations\" />
<Content Include="Pics\**\*;"> <Content Include="Pics\**\*;">
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory> <CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
</Content> </Content>
<Folder Include="Infrastructure\MarketingMigrations\" /> <Folder Include="Infrastructure\MarketingMigrations\" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="4.2.1" /> <PackageReference Include="Autofac.Extensions.DependencyInjection" Version="4.2.1" />
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.2.1" /> <PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.4.1" />
<PackageReference Include="Microsoft.ApplicationInsights.DependencyCollector" Version="2.6.1" /> <PackageReference Include="Microsoft.ApplicationInsights.DependencyCollector" Version="2.7.2" />
<PackageReference Include="Microsoft.ApplicationInsights.Kubernetes" Version="1.0.0-beta8" /> <PackageReference Include="Microsoft.ApplicationInsights.Kubernetes" Version="1.0.0-beta9" />
<PackageReference Include="Microsoft.Extensions.Configuration.AzureKeyVault" Version="2.1.0" /> <PackageReference Include="Microsoft.Extensions.Configuration.AzureKeyVault" Version="2.1.1" />
<PackageReference Include="Microsoft.ApplicationInsights.ServiceFabric" Version="2.1.1-beta1" /> <PackageReference Include="Microsoft.ApplicationInsights.ServiceFabric" Version="2.1.1" />
<PackageReference Include="Microsoft.Extensions.Logging.AzureAppServices" Version="2.1.0" /> <PackageReference Include="Microsoft.Extensions.Logging.AzureAppServices" Version="2.1.1" />
<PackageReference Include="Microsoft.AspNetCore.App" Version="2.1.0" /> <PackageReference Include="Microsoft.AspNetCore.App" Version="2.1.3" />
<PackageReference Include="mongocsharpdriver" Version="2.5.0" /> <PackageReference Include="mongocsharpdriver" Version="2.5.0" />
<PackageReference Include="MongoDB.Bson" Version="2.5.0" /> <PackageReference Include="MongoDB.Bson" Version="2.5.0" />
<PackageReference Include="MongoDB.Driver" Version="2.5.0" /> <PackageReference Include="MongoDB.Driver" Version="2.5.0" />
<PackageReference Include="MongoDB.Driver.Core" Version="2.5.0" /> <PackageReference Include="MongoDB.Driver.Core" Version="2.5.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="2.4.0" /> <PackageReference Include="Swashbuckle.AspNetCore" Version="2.4.0" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\..\..\BuildingBlocks\EventBus\EventBusRabbitMQ\EventBusRabbitMQ.csproj" /> <ProjectReference Include="..\..\..\BuildingBlocks\EventBus\EventBusRabbitMQ\EventBusRabbitMQ.csproj" />
<ProjectReference Include="..\..\..\BuildingBlocks\HealthChecks\src\Microsoft.AspNetCore.HealthChecks\Microsoft.AspNetCore.HealthChecks.csproj" /> <ProjectReference Include="..\..\..\BuildingBlocks\HealthChecks\src\Microsoft.AspNetCore.HealthChecks\Microsoft.AspNetCore.HealthChecks.csproj" />
<ProjectReference Include="..\..\..\BuildingBlocks\HealthChecks\src\Microsoft.Extensions.HealthChecks.AzureStorage\Microsoft.Extensions.HealthChecks.AzureStorage.csproj" /> <ProjectReference Include="..\..\..\BuildingBlocks\HealthChecks\src\Microsoft.Extensions.HealthChecks.AzureStorage\Microsoft.Extensions.HealthChecks.AzureStorage.csproj" />
<ProjectReference Include="..\..\..\BuildingBlocks\HealthChecks\src\Microsoft.Extensions.HealthChecks\Microsoft.Extensions.HealthChecks.csproj" /> <ProjectReference Include="..\..\..\BuildingBlocks\HealthChecks\src\Microsoft.Extensions.HealthChecks\Microsoft.Extensions.HealthChecks.csproj" />
<ProjectReference Include="..\..\..\BuildingBlocks\EventBus\EventBusServiceBus\EventBusServiceBus.csproj" /> <ProjectReference Include="..\..\..\BuildingBlocks\EventBus\EventBusServiceBus\EventBusServiceBus.csproj" />
<ProjectReference Include="..\..\..\BuildingBlocks\WebHostCustomization\WebHost.Customization\WebHost.Customization.csproj" /> <ProjectReference Include="..\..\..\BuildingBlocks\WebHostCustomization\WebHost.Customization\WebHost.Customization.csproj" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Update="Pics\*"> <None Update="Pics\*">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None> </None>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<WCFMetadata Include="Connected Services" /> <WCFMetadata Include="Connected Services" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -14,7 +14,8 @@
"launchUrl": "swagger", "launchUrl": "swagger",
"environmentVariables": { "environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development" "ASPNETCORE_ENVIRONMENT": "Development"
} },
"use64Bit": true
}, },
"Marketing.API": { "Marketing.API": {
"commandName": "Project", "commandName": "Project",

View File

@ -1,8 +1,8 @@
FROM microsoft/dotnet:2.1-aspnetcore-runtime AS base FROM microsoft/dotnet:2.1.3-aspnetcore-runtime AS base
WORKDIR /app WORKDIR /app
EXPOSE 80 EXPOSE 80
FROM microsoft/dotnet:2.1-sdk AS build FROM microsoft/dotnet:2.1.401-sdk AS build
WORKDIR /src WORKDIR /src
COPY . . COPY . .
WORKDIR /src/src/Services/Ordering/Ordering.API WORKDIR /src/src/Services/Ordering/Ordering.API

View File

@ -1,56 +1,57 @@
<Project Sdk="Microsoft.NET.Sdk.Web"> <Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup> <PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework> <TargetFramework>netcoreapp2.1</TargetFramework>
<UserSecretsId>aspnet-Ordering.API-20161122013547</UserSecretsId> <RuntimeFrameworkVersion>2.1.3</RuntimeFrameworkVersion>
<AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback> <UserSecretsId>aspnet-Ordering.API-20161122013547</UserSecretsId>
<DockerComposeProjectPath>..\..\..\..\docker-compose.dcproj</DockerComposeProjectPath> <AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback>
</PropertyGroup> <DockerComposeProjectPath>..\..\..\..\docker-compose.dcproj</DockerComposeProjectPath>
</PropertyGroup>
<ItemGroup> <ItemGroup>
<Content Update="web.config;"> <Content Update="web.config;">
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory> <CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
</Content> </Content>
<Content Include="Setup\**\*;"> <Content Include="Setup\**\*;">
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory> <CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
</Content> </Content>
</ItemGroup> </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" />
<ProjectReference Include="..\..\..\BuildingBlocks\EventBus\EventBus\EventBus.csproj" /> <ProjectReference Include="..\..\..\BuildingBlocks\EventBus\EventBus\EventBus.csproj" />
<ProjectReference Include="..\..\..\BuildingBlocks\EventBus\IntegrationEventLogEF\IntegrationEventLogEF.csproj" /> <ProjectReference Include="..\..\..\BuildingBlocks\EventBus\IntegrationEventLogEF\IntegrationEventLogEF.csproj" />
<ProjectReference Include="..\..\..\BuildingBlocks\HealthChecks\src\Microsoft.AspNetCore.HealthChecks\Microsoft.AspNetCore.HealthChecks.csproj" /> <ProjectReference Include="..\..\..\BuildingBlocks\HealthChecks\src\Microsoft.AspNetCore.HealthChecks\Microsoft.AspNetCore.HealthChecks.csproj" />
<ProjectReference Include="..\..\..\BuildingBlocks\HealthChecks\src\Microsoft.Extensions.HealthChecks.SqlServer\Microsoft.Extensions.HealthChecks.SqlServer.csproj" /> <ProjectReference Include="..\..\..\BuildingBlocks\HealthChecks\src\Microsoft.Extensions.HealthChecks.SqlServer\Microsoft.Extensions.HealthChecks.SqlServer.csproj" />
<ProjectReference Include="..\..\..\BuildingBlocks\HealthChecks\src\Microsoft.Extensions.HealthChecks\Microsoft.Extensions.HealthChecks.csproj" /> <ProjectReference Include="..\..\..\BuildingBlocks\HealthChecks\src\Microsoft.Extensions.HealthChecks\Microsoft.Extensions.HealthChecks.csproj" />
<ProjectReference Include="..\..\..\BuildingBlocks\WebHostCustomization\WebHost.Customization\WebHost.Customization.csproj" /> <ProjectReference Include="..\..\..\BuildingBlocks\WebHostCustomization\WebHost.Customization\WebHost.Customization.csproj" />
<ProjectReference Include="..\Ordering.Domain\Ordering.Domain.csproj" /> <ProjectReference Include="..\Ordering.Domain\Ordering.Domain.csproj" />
<ProjectReference Include="..\Ordering.Infrastructure\Ordering.Infrastructure.csproj" /> <ProjectReference Include="..\Ordering.Infrastructure\Ordering.Infrastructure.csproj" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="FluentValidation.AspNetCore" Version="7.5.0" /> <PackageReference Include="Autofac.Extensions.DependencyInjection" Version="4.2.1" />
<PackageReference Include="MediatR.Extensions.Microsoft.DependencyInjection" Version="4.1.0" /> <PackageReference Include="Dapper" Version="1.50.4" />
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="4.2.1" /> <PackageReference Include="FluentValidation.AspNetCore" Version="7.5.0" />
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.2.1" /> <PackageReference Include="MediatR" Version="4.1.0" />
<PackageReference Include="Microsoft.ApplicationInsights.DependencyCollector" Version="2.6.1" /> <PackageReference Include="MediatR.Extensions.Microsoft.DependencyInjection" Version="4.1.0" />
<PackageReference Include="Microsoft.ApplicationInsights.Kubernetes" Version="1.0.0-beta8" /> <PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.4.1" />
<PackageReference Include="Microsoft.ApplicationInsights.ServiceFabric" Version="2.1.1-beta1" /> <PackageReference Include="Microsoft.ApplicationInsights.DependencyCollector" Version="2.7.2" />
<PackageReference Include="Microsoft.Extensions.Configuration.AzureKeyVault" Version="2.1.0" /> <PackageReference Include="Microsoft.ApplicationInsights.Kubernetes" Version="1.0.0-beta9" />
<PackageReference Include="Microsoft.Extensions.Logging.AzureAppServices" Version="2.1.0" /> <PackageReference Include="Microsoft.ApplicationInsights.ServiceFabric" Version="2.1.1" />
<PackageReference Include="Microsoft.AspNetCore.App" Version="2.1.0" /> <PackageReference Include="Microsoft.AspNetCore.App" Version="2.1.3" />
<PackageReference Include="MediatR" Version="4.1.0" /> <PackageReference Include="Microsoft.Extensions.Configuration.AzureKeyVault" Version="2.1.1" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="2.4.0" /> <PackageReference Include="Microsoft.Extensions.Logging.AzureAppServices" Version="2.1.1" />
<PackageReference Include="System.Reflection" Version="4.3.0" /> <PackageReference Include="Polly" Version="6.0.1" />
<PackageReference Include="Dapper" Version="1.50.4" /> <PackageReference Include="Swashbuckle.AspNetCore" Version="2.4.0" />
<PackageReference Include="System.ValueTuple" Version="4.5.0" /> <PackageReference Include="System.Reflection" Version="4.3.0" />
<PackageReference Include="Polly" Version="6.0.1" /> <PackageReference Include="System.ValueTuple" Version="4.5.0" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Update="Setup\*"> <None Update="Setup\*">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None> </None>
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -14,7 +14,8 @@
"launchUrl": "/swagger", "launchUrl": "/swagger",
"environmentVariables": { "environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development" "ASPNETCORE_ENVIRONMENT": "Development"
} },
"use64Bit": true
}, },
"Microsoft.eShopOnContainers.Services.Ordering.API": { "Microsoft.eShopOnContainers.Services.Ordering.API": {
"commandName": "Project", "commandName": "Project",

View File

@ -1,8 +1,8 @@
FROM microsoft/dotnet:2.1-aspnetcore-runtime AS base FROM microsoft/dotnet:2.1.3-aspnetcore-runtime AS base
WORKDIR /app WORKDIR /app
EXPOSE 80 EXPOSE 80
FROM microsoft/dotnet:2.1-sdk AS build FROM microsoft/dotnet:2.1.401-sdk AS build
WORKDIR /src WORKDIR /src
COPY . . COPY . .
WORKDIR /src/src/Services/Ordering/Ordering.BackgroundTasks WORKDIR /src/src/Services/Ordering/Ordering.BackgroundTasks

View File

@ -1,31 +1,32 @@
<Project Sdk="Microsoft.NET.Sdk.Web"> <Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup> <PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework> <TargetFramework>netcoreapp2.1</TargetFramework>
<AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback> <RuntimeFrameworkVersion>2.1.3</RuntimeFrameworkVersion>
<DockerComposeProjectPath>..\..\..\..\docker-compose.dcproj</DockerComposeProjectPath> <AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback>
</PropertyGroup> <DockerComposeProjectPath>..\..\..\..\docker-compose.dcproj</DockerComposeProjectPath>
</PropertyGroup>
<ItemGroup> <ItemGroup>
<Compile Remove="wwwroot\**" /> <Compile Remove="wwwroot\**" />
<Content Remove="wwwroot\**" /> <Content Remove="wwwroot\**" />
<EmbeddedResource Remove="wwwroot\**" /> <EmbeddedResource Remove="wwwroot\**" />
<None Remove="wwwroot\**" /> <None Remove="wwwroot\**" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="4.2.1" /> <PackageReference Include="Autofac.Extensions.DependencyInjection" Version="4.2.1" />
<PackageReference Include="Dapper" Version="1.50.4" /> <PackageReference Include="Dapper" Version="1.50.4" />
<PackageReference Include="Microsoft.AspNetCore.App" Version="2.1.0" /> <PackageReference Include="Microsoft.AspNetCore.App" Version="2.1.3" />
</ItemGroup> </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" />
<ProjectReference Include="..\..\..\BuildingBlocks\EventBus\EventBus\EventBus.csproj" /> <ProjectReference Include="..\..\..\BuildingBlocks\EventBus\EventBus\EventBus.csproj" />
<ProjectReference Include="..\..\..\BuildingBlocks\HealthChecks\src\Microsoft.AspNetCore.HealthChecks\Microsoft.AspNetCore.HealthChecks.csproj" /> <ProjectReference Include="..\..\..\BuildingBlocks\HealthChecks\src\Microsoft.AspNetCore.HealthChecks\Microsoft.AspNetCore.HealthChecks.csproj" />
<ProjectReference Include="..\..\..\BuildingBlocks\HealthChecks\src\Microsoft.Extensions.HealthChecks.SqlServer\Microsoft.Extensions.HealthChecks.SqlServer.csproj" /> <ProjectReference Include="..\..\..\BuildingBlocks\HealthChecks\src\Microsoft.Extensions.HealthChecks.SqlServer\Microsoft.Extensions.HealthChecks.SqlServer.csproj" />
<ProjectReference Include="..\..\..\BuildingBlocks\HealthChecks\src\Microsoft.Extensions.HealthChecks\Microsoft.Extensions.HealthChecks.csproj" /> <ProjectReference Include="..\..\..\BuildingBlocks\HealthChecks\src\Microsoft.Extensions.HealthChecks\Microsoft.Extensions.HealthChecks.csproj" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -14,7 +14,8 @@
"launchUrl": "api/values", "launchUrl": "api/values",
"environmentVariables": { "environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development" "ASPNETCORE_ENVIRONMENT": "Development"
} },
"use64Bit": true
}, },
"Ordering.BackgroundTasks": { "Ordering.BackgroundTasks": {
"commandName": "Project", "commandName": "Project",
@ -26,4 +27,4 @@
"applicationUrl": "http://localhost:5162/" "applicationUrl": "http://localhost:5162/"
} }
} }
} }

View File

@ -9,9 +9,9 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="2.1.0" /> <PackageReference Include="Microsoft.EntityFrameworkCore" Version="2.1.2" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="2.1.0" /> <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="2.1.2" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="2.1.0" /> <PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="2.1.1" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@ -1,8 +1,8 @@
FROM microsoft/dotnet:2.1-aspnetcore-runtime AS base FROM microsoft/dotnet:2.1.3-aspnetcore-runtime AS base
WORKDIR /app WORKDIR /app
EXPOSE 80 EXPOSE 80
FROM microsoft/dotnet:2.1-sdk AS build FROM microsoft/dotnet:2.1.401-sdk AS build
WORKDIR /src WORKDIR /src
COPY . . COPY . .
WORKDIR /src/src/Services/Ordering/Ordering.SignalrHub WORKDIR /src/src/Services/Ordering/Ordering.SignalrHub

View File

@ -1,31 +1,32 @@
<Project Sdk="Microsoft.NET.Sdk.Web"> <Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup> <PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework> <TargetFramework>netcoreapp2.1</TargetFramework>
<DockerComposeProjectPath>..\..\..\..\docker-compose.dcproj</DockerComposeProjectPath> <RuntimeFrameworkVersion>2.1.3</RuntimeFrameworkVersion>
</PropertyGroup> <DockerComposeProjectPath>..\..\..\..\docker-compose.dcproj</DockerComposeProjectPath>
</PropertyGroup>
<ItemGroup> <ItemGroup>
<Folder Include="wwwroot\" /> <Folder Include="wwwroot\" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="4.2.1" /> <PackageReference Include="Autofac.Extensions.DependencyInjection" Version="4.2.1" />
<PackageReference Include="Microsoft.AspNetCore.App" Version="2.1.0" /> <PackageReference Include="Microsoft.AspNetCore.App" Version="2.1.3" />
<PackageReference Include="Microsoft.AspNetCore.SignalR" Version="1.0.0" /> <PackageReference Include="Microsoft.AspNetCore.SignalR" Version="1.0.3" />
<PackageReference Include="Microsoft.AspNetCore.SignalR.Core" Version="1.0.0" /> <PackageReference Include="Microsoft.AspNetCore.SignalR.Core" Version="1.0.3" />
<PackageReference Include="Microsoft.AspNetCore.SignalR.Redis" Version="1.0.0" /> <PackageReference Include="Microsoft.AspNetCore.SignalR.Redis" Version="1.0.3" />
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.2.1" /> <PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.4.1" />
<PackageReference Include="Microsoft.ApplicationInsights.DependencyCollector" Version="2.6.1" /> <PackageReference Include="Microsoft.ApplicationInsights.DependencyCollector" Version="2.7.2" />
<PackageReference Include="Microsoft.ApplicationInsights.Kubernetes" Version="1.0.0-beta8" /> <PackageReference Include="Microsoft.ApplicationInsights.Kubernetes" Version="1.0.0-beta9" />
<PackageReference Include="Microsoft.ApplicationInsights.ServiceFabric" Version="2.1.1-beta1" /> <PackageReference Include="Microsoft.ApplicationInsights.ServiceFabric" Version="2.1.1" />
<PackageReference Include="Microsoft.Extensions.Logging.AzureAppServices" Version="2.1.0" /> <PackageReference Include="Microsoft.Extensions.Logging.AzureAppServices" Version="2.1.1" />
</ItemGroup> </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" />
<ProjectReference Include="..\..\..\BuildingBlocks\EventBus\EventBus\EventBus.csproj" /> <ProjectReference Include="..\..\..\BuildingBlocks\EventBus\EventBus\EventBus.csproj" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -13,7 +13,8 @@
"launchBrowser": true, "launchBrowser": true,
"environmentVariables": { "environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development" "ASPNETCORE_ENVIRONMENT": "Development"
} },
"use64Bit": true
}, },
"Ordering.SignalrHub": { "Ordering.SignalrHub": {
"commandName": "Project", "commandName": "Project",
@ -24,4 +25,4 @@
"applicationUrl": "http://localhost:51312/" "applicationUrl": "http://localhost:51312/"
} }
} }
} }

View File

@ -1,8 +1,8 @@
FROM microsoft/dotnet:2.1-aspnetcore-runtime AS base FROM microsoft/dotnet:2.1.3-aspnetcore-runtime AS base
WORKDIR /app WORKDIR /app
EXPOSE 80 EXPOSE 80
FROM microsoft/dotnet:2.1-sdk AS build FROM microsoft/dotnet:2.1.401-sdk AS build
WORKDIR /src WORKDIR /src
COPY . . COPY . .
WORKDIR /src/src/Services/Payment/Payment.API WORKDIR /src/src/Services/Payment/Payment.API

View File

@ -1,28 +1,29 @@
<Project Sdk="Microsoft.NET.Sdk.Web"> <Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup> <PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework> <TargetFramework>netcoreapp2.1</TargetFramework>
<DockerComposeProjectPath>..\..\..\..\docker-compose.dcproj</DockerComposeProjectPath> <RuntimeFrameworkVersion>2.1.3</RuntimeFrameworkVersion>
<AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback> <DockerComposeProjectPath>..\..\..\..\docker-compose.dcproj</DockerComposeProjectPath>
</PropertyGroup> <AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback>
</PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="4.2.1" /> <PackageReference Include="Autofac.Extensions.DependencyInjection" Version="4.2.1" />
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.2.1" /> <PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.4.1" />
<PackageReference Include="Microsoft.ApplicationInsights.DependencyCollector" Version="2.6.1" /> <PackageReference Include="Microsoft.ApplicationInsights.DependencyCollector" Version="2.7.2" />
<PackageReference Include="Microsoft.ApplicationInsights.Kubernetes" Version="1.0.0-beta8" /> <PackageReference Include="Microsoft.ApplicationInsights.Kubernetes" Version="1.0.0-beta9" />
<PackageReference Include="Microsoft.ApplicationInsights.ServiceFabric" Version="2.1.1-beta1" /> <PackageReference Include="Microsoft.ApplicationInsights.ServiceFabric" Version="2.1.1" />
<PackageReference Include="Microsoft.Extensions.Logging.AzureAppServices" Version="2.1.0" /> <PackageReference Include="Microsoft.Extensions.Logging.AzureAppServices" Version="2.1.1" />
<PackageReference Include="Microsoft.AspNetCore.App" Version="2.1.0" /> <PackageReference Include="Microsoft.AspNetCore.App" Version="2.1.3" />
</ItemGroup> </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" />
<ProjectReference Include="..\..\..\BuildingBlocks\EventBus\EventBus\EventBus.csproj" /> <ProjectReference Include="..\..\..\BuildingBlocks\EventBus\EventBus\EventBus.csproj" />
<ProjectReference Include="..\..\..\BuildingBlocks\EventBus\IntegrationEventLogEF\IntegrationEventLogEF.csproj" /> <ProjectReference Include="..\..\..\BuildingBlocks\EventBus\IntegrationEventLogEF\IntegrationEventLogEF.csproj" />
<ProjectReference Include="..\..\..\BuildingBlocks\HealthChecks\src\Microsoft.AspNetCore.HealthChecks\Microsoft.AspNetCore.HealthChecks.csproj" /> <ProjectReference Include="..\..\..\BuildingBlocks\HealthChecks\src\Microsoft.AspNetCore.HealthChecks\Microsoft.AspNetCore.HealthChecks.csproj" />
<ProjectReference Include="..\..\..\BuildingBlocks\HealthChecks\src\Microsoft.Extensions.HealthChecks.SqlServer\Microsoft.Extensions.HealthChecks.SqlServer.csproj" /> <ProjectReference Include="..\..\..\BuildingBlocks\HealthChecks\src\Microsoft.Extensions.HealthChecks.SqlServer\Microsoft.Extensions.HealthChecks.SqlServer.csproj" />
<ProjectReference Include="..\..\..\BuildingBlocks\HealthChecks\src\Microsoft.Extensions.HealthChecks\Microsoft.Extensions.HealthChecks.csproj" /> <ProjectReference Include="..\..\..\BuildingBlocks\HealthChecks\src\Microsoft.Extensions.HealthChecks\Microsoft.Extensions.HealthChecks.csproj" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -14,7 +14,8 @@
"launchUrl": "api/values", "launchUrl": "api/values",
"environmentVariables": { "environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development" "ASPNETCORE_ENVIRONMENT": "Development"
} },
"use64Bit": true
}, },
"Payment.API": { "Payment.API": {
"commandName": "Project", "commandName": "Project",

View File

@ -0,0 +1,13 @@
using Microsoft.AspNetCore.Mvc;
namespace WebMVC.Controllers
{
public class HomeController : Controller
{
public IActionResult Privacy()
{
return View();
}
}
}

View File

@ -1,9 +1,10 @@
ARG NODE_IMAGE=node:8.11 ARG NODE_IMAGE=node:8.11
FROM microsoft/dotnet:2.1-aspnetcore-runtime AS base FROM microsoft/dotnet:2.1.3-aspnetcore-runtime AS base
WORKDIR /app WORKDIR /app
EXPOSE 80 EXPOSE 80
EXPOSE 443
FROM microsoft/dotnet:2.1-sdk as dotnet-build FROM microsoft/dotnet:2.1.401-sdk as dotnet-build
WORKDIR /src WORKDIR /src
FROM ${NODE_IMAGE} as node-build FROM ${NODE_IMAGE} as node-build
@ -16,6 +17,7 @@ FROM dotnet-build as build
WORKDIR /src/src/Web/WebMVC/wwwroot WORKDIR /src/src/Web/WebMVC/wwwroot
COPY --from=node-build /web/wwwroot . COPY --from=node-build /web/wwwroot .
WORKDIR /src WORKDIR /src
COPY Certificates/eShopOnContainers.pfx /root/.aspnet/https/
COPY . . COPY . .
WORKDIR /src/src/Web/WebMVC WORKDIR /src/src/Web/WebMVC
RUN dotnet restore -nowarn:msb3202,nu1503 RUN dotnet restore -nowarn:msb3202,nu1503

View File

@ -4,7 +4,7 @@
"anonymousAuthentication": true, "anonymousAuthentication": true,
"iisExpress": { "iisExpress": {
"applicationUrl": "http://localhost:5100", "applicationUrl": "http://localhost:5100",
"sslPort": 0 "sslPort": 4100
} }
}, },
"profiles": { "profiles": {
@ -12,15 +12,16 @@
"commandName": "IISExpress", "commandName": "IISExpress",
"environmentVariables": { "environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development" "ASPNETCORE_ENVIRONMENT": "Development"
} },
"use64Bit": true
}, },
"Microsoft.eShopOnContainers.WebMVC": { "Microsoft.eShopOnContainers.WebMVC": {
"commandName": "Project", "commandName": "Project",
"launchBrowser": true, "launchUrl": "http://localhost:4001",
"launchUrl": "http://localhost:5000", "environmentVariables": {
"environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development"
"ASPNETCORE_ENVIRONMENT": "Development" },
} "applicationUrl": "https://localhost:4001;http://localhost:5001"
} }
} }
} }

View File

@ -45,11 +45,12 @@ namespace Microsoft.eShopOnContainers.WebMVC.Services
var responseString = await _httpClient.GetStringAsync(uri); var responseString = await _httpClient.GetStringAsync(uri);
var items = new List<SelectListItem>(); var items = new List<SelectListItem>
{
new SelectListItem() { Value = null, Text = "All", Selected = true }
};
items.Add(new SelectListItem() { Value = null, Text = "All", Selected = true }); var brands = JArray.Parse(responseString);
var brands = JArray.Parse(responseString);
foreach (var brand in brands.Children<JObject>()) foreach (var brand in brands.Children<JObject>())
{ {

View File

@ -24,258 +24,278 @@ using WebMVC.Services;
namespace Microsoft.eShopOnContainers.WebMVC namespace Microsoft.eShopOnContainers.WebMVC
{ {
public class Startup public class Startup
{ {
public Startup(IConfiguration configuration) public Startup(IConfiguration configuration)
{ {
Configuration = configuration; Configuration = configuration;
} }
public IConfiguration Configuration { get; } public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the IoC container. // This method gets called by the runtime. Use this method to add services to the IoC container.
public void ConfigureServices(IServiceCollection services) public void ConfigureServices(IServiceCollection services)
{ {
services.AddAppInsight(Configuration) services.Configure<CookiePolicyOptions>(opts =>
.AddHealthChecks(Configuration) {
.AddCustomMvc(Configuration) opts.MinimumSameSitePolicy = SameSiteMode.None;
.AddHttpClientServices(Configuration) opts.CheckConsentNeeded = context => true;
//.AddHttpClientLogging(Configuration) //Opt-in HttpClientLogging config });
.AddCustomAuthentication(Configuration); services
} .AddAppInsight(Configuration)
.AddHealthChecks(Configuration)
.AddCustomMvc(Configuration)
.AddHttpClientServices(Configuration)
//.AddHttpClientLogging(Configuration) //Opt-in HttpClientLogging config
.AddCustomAuthentication(Configuration);
services.AddHttpsRedirection(options =>
{
options.HttpsPort = 4100;
});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline. // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{ {
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear(); JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
loggerFactory.AddAzureWebAppDiagnostics(); loggerFactory.AddAzureWebAppDiagnostics();
loggerFactory.AddApplicationInsights(app.ApplicationServices, LogLevel.Trace); loggerFactory.AddApplicationInsights(app.ApplicationServices, LogLevel.Trace);
if (env.IsDevelopment()) if (env.IsDevelopment())
{ {
app.UseDeveloperExceptionPage(); app.UseDeveloperExceptionPage();
} }
else else
{ {
app.UseExceptionHandler("/Error"); app.UseExceptionHandler("/Error");
} app.UseHsts();
}
var pathBase = Configuration["PATH_BASE"]; app.UseHttpsRedirection();
if (!string.IsNullOrEmpty(pathBase)) app.UseCookiePolicy();
{
loggerFactory.CreateLogger("init").LogDebug($"Using PATH BASE '{pathBase}'"); string pathBase = Configuration["PATH_BASE"];
app.UsePathBase(pathBase); if (!string.IsNullOrEmpty(pathBase))
} {
loggerFactory.CreateLogger("init").LogDebug($"Using PATH BASE '{pathBase}'");
app.UsePathBase(pathBase);
}
#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously #pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously
app.Map("/liveness", lapp => lapp.Run(async ctx => ctx.Response.StatusCode = 200)); app.Map("/liveness", lapp => lapp.Run(async ctx => ctx.Response.StatusCode = 200));
#pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously #pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously
app.UseSession(); app.UseSession();
app.UseStaticFiles(); app.UseStaticFiles();
if (Configuration.GetValue<bool>("UseLoadTest")) if (Configuration.GetValue<bool>("UseLoadTest"))
{ {
app.UseMiddleware<ByPassAuthMiddleware>(); app.UseMiddleware<ByPassAuthMiddleware>();
} }
app.UseAuthentication(); app.UseAuthentication();
var log = loggerFactory.CreateLogger("identity"); ILogger log = loggerFactory.CreateLogger("identity");
WebContextSeed.Seed(app, env, loggerFactory); WebContextSeed.Seed(app, env, loggerFactory);
app.UseMvc(routes => app.UseMvc(routes =>
{ {
routes.MapRoute( routes.MapRoute(
name: "default", name: "default",
template: "{controller=Catalog}/{action=Index}/{id?}"); template: "{controller=Catalog}/{action=Index}/{id?}");
routes.MapRoute( routes.MapRoute(
name: "defaultError", name: "defaultError",
template: "{controller=Error}/{action=Error}"); template: "{controller=Error}/{action=Error}");
}); });
} }
} }
static class ServiceCollectionExtensions static class ServiceCollectionExtensions
{ {
public static IServiceCollection AddAppInsight(this IServiceCollection services, IConfiguration configuration) public static IServiceCollection AddAppInsight(this IServiceCollection services, IConfiguration configuration)
{ {
services.AddApplicationInsightsTelemetry(configuration); services.AddApplicationInsightsTelemetry(configuration);
var orchestratorType = configuration.GetValue<string>("OrchestratorType"); string orchestratorType = configuration.GetValue<string>("OrchestratorType");
if (orchestratorType?.ToUpper() == "K8S") if (orchestratorType?.ToUpper() == "K8S")
{ {
// Enable K8s telemetry initializer // Enable K8s telemetry initializer
services.EnableKubernetes(); services.EnableKubernetes();
} }
if (orchestratorType?.ToUpper() == "SF") if (orchestratorType?.ToUpper() == "SF")
{ {
// Enable SF telemetry initializer // Enable SF telemetry initializer
services.AddSingleton<ITelemetryInitializer>((serviceProvider) => services.AddSingleton<ITelemetryInitializer>((serviceProvider) =>
new FabricTelemetryInitializer()); new FabricTelemetryInitializer());
} }
return services; return services;
} }
public static IServiceCollection AddHealthChecks(this IServiceCollection services, IConfiguration configuration) public static IServiceCollection AddHealthChecks(this IServiceCollection services, IConfiguration configuration)
{ {
services.AddHealthChecks(checks => services.AddHealthChecks(checks =>
{ {
var minutes = 1; int minutes = 1;
if (int.TryParse(configuration["HealthCheck:Timeout"], out var minutesParsed)) if (int.TryParse(configuration["HealthCheck:Timeout"], out int minutesParsed))
{ {
minutes = minutesParsed; minutes = minutesParsed;
} }
checks.AddUrlCheck(configuration["CatalogUrlHC"], TimeSpan.FromMinutes(minutes)); checks.AddUrlCheck(configuration["CatalogUrlHC"], TimeSpan.FromMinutes(minutes));
checks.AddUrlCheck(configuration["OrderingUrlHC"], TimeSpan.FromMinutes(minutes)); checks.AddUrlCheck(configuration["OrderingUrlHC"], TimeSpan.FromMinutes(minutes));
checks.AddUrlCheck(configuration["BasketUrlHC"], TimeSpan.Zero); //No cache for this HealthCheck, better just for demos checks.AddUrlCheck(configuration["BasketUrlHC"], TimeSpan.Zero); //No cache for this HealthCheck, better just for demos
checks.AddUrlCheck(configuration["IdentityUrlHC"], TimeSpan.FromMinutes(minutes)); checks.AddUrlCheck(configuration["IdentityUrlHC"], TimeSpan.FromMinutes(minutes));
checks.AddUrlCheck(configuration["MarketingUrlHC"], TimeSpan.FromMinutes(minutes)); checks.AddUrlCheck(configuration["MarketingUrlHC"], TimeSpan.FromMinutes(minutes));
}); });
return services; return services;
} }
public static IServiceCollection AddCustomMvc(this IServiceCollection services, IConfiguration configuration) public static IServiceCollection AddCustomMvc(this IServiceCollection services, IConfiguration configuration)
{ {
services.AddOptions(); services.AddOptions();
services.Configure<AppSettings>(configuration); services.Configure<AppSettings>(configuration);
services.AddMvc(); services
.AddMvc(opts =>
{
opts.SslPort = 4100;
opts.RequireHttpsPermanent = true;
})
.SetCompatibilityVersion(AspNetCore.Mvc.CompatibilityVersion.Version_2_1);
services.AddSession(); services.AddSession();
if (configuration.GetValue<string>("IsClusterEnv") == bool.TrueString) if (configuration.GetValue<string>("IsClusterEnv") == bool.TrueString)
{ {
services.AddDataProtection(opts => services.AddDataProtection(opts =>
{ {
opts.ApplicationDiscriminator = "eshop.webmvc"; opts.ApplicationDiscriminator = "eshop.webmvc";
}) })
.PersistKeysToRedis(ConnectionMultiplexer.Connect(configuration["DPConnectionString"]), "DataProtection-Keys"); .PersistKeysToRedis(ConnectionMultiplexer.Connect(configuration["DPConnectionString"]), "DataProtection-Keys");
} }
return services; return services;
} }
// Adds all Http client services (like Service-Agents) using resilient Http requests based on HttpClient factory and Polly's policies // Adds all Http client services (like Service-Agents) using resilient Http requests based on HttpClient factory and Polly's policies
public static IServiceCollection AddHttpClientServices(this IServiceCollection services, IConfiguration configuration) public static IServiceCollection AddHttpClientServices(this IServiceCollection services, IConfiguration configuration)
{ {
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>(); services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
//register delegating handlers //register delegating handlers
services.AddTransient<HttpClientAuthorizationDelegatingHandler>(); services.AddTransient<HttpClientAuthorizationDelegatingHandler>();
services.AddTransient<HttpClientRequestIdDelegatingHandler>(); services.AddTransient<HttpClientRequestIdDelegatingHandler>();
//set 5 min as the lifetime for each HttpMessageHandler int the pool //set 5 min as the lifetime for each HttpMessageHandler int the pool
services.AddHttpClient("extendedhandlerlifetime").SetHandlerLifetime(TimeSpan.FromMinutes(5)); services.AddHttpClient("extendedhandlerlifetime").SetHandlerLifetime(TimeSpan.FromMinutes(5));
//add http client services //add http client services
services.AddHttpClient<IBasketService, BasketService>() services.AddHttpClient<IBasketService, BasketService>()
.SetHandlerLifetime(TimeSpan.FromMinutes(5)) //Sample. Default lifetime is 2 minutes .SetHandlerLifetime(TimeSpan.FromMinutes(5)) //Sample. Default lifetime is 2 minutes
.AddHttpMessageHandler<HttpClientAuthorizationDelegatingHandler>() .AddHttpMessageHandler<HttpClientAuthorizationDelegatingHandler>()
.AddPolicyHandler(GetRetryPolicy()) .AddPolicyHandler(GetRetryPolicy())
.AddPolicyHandler(GetCircuitBreakerPolicy()); .AddPolicyHandler(GetCircuitBreakerPolicy());
services.AddHttpClient<ICatalogService, CatalogService>() services.AddHttpClient<ICatalogService, CatalogService>()
.AddPolicyHandler(GetRetryPolicy()) .AddPolicyHandler(GetRetryPolicy())
.AddPolicyHandler(GetCircuitBreakerPolicy()); .AddPolicyHandler(GetCircuitBreakerPolicy());
services.AddHttpClient<IOrderingService, OrderingService>() services.AddHttpClient<IOrderingService, OrderingService>()
.AddHttpMessageHandler<HttpClientAuthorizationDelegatingHandler>() .AddHttpMessageHandler<HttpClientAuthorizationDelegatingHandler>()
.AddHttpMessageHandler<HttpClientRequestIdDelegatingHandler>() .AddHttpMessageHandler<HttpClientRequestIdDelegatingHandler>()
.AddPolicyHandler(GetRetryPolicy()) .AddPolicyHandler(GetRetryPolicy())
.AddPolicyHandler(GetCircuitBreakerPolicy()); .AddPolicyHandler(GetCircuitBreakerPolicy());
services.AddHttpClient<ICampaignService, CampaignService>() services.AddHttpClient<ICampaignService, CampaignService>()
.AddHttpMessageHandler<HttpClientAuthorizationDelegatingHandler>() .AddHttpMessageHandler<HttpClientAuthorizationDelegatingHandler>()
.AddPolicyHandler(GetRetryPolicy()) .AddPolicyHandler(GetRetryPolicy())
.AddPolicyHandler(GetCircuitBreakerPolicy()); .AddPolicyHandler(GetCircuitBreakerPolicy());
services.AddHttpClient<ILocationService, LocationService>() services.AddHttpClient<ILocationService, LocationService>()
.AddHttpMessageHandler<HttpClientAuthorizationDelegatingHandler>() .AddHttpMessageHandler<HttpClientAuthorizationDelegatingHandler>()
.AddPolicyHandler(GetRetryPolicy()) .AddPolicyHandler(GetRetryPolicy())
.AddPolicyHandler(GetCircuitBreakerPolicy()); .AddPolicyHandler(GetCircuitBreakerPolicy());
//add custom application services //add custom application services
services.AddTransient<IIdentityParser<ApplicationUser>, IdentityParser>(); services.AddTransient<IIdentityParser<ApplicationUser>, IdentityParser>();
return services; return services;
} }
public static IServiceCollection AddHttpClientLogging(this IServiceCollection services, IConfiguration configuration) public static IServiceCollection AddHttpClientLogging(this IServiceCollection services, IConfiguration configuration)
{ {
services.AddLogging(b => services.AddLogging(b =>
{ {
b.AddFilter((category, level) => true); // Spam the world with logs. b.AddFilter((category, level) => true); // Spam the world with logs.
// Add console logger so we can see all the logging produced by the client by default. // Add console logger so we can see all the logging produced by the client by default.
b.AddConsole(c => c.IncludeScopes = true); b.AddConsole(c => c.IncludeScopes = true);
// Add console logger // Add console logger
b.AddDebug(); b.AddDebug();
}); });
return services; return services;
} }
public static IServiceCollection AddCustomAuthentication(this IServiceCollection services, IConfiguration configuration) public static IServiceCollection AddCustomAuthentication(this IServiceCollection services, IConfiguration configuration)
{ {
var useLoadTest = configuration.GetValue<bool>("UseLoadTest"); bool useLoadTest = configuration.GetValue<bool>("UseLoadTest");
var identityUrl = configuration.GetValue<string>("IdentityUrl"); string identityUrl = configuration.GetValue<string>("IdentityUrl");
var callBackUrl = configuration.GetValue<string>("CallBackUrl"); string callBackUrl = configuration.GetValue<string>("CallBackUrl");
// Add Authentication services // Add Authentication services
services.AddAuthentication(options => services.AddAuthentication(options =>
{ {
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme; options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme; options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
}) })
.AddCookie() .AddCookie()
.AddOpenIdConnect(options => .AddOpenIdConnect(options =>
{ {
options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme; options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.Authority = identityUrl.ToString(); options.Authority = identityUrl.ToString();
options.SignedOutRedirectUri = callBackUrl.ToString(); options.SignedOutRedirectUri = callBackUrl.ToString();
options.ClientId = useLoadTest ? "mvctest" : "mvc"; options.ClientId = useLoadTest ? "mvctest" : "mvc";
options.ClientSecret = "secret"; options.ClientSecret = "secret";
options.ResponseType = useLoadTest ? "code id_token token" : "code id_token"; options.ResponseType = useLoadTest ? "code id_token token" : "code id_token";
options.SaveTokens = true; options.SaveTokens = true;
options.GetClaimsFromUserInfoEndpoint = true; options.GetClaimsFromUserInfoEndpoint = true;
options.RequireHttpsMetadata = false; options.RequireHttpsMetadata = false;
options.Scope.Add("openid"); options.Scope.Add("openid");
options.Scope.Add("profile"); options.Scope.Add("profile");
options.Scope.Add("orders"); options.Scope.Add("orders");
options.Scope.Add("basket"); options.Scope.Add("basket");
options.Scope.Add("marketing"); options.Scope.Add("marketing");
options.Scope.Add("locations"); options.Scope.Add("locations");
options.Scope.Add("webshoppingagg"); options.Scope.Add("webshoppingagg");
options.Scope.Add("orders.signalrhub"); options.Scope.Add("orders.signalrhub");
}); });
return services; return services;
} }
static IAsyncPolicy<HttpResponseMessage> GetRetryPolicy() static IAsyncPolicy<HttpResponseMessage> GetRetryPolicy()
{ {
return HttpPolicyExtensions return HttpPolicyExtensions
.HandleTransientHttpError() .HandleTransientHttpError()
.OrResult(msg => msg.StatusCode == System.Net.HttpStatusCode.NotFound) .OrResult(msg => msg.StatusCode == System.Net.HttpStatusCode.NotFound)
.WaitAndRetryAsync(6, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt))); .WaitAndRetryAsync(6, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)));
} }
static IAsyncPolicy<HttpResponseMessage> GetCircuitBreakerPolicy() static IAsyncPolicy<HttpResponseMessage> GetCircuitBreakerPolicy()
{ {
return HttpPolicyExtensions return HttpPolicyExtensions
.HandleTransientHttpError() .HandleTransientHttpError()
.CircuitBreakerAsync(5, TimeSpan.FromSeconds(30)); .CircuitBreakerAsync(5, TimeSpan.FromSeconds(30));
} }
} }
} }

View File

@ -1,28 +1,30 @@
@{ @{
ViewData["Title"] = "Campaign details"; ViewData["Title"] = "Campaign details";
@model CampaignItem var headers = new List<Header>{
new Header { Controller = "Campaigns", Text = "Back to Campaigns" },
new Header { Controller = "Catalog", Text = "Back to catalog" }
};
@model CampaignItem
} }
<section class="esh-campaigns-hero"> <section class="esh-campaigns-hero">
<div class="container"> <div class="container">
<img class="esh-campaigns-title" src="~/images/main_banner_text.png" /> <img class="esh-campaigns-title" src="~/images/main_banner_text.png" />
</div> </div>
</section> </section>
@Html.Partial("_Header", new List<Header>() { <partial name="_Header" model="headers" />
new Header() { Controller = "Catalog", Text = "Back to catalog" },
new Header() { Controller = "Campaigns", Text = "Back to Campaigns" } })
<div class="container"> <div class="container">
<div class="card esh-campaigns-items"> <div class="card esh-campaigns-items">
<img class="card-img-top" src="@Model.PictureUri" alt="Card image cap"> <img class="card-img-top" src="@Model.PictureUri" alt="Card image cap">
<div class="card-block"> <div class="card-block">
<h4 class="card-title">@Model.Name</h4> <h4 class="card-title">@Model.Name</h4>
<p class="card-text">@Model.Description</p> <p class="card-text">@Model.Description</p>
<p class="card-text"> <p class="card-text">
<small class="text-muted"> <small class="text-muted">
From @Model.From.ToString("MMMM dd, yyyy") until @Model.To.ToString("MMMM dd, yyyy") From @Model.From.ToString("MMMM dd, yyyy") until @Model.To.ToString("MMMM dd, yyyy")
</small> </small>
</p> </p>
</div> </div>
</div> </div>
</div> </div>

View File

@ -1,72 +1,75 @@
@{ @{
ViewData["Title"] = "Campaigns"; ViewData["Title"] = "Campaigns";
@model WebMVC.ViewModels.CampaignViewModel @model WebMVC.ViewModels.CampaignViewModel
var headers = new List<Header>() {
new Header() { Controller = "Catalog", Text = "Back to catalog" } };
} }
<section class="esh-campaigns-hero"> <section class="esh-campaigns-hero">
<div class="container"> <div class="container">
<img class="esh-campaigns-title" src="~/images/main_banner_text.png" /> <img class="esh-campaigns-title" src="~/images/main_banner_text.png" />
</div> </div>
</section> </section>
@Html.Partial("_Header", new List<Header>() { <partial name="_Header" model="headers" />
new Header() { Controller = "Catalog", Text = "Back to catalog" } })
<div class="container"> <div class="container">
<br /> <br />
<div class="row"> <div class="row">
@if (!ViewData.ModelState.IsValid)
{
<div class="alert alert-warning">
@Html.ValidationSummary(false)
</div>
}
<div class="col-md-12"> @if (!ViewData.ModelState.IsValid)
<div class="esh-campaigns-items" style="font-weight: 300;"> {
UPDATE USER LOCATION <div class="alert alert-warning">
</div> @Html.ValidationSummary(false)
</div>
}
<form class="form-inline" asp-action="CreateNewUserLocation" method="post"> <div class="col-md-12">
<label class="sr-only" for="longitudeInput">Name</label> <div class="esh-campaigns-items" style="font-weight: 300;">
UPDATE USER LOCATION
<div class="input-group mb-2 mr-sm-2 mb-sm-0"> </div>
<div class="input-group-addon">Lat</div>
<input type="text" class="form-control mb-2 mr-sm-2 mb-sm-0" id="latitudeInput" asp-for="Lat" placeholder="Latitude">
</div>
<div class="input-group mb-2 mr-sm-2 mb-sm-0"> <form class="form-inline" asp-action="CreateNewUserLocation" method="post">
<div class="input-group-addon">Lon</div> <label class="sr-only" for="longitudeInput">Name</label>
<input type="text" class="form-control mb-2 mr-sm-2 mb-sm-0" id="longitudeInput" asp-for="Lon" placeholder="Longitude">
</div>
<div class="input-group mb-2 mr-sm-2 mb-sm-0 col-md-2">
<input type="submit" value="Update" class="btn esh-campaigns-form-button" />
</div>
</form>
</div>
</div>
<br />
@if (Model != null && Model.CampaignItems !=null && Model.CampaignItems.Any())
{
<div class="card-group esh-campaigns-items row">
@foreach (var catalogItem in Model.CampaignItems)
{
<div class="esh-campaigns-item col-md-4">
@Html.Partial("_campaign", catalogItem)
</div>
}
</div>
@Html.Partial("_pagination", Model.PaginationInfo) <div class="input-group mb-2 mr-sm-2 mb-sm-0">
} <div class="input-group-addon">Lat</div>
else <input type="text" class="form-control mb-2 mr-sm-2 mb-sm-0" id="latitudeInput" asp-for="Lat" placeholder="Latitude">
{ </div>
<div class="esh-campaigns-items row">
THERE ARE NO CAMPAIGNS <div class="input-group mb-2 mr-sm-2 mb-sm-0">
</div> <div class="input-group-addon">Lon</div>
} <input type="text" class="form-control mb-2 mr-sm-2 mb-sm-0" id="longitudeInput" asp-for="Lon" placeholder="Longitude">
</div>
<div class="input-group mb-2 mr-sm-2 mb-sm-0 col-md-2">
<input type="submit" value="Update" class="btn esh-campaigns-form-button" />
</div>
</form>
</div>
</div>
<br />
@if (Model != null && Model.CampaignItems != null && Model.CampaignItems.Any())
{
<div class="card-group esh-campaigns-items row">
@foreach (var catalogItem in Model.CampaignItems)
{
<div class="esh-campaigns-item col-md-4">
@*@Html.Partial("_campaign", catalogItem)*@
<partial name="_campaign" model="catalogItem" />
</div>
}
</div>
@*@Html.Partial("_pagination", Model.PaginationInfo)*@
<partial name="_pagination" model="Model.PaginationInfo" />
}
else
{
<div class="esh-campaigns-items row">
THERE ARE NO CAMPAIGNS
</div>
}
</div> </div>

View File

@ -5,14 +5,14 @@
@inject IIdentityParser<ApplicationUser> UserManager @inject IIdentityParser<ApplicationUser> UserManager
@{ @{
ViewData["Title"] = "My Cart"; ViewData["Title"] = "My Cart";
var headers = new List<Header>() {
new Header() { Controller = "Catalog", Text = "Back to catalog" } };
} }
<form method="post" id="cartForm"> <form method="post" id="cartForm">
<div class="esh-basket"> <div class="esh-basket">
@Html.Partial("_Header", new List<Header>() { <partial name="_header" model="headers" />
new Header() { Controller = "Catalog", Text = "Back to catalog" } }) @await Component.InvokeAsync("CartList", new { user = UserManager.Parse(User) })
</div>
@await Component.InvokeAsync("CartList", new { user = UserManager.Parse(User) })
</div>
</form> </form>

View File

@ -1,57 +1,57 @@
@{ @{
ViewData["Title"] = "Catalog"; ViewData["Title"] = "Catalog";
@model Microsoft.eShopOnContainers.WebMVC.ViewModels.CatalogViewModels.IndexViewModel @model Microsoft.eShopOnContainers.WebMVC.ViewModels.CatalogViewModels.IndexViewModel
} }
<section class="esh-catalog-hero"> <section class="esh-catalog-hero">
<div class="container"> <div class="container">
<img class="esh-catalog-title" src="~/images/main_banner_text.png" /> <img class="esh-catalog-title" src="~/images/main_banner_text.png" />
</div> </div>
</section> </section>
<section class="esh-catalog-filters"> <section class="esh-catalog-filters">
<div class="container"> <div class="container">
<form asp-action="Index" asp-controller="Catalog" method="post"> <form asp-action="Index" asp-controller="Catalog" method="post">
<label class="esh-catalog-label" data-title="brand"> <label class="esh-catalog-label" data-title="brand">
<select asp-for="@Model.BrandFilterApplied" asp-items="@Model.Brands" class="esh-catalog-filter"></select> <select asp-for="@Model.BrandFilterApplied" asp-items="@Model.Brands" class="esh-catalog-filter"></select>
</label> </label>
<label class="esh-catalog-label" data-title="type"> <label class="esh-catalog-label" data-title="type">
<select asp-for="@Model.TypesFilterApplied" asp-items="@Model.Types" class="esh-catalog-filter"></select> <select asp-for="@Model.TypesFilterApplied" asp-items="@Model.Types" class="esh-catalog-filter"></select>
</label> </label>
<input class="esh-catalog-send" type="image" src="~/images/arrow-right.svg" /> <input class="esh-catalog-send" type="image" src="~/images/arrow-right.svg" />
</form> </form>
</div> </div>
</section> </section>
<div class="container"> <div class="container">
<div class="row"> <div class="row">
<br /> <br />
@if(ViewBag.BasketInoperativeMsg != null) @if (ViewBag.BasketInoperativeMsg != null)
{ {
<div class="alert alert-warning" role="alert"> <div class="alert alert-warning" role="alert">
&nbsp;@ViewBag.BasketInoperativeMsg &nbsp;@ViewBag.BasketInoperativeMsg
</div> </div>
} }
</div> </div>
@if (Model.CatalogItems.Count() > 0) @if (Model.CatalogItems.Count() > 0)
{ {
@Html.Partial("_pagination", Model.PaginationInfo) <partial name="_pagination" model="Model.PaginationInfo" />
<div class="esh-catalog-items row"> <div class="esh-catalog-items row">
@foreach (var catalogItem in Model.CatalogItems) @foreach (var catalogItem in Model.CatalogItems)
{ {
<div class="esh-catalog-item col-md-4"> <div class="esh-catalog-item col-md-4">
@Html.Partial("_product", catalogItem) <partial name="_product" , model="catalogItem" />
</div> </div>
} }
</div> </div>
@Html.Partial("_pagination", Model.PaginationInfo) <partial name="_pagination" model="Model.PaginationInfo" />
} }
else else
{ {
<div class="esh-catalog-items row"> <div class="esh-catalog-items row">
THERE ARE NO RESULTS THAT MATCH YOUR SEARCH THERE ARE NO RESULTS THAT MATCH YOUR SEARCH
</div> </div>
} }
</div> </div>

View File

@ -0,0 +1,6 @@
@{
ViewData["Title"] = "Privacy Policy";
}
<h2>@ViewData["Title"]</h2>
<p>Use this page to detail your site's privacy policy.</p>

View File

@ -3,103 +3,105 @@
@inject IIdentityParser<ApplicationUser> UserManager @inject IIdentityParser<ApplicationUser> UserManager
@{ @{
ViewData["Title"] = "New Order"; ViewData["Title"] = "New Order";
var header = new Header { Controller = "Cart", Text = "Back to cart" };
} }
@Html.Partial("_Header", new List<Header>() { <partial name="_header" model="new List<Header> { header }" />
new Header() { Controller = "Cart", Text = "Back to cart" } })
<div class="container"> <div class="container">
<form method="post" asp-controller="Order" asp-action="Checkout"> <form method="post" asp-controller="Order" asp-action="Checkout">
<section class="esh-orders_new-section"> <section class="esh-orders_new-section">
<div class="row"> <div class="row">
@foreach (var error in ViewData.ModelState.Values.SelectMany(err => err.Errors)) { @foreach (var error in ViewData.ModelState.Values.SelectMany(err => err.Errors))
<div class="alert alert-warning" role="alert"> {
&nbsp;@error.ErrorMessage <div class="alert alert-warning" role="alert">
</div> &nbsp;@error.ErrorMessage
} </div>
</div> }
<h4 class="esh-orders_new-title">Shipping address</h4> </div>
<div class="row"> <h4 class="esh-orders_new-title">Shipping address</h4>
<div class="col-md-6"> <div class="row">
<div class="form-group"> <div class="col-md-6">
<label asp-for="Street" class="esh-orders_new-title">Address</label> <div class="form-group">
<input asp-for="Street" class="form-control form-input" type="text" placeholder="Street"/> <label asp-for="Street" class="esh-orders_new-title">Address</label>
<span asp-validation-for="Street" class="alert alert-danger" /> <input asp-for="Street" class="form-control form-input" type="text" placeholder="Street" />
</div> <span asp-validation-for="Street" class="alert alert-danger" />
</div> </div>
<div class="col-md-6"> </div>
<div class="form-group"> <div class="col-md-6">
<label asp-for="City" class="esh-orders_new-title">City</label> <div class="form-group">
<input asp-for="City" class="form-control form-input" type="text" placeholder="City"/> <label asp-for="City" class="esh-orders_new-title">City</label>
<span asp-validation-for="City" class="alert alert-danger" /> <input asp-for="City" class="form-control form-input" type="text" placeholder="City" />
</div> <span asp-validation-for="City" class="alert alert-danger" />
</div> </div>
<div class="col-md-6"> </div>
<div class="form-group"> <div class="col-md-6">
<label asp-for="State" class="esh-orders_new-title">State</label> <div class="form-group">
<input asp-for="State" class="form-control form-input" type="text" placeholder="State"/> <label asp-for="State" class="esh-orders_new-title">State</label>
<span asp-validation-for="State" class="alert alert-danger" /> <input asp-for="State" class="form-control form-input" type="text" placeholder="State" />
</div> <span asp-validation-for="State" class="alert alert-danger" />
</div> </div>
<div class="col-md-6"> </div>
<div class="form-group"> <div class="col-md-6">
<label asp-for="Country" class="esh-orders_new-title">Country</label> <div class="form-group">
<input asp-for="Country" class="form-control form-input" type="text" placeholder="Country"/> <label asp-for="Country" class="esh-orders_new-title">Country</label>
<span asp-validation-for="Country" class="alert alert-danger" /> <input asp-for="Country" class="form-control form-input" type="text" placeholder="Country" />
</div> <span asp-validation-for="Country" class="alert alert-danger" />
</div> </div>
</div> </div>
</section> </div>
<section class="esh-orders_new-section"> </section>
<h4 class="esh-orders_new-title">Payment method</h4> <section class="esh-orders_new-section">
<div class="row"> <h4 class="esh-orders_new-title">Payment method</h4>
<div class="col-md-6"> <div class="row">
<div class="form-group"> <div class="col-md-6">
<label asp-for="CardNumber" class="esh-orders_new-title">Card number</label> <div class="form-group">
<input asp-for="CardNumber" class="form-control form-input" type="text" placeholder="000000000000000"/> <label asp-for="CardNumber" class="esh-orders_new-title">Card number</label>
<span asp-validation-for="CardNumber" class="alert alert-danger" /> <input asp-for="CardNumber" class="form-control form-input" type="text" placeholder="000000000000000" />
</div> <span asp-validation-for="CardNumber" class="alert alert-danger" />
</div> </div>
<div class="col-md-6"> </div>
<div class="form-group"> <div class="col-md-6">
<label asp-for="CardHolderName" class="esh-orders_new-title">Cardholder name</label> <div class="form-group">
<input asp-for="CardHolderName" class="form-control form-input" type="text" placeholder="Cardholder"/> <label asp-for="CardHolderName" class="esh-orders_new-title">Cardholder name</label>
<span asp-validation-for="CardHolderName" class="alert alert-danger" /> <input asp-for="CardHolderName" class="form-control form-input" type="text" placeholder="Cardholder" />
</div> <span asp-validation-for="CardHolderName" class="alert alert-danger" />
</div> </div>
<div class="col-md-6"> </div>
<div class="form-group"> <div class="col-md-6">
<label asp-for="CardExpirationShort" class="esh-orders_new-title">Expiration date</label> <div class="form-group">
<input asp-for="CardExpirationShort" class="form-control form-input form-input-medium" type="text" placeholder="MM/YY"/> <label asp-for="CardExpirationShort" class="esh-orders_new-title">Expiration date</label>
<span asp-validation-for="CardExpirationShort" class="alert alert-danger" /> <input asp-for="CardExpirationShort" class="form-control form-input form-input-medium" type="text" placeholder="MM/YY" />
</div> <span asp-validation-for="CardExpirationShort" class="alert alert-danger" />
</div> </div>
<div class="col-md-6"> </div>
<div class="form-group"> <div class="col-md-6">
<label asp-for="CardSecurityNumber" class="esh-orders_new-title">Security code</label> <div class="form-group">
<input asp-for="CardSecurityNumber" class="form-control form-input form-input-small" type="text" placeholder="000"/> <label asp-for="CardSecurityNumber" class="esh-orders_new-title">Security code</label>
<span asp-validation-for="CardSecurityNumber" class="alert alert-danger" /> <input asp-for="CardSecurityNumber" class="form-control form-input form-input-small" type="text" placeholder="000" />
</div> <span asp-validation-for="CardSecurityNumber" class="alert alert-danger" />
</div> </div>
</div> </div>
</section> </div>
</section>
@await Html.PartialAsync("_OrderItems") <partial name="_OrderItems" />
<section class="esh-orders_new-section"> <section class="esh-orders_new-section">
<div class="form-group"> <div class="form-group">
<div class="col-md-9"> <div class="col-md-9">
</div> </div>
<div class="col-md-2"> <div class="col-md-2">
<input type="submit" value="[ Place Order ]" name="action" class="btn esh-orders_new-placeOrder" /> <input type="submit" value="[ Place Order ]" name="action" class="btn esh-orders_new-placeOrder" />
</div> </div>
</div> </div>
</section> </section>
<input asp-for="ZipCode" type="hidden" /> <input asp-for="ZipCode" type="hidden" />
<input asp-for="RequestId" type="hidden" value="@Guid.NewGuid().ToString()"/> <input asp-for="RequestId" type="hidden" value="@Guid.NewGuid().ToString()" />
</form> </form>
</div> </div>
@section Scripts { @section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");} <partial name="_ValidationScriptsPartial" />
} }

View File

@ -3,88 +3,89 @@
@model Microsoft.eShopOnContainers.WebMVC.ViewModels.Order @model Microsoft.eShopOnContainers.WebMVC.ViewModels.Order
@{ @{
ViewData["Title"] = "Order Detail"; ViewData["Title"] = "Order Detail";
var headers = new List<Header>() {
new Header() { Controller = "Catalog", Text = "Back to catalog" } };
} }
<div class="esh-orders_detail"> <div class="esh-orders_detail">
@Html.Partial("_Header", new List<Header>() { <partial name="_Header" model="headers" />
new Header() { Controller = "Catalog", Text = "Back to catalog" } })
<div class="container"> <div class="container">
<section class="esh-orders_detail-section"> <section class="esh-orders_detail-section">
<article class="esh-orders_detail-titles row"> <article class="esh-orders_detail-titles row">
<section class="esh-orders_detail-title col-xs-3">Order number</section> <section class="esh-orders_detail-title col-xs-3">Order number</section>
<section class="esh-orders_detail-title col-xs-3">Date</section> <section class="esh-orders_detail-title col-xs-3">Date</section>
<section class="esh-orders_detail-title col-xs-3">Total</section> <section class="esh-orders_detail-title col-xs-3">Total</section>
<section class="esh-orders_detail-title col-xs-3">Status</section> <section class="esh-orders_detail-title col-xs-3">Status</section>
</article> </article>
<article class="esh-orders_detail-items row"> <article class="esh-orders_detail-items row">
<section class="esh-orders_detail-item col-xs-3">@Model.OrderNumber</section> <section class="esh-orders_detail-item col-xs-3">@Model.OrderNumber</section>
<section class="esh-orders_detail-item col-xs-3">@Model.Date</section> <section class="esh-orders_detail-item col-xs-3">@Model.Date</section>
<section class="esh-orders_detail-item col-xs-3">$@Model.Total</section> <section class="esh-orders_detail-item col-xs-3">$@Model.Total</section>
<section class="esh-orders_detail-title col-xs-3">@Model.Status</section> <section class="esh-orders_detail-title col-xs-3">@Model.Status</section>
</article> </article>
</section> </section>
<section class="esh-orders_detail-section">
<article class="esh-orders_detail-titles row">
<section class="esh-orders_detail-title col-xs-12">Description</section>
</article>
<article class="esh-orders_detail-items row"> <section class="esh-orders_detail-section">
<section class="esh-orders_detail-item col-xs-12">@Model.Description</section> <article class="esh-orders_detail-titles row">
</article> <section class="esh-orders_detail-title col-xs-12">Description</section>
</section> </article>
<section class="esh-orders_detail-section"> <article class="esh-orders_detail-items row">
<article class="esh-orders_detail-titles row"> <section class="esh-orders_detail-item col-xs-12">@Model.Description</section>
<section class="esh-orders_detail-title col-xs-12">Shiping address</section> </article>
</article> </section>
<article class="esh-orders_detail-items row"> <section class="esh-orders_detail-section">
<section class="esh-orders_detail-item col-xs-12">@Model.Street</section> <article class="esh-orders_detail-titles row">
</article> <section class="esh-orders_detail-title col-xs-12">Shiping address</section>
</article>
<article class="esh-orders_detail-items row"> <article class="esh-orders_detail-items row">
<section class="esh-orders_detail-item col-xs-12">@Model.City</section> <section class="esh-orders_detail-item col-xs-12">@Model.Street</section>
</article> </article>
<article class="esh-orders_detail-items row"> <article class="esh-orders_detail-items row">
<section class="esh-orders_detail-item col-xs-12">@Model.Country</section> <section class="esh-orders_detail-item col-xs-12">@Model.City</section>
</article> </article>
</section>
<section class="esh-orders_detail-section"> <article class="esh-orders_detail-items row">
<article class="esh-orders_detail-titles row"> <section class="esh-orders_detail-item col-xs-12">@Model.Country</section>
<section class="esh-orders_detail-title col-xs-12">ORDER DETAILS</section> </article>
</article> </section>
@for (int i = 0; i < Model.OrderItems.Count; i++) <section class="esh-orders_detail-section">
{ <article class="esh-orders_detail-titles row">
var item = Model.OrderItems[i]; <section class="esh-orders_detail-title col-xs-12">ORDER DETAILS</section>
<article class="esh-orders_detail-items esh-orders_detail-items--border row"> </article>
<section class="esh-orders_detail-item col-md-4 hidden-md-down">
<img class="esh-orders_detail-image" src="@item.PictureUrl">
</section>
<section class="esh-orders_detail-item esh-orders_detail-item--middle col-xs-4">@item.ProductName</section>
<section class="esh-orders_detail-item esh-orders_detail-item--middle col-xs-1">$ @item.UnitPrice.ToString("N2")</section>
<section class="esh-orders_detail-item esh-orders_detail-item--middle col-xs-1">@item.Units</section>
<section class="esh-orders_detail-item esh-orders_detail-item--middle col-xs-2">$ @Math.Round(item.Units * item.UnitPrice, 2).ToString("N2")</section>
</article>
}
</section>
<section class="esh-orders_detail-section esh-orders_detail-section--right"> @for (int i = 0; i < Model.OrderItems.Count; i++)
<article class="esh-orders_detail-titles esh-basket-titles--clean row"> {
<section class="esh-orders_detail-title col-xs-9"></section> var item = Model.OrderItems[i];
<section class="esh-orders_detail-title col-xs-2">TOTAL</section> <article class="esh-orders_detail-items esh-orders_detail-items--border row">
</article> <section class="esh-orders_detail-item col-md-4 hidden-md-down">
<img class="esh-orders_detail-image" src="@item.PictureUrl">
</section>
<section class="esh-orders_detail-item esh-orders_detail-item--middle col-xs-4">@item.ProductName</section>
<section class="esh-orders_detail-item esh-orders_detail-item--middle col-xs-1">$ @item.UnitPrice.ToString("N2")</section>
<section class="esh-orders_detail-item esh-orders_detail-item--middle col-xs-1">@item.Units</section>
<section class="esh-orders_detail-item esh-orders_detail-item--middle col-xs-2">$ @Math.Round(item.Units * item.UnitPrice, 2).ToString("N2")</section>
</article>
}
</section>
<article class="esh-orders_detail-items row"> <section class="esh-orders_detail-section esh-orders_detail-section--right">
<section class="esh-orders_detail-item col-xs-9"></section> <article class="esh-orders_detail-titles esh-basket-titles--clean row">
<section class="esh-orders_detail-item esh-orders_detail-item--mark col-xs-2">$ @Model.Total</section> <section class="esh-orders_detail-title col-xs-9"></section>
</article> <section class="esh-orders_detail-title col-xs-2">TOTAL</section>
</section> </article>
</div>
<article class="esh-orders_detail-items row">
<section class="esh-orders_detail-item col-xs-9"></section>
<section class="esh-orders_detail-item esh-orders_detail-item--mark col-xs-2">$ @Model.Total</section>
</article>
</section>
</div>
</div> </div>

View File

@ -3,45 +3,47 @@
@model IEnumerable<Microsoft.eShopOnContainers.WebMVC.ViewModels.Order> @model IEnumerable<Microsoft.eShopOnContainers.WebMVC.ViewModels.Order>
@{ @{
ViewData["Title"] = "My Orders"; ViewData["Title"] = "My Orders";
var headers = new List<Header>() {
new Header() { Controller = "Catalog", Text = "Back to catalog" },
new Header() { Text = " / " },
new Header() { Controller = "OrderManagement", Text = "Orders Management" }
};
} }
<div class="esh-orders"> <div class="esh-orders">
@Html.Partial("_Header", new List<Header>() { <partial name="_Header" model="headers" />
new Header() { Controller = "Catalog", Text = "Back to catalog" },
new Header() { Text = " / " },
new Header() { Controller = "OrderManagement", Text = "Orders Management" } })
<div class="container"> <div class="container">
<article class="esh-orders-titles row"> <article class="esh-orders-titles row">
<section class="esh-orders-title col-xs-2">Order number</section> <section class="esh-orders-title col-xs-2">Order number</section>
<section class="esh-orders-title col-xs-4">Date</section> <section class="esh-orders-title col-xs-4">Date</section>
<section class="esh-orders-title col-xs-2">Total</section> <section class="esh-orders-title col-xs-2">Total</section>
<section class="esh-orders-title col-xs-2">Status</section> <section class="esh-orders-title col-xs-2">Status</section>
<section class="esh-orders-title col-xs-2"></section> <section class="esh-orders-title col-xs-2"></section>
</article> </article>
@if (Model != null && Model.Any()) @if (Model != null && Model.Any())
{ {
foreach (var item in Model) foreach (var item in Model)
{ {
<article class="esh-orders-items row"> <article class="esh-orders-items row">
<section class="esh-orders-item col-xs-2">@Html.DisplayFor(modelItem => item.OrderNumber)</section> <section class="esh-orders-item col-xs-2">@Html.DisplayFor(modelItem => item.OrderNumber)</section>
<section class="esh-orders-item col-xs-4">@Html.DisplayFor(modelItem => item.Date)</section> <section class="esh-orders-item col-xs-4">@Html.DisplayFor(modelItem => item.Date)</section>
<section class="esh-orders-item col-xs-2">$ @Html.DisplayFor(modelItem => item.Total)</section> <section class="esh-orders-item col-xs-2">$ @Html.DisplayFor(modelItem => item.Total)</section>
<section class="esh-orders-item col-xs-2">@Html.DisplayFor(modelItem => item.Status)</section> <section class="esh-orders-item col-xs-2">@Html.DisplayFor(modelItem => item.Status)</section>
<section class="esh-orders-item col-xs-1"> <section class="esh-orders-item col-xs-1">
<a class="esh-orders-link" asp-controller="Order" asp-action="Detail" asp-route-orderId="@item.OrderNumber">Detail</a> <a class="esh-orders-link" asp-controller="Order" asp-action="Detail" asp-route-orderId="@item.OrderNumber">Detail</a>
</section> </section>
<section class="esh-orders-item col-xs-1"> <section class="esh-orders-item col-xs-1">
@if (item.Status.ToLower() == "submitted") @if (item.Status.ToLower() == "submitted")
{ {
<a class="esh-orders-link" asp-controller="Order" asp-action="cancel" asp-route-orderId="@item.OrderNumber">Cancel</a> <a class="esh-orders-link" asp-controller="Order" asp-action="cancel" asp-route-orderId="@item.OrderNumber">Cancel</a>
} }
</section> </section>
</article> </article>
} }
} }
</div> </div>
</div> </div>

View File

@ -3,41 +3,42 @@
@model IEnumerable<Microsoft.eShopOnContainers.WebMVC.ViewModels.Order> @model IEnumerable<Microsoft.eShopOnContainers.WebMVC.ViewModels.Order>
@{ @{
ViewData["Title"] = "My Orders"; ViewData["Title"] = "My Orders";
var headers = new List<Header>() {
new Header { Controller = " Catalog", Text="Back to catalog" } };
} }
<div class="esh-orders"> <div class="esh-orders">
@Html.Partial("_Header", new List<Header>() { <partial name="_Header" model="headers" />
new Header() { Controller = "Catalog", Text = "Back to catalog" } })
<div class="container"> <div class="container">
<article class="esh-orders-titles row"> <article class="esh-orders-titles row">
<section class="esh-orders-title col-xs-2">Order number</section> <section class="esh-orders-title col-xs-2">Order number</section>
<section class="esh-orders-title col-xs-4">Date</section> <section class="esh-orders-title col-xs-4">Date</section>
<section class="esh-orders-title col-xs-2">Total</section> <section class="esh-orders-title col-xs-2">Total</section>
<section class="esh-orders-title col-xs-2">Status</section> <section class="esh-orders-title col-xs-2">Status</section>
<section class="esh-orders-title col-xs-2"></section> <section class="esh-orders-title col-xs-2"></section>
</article> </article>
@foreach (var item in Model) @foreach (var item in Model)
{ {
<article class="esh-orders-items row"> <article class="esh-orders-items row">
<section class="esh-orders-item col-xs-2">@Html.DisplayFor(modelItem => item.OrderNumber)</section> <section class="esh-orders-item col-xs-2">@Html.DisplayFor(modelItem => item.OrderNumber)</section>
<section class="esh-orders-item col-xs-4">@Html.DisplayFor(modelItem => item.Date)</section> <section class="esh-orders-item col-xs-4">@Html.DisplayFor(modelItem => item.Date)</section>
<section class="esh-orders-item col-xs-2">$ @Html.DisplayFor(modelItem => item.Total)</section> <section class="esh-orders-item col-xs-2">$ @Html.DisplayFor(modelItem => item.Total)</section>
<section class="esh-orders-item col-xs-2">@Html.DisplayFor(modelItem => item.Status)</section> <section class="esh-orders-item col-xs-2">@Html.DisplayFor(modelItem => item.Status)</section>
<section class="esh-orders-item col-xs-2"> <section class="esh-orders-item col-xs-2">
<form asp-action="OrderProcess" id="orderForm+@item.OrderNumber" method="post"> <form asp-action="OrderProcess" id="orderForm+@item.OrderNumber" method="post">
<input type="hidden" name="orderId" value="@item.OrderNumber" /> <input type="hidden" name="orderId" value="@item.OrderNumber" />
<select name="actionCode" asp-items="@item.ActionCodeSelectList" <select name="actionCode" asp-items="@item.ActionCodeSelectList"
disabled=@(item.Status != "paid") disabled=@(item.Status != "paid")
onchange="document.getElementById('orderForm+@item.OrderNumber').submit()"> onchange="document.getElementById('orderForm+@item.OrderNumber').submit()">
<option value="">&nbsp;&nbsp;Select Action</option> <option value="">&nbsp;&nbsp;Select Action</option>
<option value="">------------------</option> <option value="">------------------</option>
</select> </select>
</form> </form>
</section> </section>
</article> </article>
} }
</div> </div>
</div> </div>

View File

@ -0,0 +1,41 @@
@using Microsoft.AspNetCore.Http.Features
@{
var consentFeature = Context.Features.Get<ITrackingConsentFeature>();
var showBanner = !consentFeature?.CanTrack ?? false;
var cookieString = consentFeature?.CreateConsentCookie();
}
@if (showBanner)
{
<nav id="cookieConsent" class="navbar navbar-default navbar-fixed-top" role="alert">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#cookieConsent .navbar-collapse">
<span class="sr-only">Toggle cookie consent banner</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<span class="navbar-brand"><span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span></span>
</div>
<div class="collapse navbar-collapse">
<p class="navbar-text">
Use this space to summarize your privacy and cookie use policy.
</p>
<div class="navbar-right">
<a asp-controller="Home" asp-action="Privacy" class="btn btn-info navbar-btn">Learn More</a>
<button type="button" class="btn btn-default navbar-btn" data-cookie-string="@cookieString">Accept</button>
</div>
</div>
</div>
</nav>
<script>
(function () {
document.querySelector("#cookieConsent button[data-cookie-string]").addEventListener("click", function (el) {
document.cookie = el.target.dataset.cookieString;
document.querySelector("#cookieConsent").classList.add("hidden");
}, false);
})();
</script>
}

View File

@ -49,6 +49,7 @@
</div> </div>
</header> </header>
<partial name="_CookieConsentPartial" />
@RenderBody() @RenderBody()

View File

@ -1,52 +1,50 @@
<Project Sdk="Microsoft.NET.Sdk.Web"> <Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup> <PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework> <TargetFramework>netcoreapp2.1</TargetFramework>
<UserSecretsId>aspnet-Microsoft.eShopOnContainers-946ae052-8305-4a99-965b-ec8636ddbae3</UserSecretsId> <RuntimeFrameworkVersion>2.1.3</RuntimeFrameworkVersion>
<DockerComposeProjectPath>..\..\..\docker-compose.dcproj</DockerComposeProjectPath> <UserSecretsId>aspnet-Microsoft.eShopOnContainers-946ae052-8305-4a99-965b-ec8636ddbae3</UserSecretsId>
</PropertyGroup> <DockerComposeProjectPath>..\..\..\docker-compose.dcproj</DockerComposeProjectPath>
</PropertyGroup>
<ItemGroup> <ItemGroup>
<Content Include="Setup\images.zip"> <Content Include="Setup\images.zip">
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory> <CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content> </Content>
<Content Include="Setup\override.css"> <Content Include="Setup\override.css">
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory> <CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content> </Content>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="BuildBundlerMinifier" Version="2.6.375" /> <PackageReference Include="BuildBundlerMinifier" Version="2.8.391" />
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.2.1" /> <PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.4.1" />
<PackageReference Include="Microsoft.ApplicationInsights.DependencyCollector" Version="2.6.1" /> <PackageReference Include="Microsoft.ApplicationInsights.DependencyCollector" Version="2.7.2" />
<PackageReference Include="Microsoft.ApplicationInsights.Kubernetes" Version="1.0.0-beta8" /> <PackageReference Include="Microsoft.ApplicationInsights.Kubernetes" Version="1.0.0-beta9" />
<PackageReference Include="Microsoft.ApplicationInsights.ServiceFabric" Version="2.1.1-beta1" /> <PackageReference Include="Microsoft.ApplicationInsights.ServiceFabric" Version="2.1.1" />
<PackageReference Include="Microsoft.Extensions.Http.Polly" Version="2.1.0" /> <PackageReference Include="Microsoft.Extensions.Http.Polly" Version="2.1.1" />
<PackageReference Include="Microsoft.Extensions.Logging.AzureAppServices" Version="2.1.0" /> <PackageReference Include="Microsoft.Extensions.Logging.AzureAppServices" Version="2.1.1" />
<PackageReference Include="Microsoft.AspNetCore.App" Version="2.1.0" /> <PackageReference Include="Microsoft.AspNetCore.App" Version="2.1.3" />
<PackageReference Include="Microsoft.AspNetCore.DataProtection.Redis" Version="0.3.3" /> <PackageReference Include="Microsoft.AspNetCore.DataProtection.Redis" Version="0.4.1" />
<PackageReference Include="Microsoft.VisualStudio.Azure.Fabric.MSBuild" Version="1.6.5" /> <PackageReference Include="Microsoft.VisualStudio.Azure.Fabric.MSBuild" Version="1.6.7" />
<PackageReference Include="Microsoft.Web.LibraryManager.Build" Version="1.0.113" /> <PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="2.1.3" />
</ItemGroup> <PackageReference Include="Microsoft.Web.LibraryManager.Build" Version="1.0.163" />
</ItemGroup>
<Target Name="PrepublishScript" BeforeTargets="PrepareForPublish"> <Target Name="PrepublishScript" BeforeTargets="PrepareForPublish">
<Exec Command="dotnet bundle" Condition="'$(ASPNETCORE_ENVIRONMENT)'!='Development'" /> <Exec Command="dotnet bundle" Condition="'$(ASPNETCORE_ENVIRONMENT)'!='Development'" />
</Target> </Target>
<ItemGroup>
<DotNetCliToolReference Include="BundlerMinifier.Core" Version="2.7.385" />
</ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\..\BuildingBlocks\HealthChecks\src\Microsoft.AspNetCore.HealthChecks\Microsoft.AspNetCore.HealthChecks.csproj" /> <ProjectReference Include="..\..\BuildingBlocks\HealthChecks\src\Microsoft.AspNetCore.HealthChecks\Microsoft.AspNetCore.HealthChecks.csproj" />
<ProjectReference Include="..\..\BuildingBlocks\HealthChecks\src\Microsoft.Extensions.HealthChecks\Microsoft.Extensions.HealthChecks.csproj" /> <ProjectReference Include="..\..\BuildingBlocks\HealthChecks\src\Microsoft.Extensions.HealthChecks\Microsoft.Extensions.HealthChecks.csproj" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="ViewModels\CampaignItem.cs" /> <None Include="ViewModels\CampaignItem.cs" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -1,27 +1,36 @@
{ {
"CatalogUrl": "http://localhost:5101", "AllowedHosts": "*",
"OrderingUrl": "http://localhost:5102", "CatalogUrl": "http://localhost:5101",
"BasketUrl": "http://localhost:5103", "OrderingUrl": "http://localhost:5102",
"MarketingUrl": "http://localhost:5110", "BasketUrl": "http://localhost:5103",
"IdentityUrl": "http://localhost:5105", "MarketingUrl": "http://localhost:5110",
"CallBackUrl": "http://localhost:5100/", "IdentityUrl": "https://localhost:4105",
"LocationsUrl": "http://localhost:5109/", "CallBackUrl": "https://localhost:4100/",
"IsClusterEnv": "False", "LocationsUrl": "http://localhost:5109/",
"UseResilientHttp": "True", "IsClusterEnv": "False",
"UseLoadTest": false, "UseResilientHttp": "True",
"ActivateCampaignDetailFunction": "False", "UseLoadTest": false,
"UseCustomizationData": false, "ActivateCampaignDetailFunction": "False",
"Logging": { "UseCustomizationData": false,
"IncludeScopes": false, "Logging": {
"LogLevel": { "IncludeScopes": false,
"Default": "Trace", "LogLevel": {
"System": "Information", "Default": "Trace",
"Microsoft": "Information" "System": "Information",
} "Microsoft": "Information"
}, }
"ApplicationInsights": { },
"InstrumentationKey": "" "ApplicationInsights": {
}, "InstrumentationKey": ""
"HttpClientRetryCount": 8, },
"HttpClientExceptionsAllowedBeforeBreaking": 7 "HttpClientRetryCount": 8,
"HttpClientExceptionsAllowedBeforeBreaking": 7,
"Kestrel": {
"Certificates": {
"Default": {
"Path": "./synergydev.pfx",
"Password": "RH@ssl2018"
}
}
}
} }

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@ -1,9 +1,10 @@
ARG NODE_IMAGE=node:8.11 ARG NODE_IMAGE=node:8.11
FROM microsoft/dotnet:2.1-aspnetcore-runtime AS base FROM microsoft/dotnet:2.1.3-aspnetcore-runtime AS base
WORKDIR /app WORKDIR /app
EXPOSE 80 EXPOSE 80
EXPOSE 443
FROM microsoft/dotnet:2.1-sdk as dotnet-build FROM microsoft/dotnet:2.1.401-sdk as dotnet-build
WORKDIR /src WORKDIR /src
FROM ${NODE_IMAGE} as node-build FROM ${NODE_IMAGE} as node-build
@ -16,6 +17,7 @@ FROM dotnet-build as publish
WORKDIR /src/src/Web/WebSPA/wwwroot WORKDIR /src/src/Web/WebSPA/wwwroot
COPY --from=node-build /web/wwwroot . COPY --from=node-build /web/wwwroot .
WORKDIR /src WORKDIR /src
COPY /Certificates/eShopOnContainers.pfx /root/.aspnet/https/
COPY . . COPY . .
WORKDIR /src/src/Web/WebSPA WORKDIR /src/src/Web/WebSPA
RUN dotnet publish -c Release -o /app RUN dotnet publish -c Release -o /app

View File

@ -1,18 +1,19 @@
{ {
"iisSettings": { "iisSettings": {
"windowsAuthentication": false, "windowsAuthentication": false,
"anonymousAuthentication": true, "anonymousAuthentication": true,
"iisExpress": { "iisExpress": {
"applicationUrl": "http://localhost:58018/", "applicationUrl": "http://localhost:58018/",
"sslPort": 0 "sslPort": 4104
} }
}, },
"profiles": { "profiles": {
"IIS Express": { "IIS Express": {
"commandName": "IISExpress", "commandName": "IISExpress",
"environmentVariables": { "environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Production" "ASPNETCORE_ENVIRONMENT": "Production"
} },
} "use64Bit": true
} }
}
} }

Binary file not shown.

Binary file not shown.

View File

@ -17,142 +17,153 @@ using WebSPA.Infrastructure;
namespace eShopConContainers.WebSPA namespace eShopConContainers.WebSPA
{ {
public class Startup public class Startup
{ {
public Startup(IConfiguration configuration) public Startup(IConfiguration configuration)
{ {
Configuration = configuration; Configuration = configuration;
} }
public IConfiguration Configuration { get; } public IConfiguration Configuration { get; }
private IHostingEnvironment _hostingEnv; private readonly IHostingEnvironment _hostingEnv;
public Startup(IHostingEnvironment env) public Startup(IHostingEnvironment env)
{ {
_hostingEnv = env; _hostingEnv = env;
var localPath = new Uri(Configuration["ASPNETCORE_URLS"])?.LocalPath ?? "/"; string localPath = new Uri(Configuration["ASPNETCORE_URLS"])?.LocalPath ?? "/";
Configuration["BaseUrl"] = localPath; Configuration["BaseUrl"] = localPath;
} }
// This method gets called by the runtime. Use this method to add services to the container. // This method gets called by the runtime. Use this method to add services to the container.
// For more information on how to configure your application, visit http://go.microsoft.com/fwlink/?LinkID=398940 // For more information on how to configure your application, visit http://go.microsoft.com/fwlink/?LinkID=398940
public void ConfigureServices(IServiceCollection services) public void ConfigureServices(IServiceCollection services)
{ {
RegisterAppInsights(services); RegisterAppInsights(services);
services.AddHealthChecks(checks => services.AddHealthChecks(checks =>
{ {
var minutes = 1; int minutes = 1;
if (int.TryParse(Configuration["HealthCheck:Timeout"], out var minutesParsed)) if (int.TryParse(Configuration["HealthCheck:Timeout"], out int minutesParsed))
{ {
minutes = minutesParsed; minutes = minutesParsed;
} }
checks.AddUrlCheck(Configuration["CatalogUrlHC"], TimeSpan.FromMinutes(minutes)); checks.AddUrlCheck(Configuration["CatalogUrlHC"], TimeSpan.FromMinutes(minutes));
checks.AddUrlCheck(Configuration["OrderingUrlHC"], TimeSpan.FromMinutes(minutes)); checks.AddUrlCheck(Configuration["OrderingUrlHC"], TimeSpan.FromMinutes(minutes));
checks.AddUrlCheck(Configuration["BasketUrlHC"], TimeSpan.Zero); //No cache for this HealthCheck, better just for demos checks.AddUrlCheck(Configuration["BasketUrlHC"], TimeSpan.Zero); //No cache for this HealthCheck, better just for demos
checks.AddUrlCheck(Configuration["IdentityUrlHC"], TimeSpan.FromMinutes(minutes)); checks.AddUrlCheck(Configuration["IdentityUrlHC"], TimeSpan.FromMinutes(minutes));
checks.AddUrlCheck(Configuration["MarketingUrlHC"], TimeSpan.FromMinutes(minutes)); checks.AddUrlCheck(Configuration["MarketingUrlHC"], TimeSpan.FromMinutes(minutes));
});
services.Configure<AppSettings>(Configuration); });
if (Configuration.GetValue<string>("IsClusterEnv") == bool.TrueString) services.Configure<AppSettings>(Configuration);
{
services.AddDataProtection(opts =>
{
opts.ApplicationDiscriminator = "eshop.webspa";
})
.PersistKeysToRedis(ConnectionMultiplexer.Connect(Configuration["DPConnectionString"]), "DataProtection-Keys");
}
services.AddAntiforgery(options => options.HeaderName = "X-XSRF-TOKEN"); if (Configuration.GetValue<string>("IsClusterEnv") == bool.TrueString)
{
services.AddDataProtection(opts =>
{
opts.ApplicationDiscriminator = "eshop.webspa";
})
.PersistKeysToRedis(ConnectionMultiplexer.Connect(Configuration["DPConnectionString"]), "DataProtection-Keys");
}
services.AddMvc() services.AddAntiforgery(options => options.HeaderName = "X-XSRF-TOKEN");
.AddJsonOptions(options =>
{ services.AddMvc()
options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver(); .AddJsonOptions(options =>
}); {
} options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
})
.SetCompatibilityVersion(Microsoft.AspNetCore.Mvc.CompatibilityVersion.Version_2_1);
services.AddHttpsRedirection(opts =>
{
opts.HttpsPort = 4104;
});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline. // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, IAntiforgery antiforgery) public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, IAntiforgery antiforgery)
{ {
loggerFactory.AddAzureWebAppDiagnostics(); loggerFactory.AddAzureWebAppDiagnostics();
loggerFactory.AddApplicationInsights(app.ApplicationServices, LogLevel.Trace); loggerFactory.AddApplicationInsights(app.ApplicationServices, LogLevel.Trace);
if (env.IsDevelopment()) if (env.IsDevelopment())
{ {
app.UseDeveloperExceptionPage(); app.UseDeveloperExceptionPage();
} }
else
{
app.UseHsts();
}
// Configure XSRF middleware, This pattern is for SPA style applications where XSRF token is added on Index page app.UseHttpsRedirection();
// load and passed back token on every subsequent async request
// app.Use(async (context, next) =>
// {
// if (string.Equals(context.Request.Path.Value, "/", StringComparison.OrdinalIgnoreCase))
// {
// var tokens = antiforgery.GetAndStoreTokens(context);
// context.Response.Cookies.Append("XSRF-TOKEN", tokens.RequestToken, new CookieOptions() { HttpOnly = false });
// }
// await next.Invoke();
// });
//Seed Data // Configure XSRF middleware, This pattern is for SPA style applications where XSRF token is added on Index page
WebContextSeed.Seed(app, env, loggerFactory); // load and passed back token on every subsequent async request
// app.Use(async (context, next) =>
// {
// if (string.Equals(context.Request.Path.Value, "/", StringComparison.OrdinalIgnoreCase))
// {
// var tokens = antiforgery.GetAndStoreTokens(context);
// context.Response.Cookies.Append("XSRF-TOKEN", tokens.RequestToken, new CookieOptions() { HttpOnly = false });
// }
// await next.Invoke();
// });
var pathBase = Configuration["PATH_BASE"]; //Seed Data
if (!string.IsNullOrEmpty(pathBase)) WebContextSeed.Seed(app, env, loggerFactory);
{
loggerFactory.CreateLogger("init").LogDebug($"Using PATH BASE '{pathBase}'"); string pathBase = Configuration["PATH_BASE"];
app.UsePathBase(pathBase); if (!string.IsNullOrEmpty(pathBase))
} {
loggerFactory.CreateLogger("init").LogDebug($"Using PATH BASE '{pathBase}'");
app.UsePathBase(pathBase);
}
#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously #pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously
app.Map("/liveness", lapp => lapp.Run(async ctx => ctx.Response.StatusCode = 200)); app.Map("/liveness", lapp => lapp.Run(async ctx => ctx.Response.StatusCode = 200));
#pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously #pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously
app.Use(async (context, next) => app.Use(async (context, next) =>
{ {
await next(); await next();
// If there's no available file and the request doesn't contain an extension, we're probably trying to access a page. // If there's no available file and the request doesn't contain an extension, we're probably trying to access a page.
// Rewrite request to use app root // Rewrite request to use app root
if (context.Response.StatusCode == 404 && !Path.HasExtension(context.Request.Path.Value) && !context.Request.Path.Value.StartsWith("/api")) if (context.Response.StatusCode == 404 && !Path.HasExtension(context.Request.Path.Value) && !context.Request.Path.Value.StartsWith("/api"))
{ {
context.Request.Path = "/index.html"; context.Request.Path = "/index.html";
context.Response.StatusCode = 200; // Make sure we update the status code, otherwise it returns 404 context.Response.StatusCode = 200; // Make sure we update the status code, otherwise it returns 404
await next(); await next();
} }
}); });
app.UseDefaultFiles();
app.UseStaticFiles();
app.UseMvcWithDefaultRoute(); app.UseDefaultFiles();
} app.UseStaticFiles();
private void RegisterAppInsights(IServiceCollection services) app.UseMvcWithDefaultRoute();
{ }
services.AddApplicationInsightsTelemetry(Configuration);
var orchestratorType = Configuration.GetValue<string>("OrchestratorType");
if (orchestratorType?.ToUpper() == "K8S") private void RegisterAppInsights(IServiceCollection services)
{ {
// Enable K8s telemetry initializer services.AddApplicationInsightsTelemetry(Configuration);
services.EnableKubernetes(); string orchestratorType = Configuration.GetValue<string>("OrchestratorType");
}
if (orchestratorType?.ToUpper() == "SF") if (orchestratorType?.ToUpper() == "K8S")
{ {
// Enable SF telemetry initializer // Enable K8s telemetry initializer
services.AddSingleton<ITelemetryInitializer>((serviceProvider) => services.EnableKubernetes();
new FabricTelemetryInitializer()); }
} if (orchestratorType?.ToUpper() == "SF")
} {
} // Enable SF telemetry initializer
services.AddSingleton<ITelemetryInitializer>((serviceProvider) =>
new FabricTelemetryInitializer());
}
}
}
} }

View File

@ -1,102 +1,107 @@
<Project Sdk="Microsoft.NET.Sdk.Web"> <Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup> <PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework> <TargetFramework>netcoreapp2.1</TargetFramework>
<UserSecretsId>aspnetcorespa-c23d27a4-eb88-4b18-9b77-2a93f3b15119</UserSecretsId> <RuntimeFrameworkVersion>2.1.3</RuntimeFrameworkVersion>
<DockerComposeProjectPath>..\..\..\docker-compose.dcproj</DockerComposeProjectPath> <UserSecretsId>aspnetcorespa-c23d27a4-eb88-4b18-9b77-2a93f3b15119</UserSecretsId>
<TypeScriptCompileOnSaveEnabled>false</TypeScriptCompileOnSaveEnabled> <DockerComposeProjectPath>..\..\..\docker-compose.dcproj</DockerComposeProjectPath>
<TypeScriptCompileBlocked>true</TypeScriptCompileBlocked> <TypeScriptCompileOnSaveEnabled>false</TypeScriptCompileOnSaveEnabled>
<GeneratedItemPatterns>wwwroot/dist/**</GeneratedItemPatterns> <TypeScriptCompileBlocked>true</TypeScriptCompileBlocked>
<DefaultItemExcludes>$(DefaultItemExcludes);$(GeneratedItemPatterns)</DefaultItemExcludes> <GeneratedItemPatterns>wwwroot/dist/**</GeneratedItemPatterns>
</PropertyGroup> <DefaultItemExcludes>$(DefaultItemExcludes);$(GeneratedItemPatterns)</DefaultItemExcludes>
</PropertyGroup>
<ItemGroup> <ItemGroup>
<Compile Remove="node_modules\**\*;Client\**\*" /> <Compile Remove="node_modules\**\*;Client\**\*" />
<None Remove="Client\environments\environment.prod.ts" /> <None Remove="Client\environments\environment.prod.ts" />
<None Remove="Client\environments\environment.ts" /> <None Remove="Client\environments\environment.ts" />
<None Remove="Client\guid.ts" /> <None Remove="Client\guid.ts" />
<None Remove="Client\main.ts" /> <None Remove="Client\main.ts" />
<None Remove="Client\modules\app.component.ts" /> <None Remove="Client\modules\app.component.ts" />
<None Remove="Client\modules\app.module.ts" /> <None Remove="Client\modules\app.module.ts" />
<None Remove="Client\modules\app.routes.ts" /> <None Remove="Client\modules\app.routes.ts" />
<None Remove="Client\modules\app.service.ts" /> <None Remove="Client\modules\app.service.ts" />
<None Remove="Client\modules\basket\basket-status\basket-status.component.ts" /> <None Remove="Client\modules\basket\basket-status\basket-status.component.ts" />
<None Remove="Client\modules\basket\basket.component.ts" /> <None Remove="Client\modules\basket\basket.component.ts" />
<None Remove="Client\modules\basket\basket.module.ts" /> <None Remove="Client\modules\basket\basket.module.ts" />
<None Remove="Client\modules\basket\basket.service.ts" /> <None Remove="Client\modules\basket\basket.service.ts" />
<None Remove="Client\modules\campaigns\campaigns-detail\campaigns-detail.component.ts" /> <None Remove="Client\modules\campaigns\campaigns-detail\campaigns-detail.component.ts" />
<None Remove="Client\modules\campaigns\campaigns.component.ts" /> <None Remove="Client\modules\campaigns\campaigns.component.ts" />
<None Remove="Client\modules\campaigns\campaigns.module.ts" /> <None Remove="Client\modules\campaigns\campaigns.module.ts" />
<None Remove="Client\modules\campaigns\campaigns.service.ts" /> <None Remove="Client\modules\campaigns\campaigns.service.ts" />
<None Remove="Client\modules\catalog\catalog.component.ts" /> <None Remove="Client\modules\catalog\catalog.component.ts" />
<None Remove="Client\modules\catalog\catalog.module.ts" /> <None Remove="Client\modules\catalog\catalog.module.ts" />
<None Remove="Client\modules\catalog\catalog.service.ts" /> <None Remove="Client\modules\catalog\catalog.service.ts" />
<None Remove="Client\modules\orders\orders-detail\orders-detail.component.ts" /> <None Remove="Client\modules\orders\orders-detail\orders-detail.component.ts" />
<None Remove="Client\modules\orders\orders-new\orders-new.component.ts" /> <None Remove="Client\modules\orders\orders-new\orders-new.component.ts" />
<None Remove="Client\modules\orders\orders.component.ts" /> <None Remove="Client\modules\orders\orders.component.ts" />
<None Remove="Client\modules\orders\orders.module.ts" /> <None Remove="Client\modules\orders\orders.module.ts" />
<None Remove="Client\modules\orders\orders.service.ts" /> <None Remove="Client\modules\orders\orders.service.ts" />
<None Remove="Client\modules\shared\components\header\header.ts" /> <None Remove="Client\modules\shared\components\header\header.ts" />
<None Remove="Client\modules\shared\components\identity\identity.ts" /> <None Remove="Client\modules\shared\components\identity\identity.ts" />
<None Remove="Client\modules\shared\components\page-not-found\page-not-found.component.spec.ts" /> <None Remove="Client\modules\shared\components\page-not-found\page-not-found.component.spec.ts" />
<None Remove="Client\modules\shared\components\page-not-found\page-not-found.component.ts" /> <None Remove="Client\modules\shared\components\page-not-found\page-not-found.component.ts" />
<None Remove="Client\modules\shared\components\pager\pager.ts" /> <None Remove="Client\modules\shared\components\pager\pager.ts" />
<None Remove="Client\modules\shared\models\basket.model.ts" /> <None Remove="Client\modules\shared\models\basket.model.ts" />
<None Remove="Client\modules\shared\models\basketCheckout.model.ts" /> <None Remove="Client\modules\shared\models\basketCheckout.model.ts" />
<None Remove="Client\modules\shared\models\basketItem.model.ts" /> <None Remove="Client\modules\shared\models\basketItem.model.ts" />
<None Remove="Client\modules\shared\models\campaign.model.ts" /> <None Remove="Client\modules\shared\models\campaign.model.ts" />
<None Remove="Client\modules\shared\models\campaignItem.model.ts" /> <None Remove="Client\modules\shared\models\campaignItem.model.ts" />
<None Remove="Client\modules\shared\models\catalog.model.ts" /> <None Remove="Client\modules\shared\models\catalog.model.ts" />
<None Remove="Client\modules\shared\models\catalogBrand.model.ts" /> <None Remove="Client\modules\shared\models\catalogBrand.model.ts" />
<None Remove="Client\modules\shared\models\catalogItem.model.ts" /> <None Remove="Client\modules\shared\models\catalogItem.model.ts" />
<None Remove="Client\modules\shared\models\catalogType.model.ts" /> <None Remove="Client\modules\shared\models\catalogType.model.ts" />
<None Remove="Client\modules\shared\models\configuration.model.ts" /> <None Remove="Client\modules\shared\models\configuration.model.ts" />
<None Remove="Client\modules\shared\models\identity.model.ts" /> <None Remove="Client\modules\shared\models\identity.model.ts" />
<None Remove="Client\modules\shared\models\order-detail.model.ts" /> <None Remove="Client\modules\shared\models\order-detail.model.ts" />
<None Remove="Client\modules\shared\models\order.model.ts" /> <None Remove="Client\modules\shared\models\order.model.ts" />
<None Remove="Client\modules\shared\models\orderItem.model.ts" /> <None Remove="Client\modules\shared\models\orderItem.model.ts" />
<None Remove="Client\modules\shared\models\pager.model.ts" /> <None Remove="Client\modules\shared\models\pager.model.ts" />
<None Remove="Client\modules\shared\pipes\uppercase.pipe.spec.ts" /> <None Remove="Client\modules\shared\pipes\uppercase.pipe.spec.ts" />
<None Remove="Client\modules\shared\pipes\uppercase.pipe.ts" /> <None Remove="Client\modules\shared\pipes\uppercase.pipe.ts" />
<None Remove="Client\modules\shared\services\basket.wrapper.service.ts" /> <None Remove="Client\modules\shared\services\basket.wrapper.service.ts" />
<None Remove="Client\modules\shared\services\configuration.service.ts" /> <None Remove="Client\modules\shared\services\configuration.service.ts" />
<None Remove="Client\modules\shared\services\data.service.ts" /> <None Remove="Client\modules\shared\services\data.service.ts" />
<None Remove="Client\modules\shared\services\notification.service.ts" /> <None Remove="Client\modules\shared\services\notification.service.ts" />
<None Remove="Client\modules\shared\services\security.service.ts" /> <None Remove="Client\modules\shared\services\security.service.ts" />
<None Remove="Client\modules\shared\services\signalr.service.ts" /> <None Remove="Client\modules\shared\services\signalr.service.ts" />
<None Remove="Client\modules\shared\services\storage.service.ts" /> <None Remove="Client\modules\shared\services\storage.service.ts" />
<None Remove="Client\modules\shared\shared.module.ts" /> <None Remove="Client\modules\shared\shared.module.ts" />
<None Remove="Client\polyfills.ts" /> <None Remove="Client\polyfills.ts" />
<None Remove="Client\test.ts" /> <None Remove="Client\test.ts" />
<None Remove="Client\typings.d.ts" /> <None Remove="Client\typings.d.ts" />
<Content Include="Setup\images.zip"> <None Remove="Setup\DotNet Foundation CA.pfx" />
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory> <None Remove="Setup\eShopOnContainers.pfx" />
</Content> <Content Include="Setup\DotNet Foundation CA.pfx" />
<Content Update="appsettings.json;"> <Content Include="Setup\eShopOnContainers.pfx" />
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory> <Content Include="Setup\images.zip">
</Content> <CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
<Content Update="web.config;"> </Content>
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory> <Content Update="appsettings.json;">
</Content> <CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
<Content Update="wwwroot\**\*;"> </Content>
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory> <Content Update="web.config;">
</Content> <CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
</ItemGroup> </Content>
<Content Update="wwwroot\**\*;">
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
</Content>
</ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.2.1" /> <PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.4.1" />
<PackageReference Include="Microsoft.ApplicationInsights.DependencyCollector" Version="2.6.1" /> <PackageReference Include="Microsoft.ApplicationInsights.DependencyCollector" Version="2.7.2" />
<PackageReference Include="Microsoft.ApplicationInsights.Kubernetes" Version="1.0.0-beta8" /> <PackageReference Include="Microsoft.ApplicationInsights.Kubernetes" Version="1.0.0-beta9" />
<PackageReference Include="Microsoft.ApplicationInsights.ServiceFabric" Version="2.1.1-beta1" /> <PackageReference Include="Microsoft.ApplicationInsights.ServiceFabric" Version="2.1.1" />
<PackageReference Include="Microsoft.Extensions.Logging.AzureAppServices" Version="2.1.0" /> <PackageReference Include="Microsoft.Extensions.Logging.AzureAppServices" Version="2.1.1" />
<PackageReference Include="Microsoft.AspNetCore.App" Version="2.1.0" /> <PackageReference Include="Microsoft.AspNetCore.App" Version="2.1.3" />
<PackageReference Include="Microsoft.AspNetCore.DataProtection.Redis" Version="0.3.3" /> <PackageReference Include="Microsoft.AspNetCore.DataProtection.Redis" Version="0.4.1" />
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" /> <PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
</ItemGroup> </ItemGroup>
<!-- workaround for https://github.com/aspnet/websdk/issues/114 --> <!-- workaround for https://github.com/aspnet/websdk/issues/114 -->
<!-- <!--
<Target Name="AddGeneratedContentItems" BeforeTargets="AssignTargetPaths" DependsOnTargets="PrepareForPublish"> <Target Name="AddGeneratedContentItems" BeforeTargets="AssignTargetPaths" DependsOnTargets="PrepareForPublish">
<ItemGroup> <ItemGroup>
<Content Include="wwwroot/**" CopyToPublishDirectory="PreserveNewest" Exclude="$(DefaultItemExcludes);$(DefaultExcludesInProjectFolder);@(Content)" /> <Content Include="wwwroot/**" CopyToPublishDirectory="PreserveNewest" Exclude="$(DefaultItemExcludes);$(DefaultExcludesInProjectFolder);@(Content)" />
@ -104,79 +109,82 @@
</Target> </Target>
--> -->
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\..\BuildingBlocks\HealthChecks\src\Microsoft.AspNetCore.HealthChecks\Microsoft.AspNetCore.HealthChecks.csproj" /> <ProjectReference Include="..\..\BuildingBlocks\HealthChecks\src\Microsoft.AspNetCore.HealthChecks\Microsoft.AspNetCore.HealthChecks.csproj" />
<ProjectReference Include="..\..\BuildingBlocks\HealthChecks\src\Microsoft.Extensions.HealthChecks\Microsoft.Extensions.HealthChecks.csproj" /> <ProjectReference Include="..\..\BuildingBlocks\HealthChecks\src\Microsoft.Extensions.HealthChecks\Microsoft.Extensions.HealthChecks.csproj" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Folder Include="wwwroot\assets\" /> <Folder Include="wwwroot\assets\" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<TypeScriptCompile Include="Client\environments\environment.prod.ts" /> <TypeScriptCompile Include="Client\environments\environment.prod.ts" />
<TypeScriptCompile Include="Client\environments\environment.ts" /> <TypeScriptCompile Include="Client\environments\environment.ts" />
<TypeScriptCompile Include="Client\guid.ts" /> <TypeScriptCompile Include="Client\guid.ts" />
<TypeScriptCompile Include="Client\main.ts" /> <TypeScriptCompile Include="Client\main.ts" />
<TypeScriptCompile Include="Client\modules\app.component.ts" /> <TypeScriptCompile Include="Client\modules\app.component.ts" />
<TypeScriptCompile Include="Client\modules\app.module.ts" /> <TypeScriptCompile Include="Client\modules\app.module.ts" />
<TypeScriptCompile Include="Client\modules\app.routes.ts" /> <TypeScriptCompile Include="Client\modules\app.routes.ts" />
<TypeScriptCompile Include="Client\modules\app.service.ts" /> <TypeScriptCompile Include="Client\modules\app.service.ts" />
<TypeScriptCompile Include="Client\modules\basket\basket-status\basket-status.component.ts" /> <TypeScriptCompile Include="Client\modules\basket\basket-status\basket-status.component.ts" />
<TypeScriptCompile Include="Client\modules\basket\basket.component.ts" /> <TypeScriptCompile Include="Client\modules\basket\basket.component.ts" />
<TypeScriptCompile Include="Client\modules\basket\basket.module.ts" /> <TypeScriptCompile Include="Client\modules\basket\basket.module.ts" />
<TypeScriptCompile Include="Client\modules\basket\basket.service.ts" /> <TypeScriptCompile Include="Client\modules\basket\basket.service.ts" />
<TypeScriptCompile Include="Client\modules\campaigns\campaigns-detail\campaigns-detail.component.ts" /> <TypeScriptCompile Include="Client\modules\campaigns\campaigns-detail\campaigns-detail.component.ts" />
<TypeScriptCompile Include="Client\modules\campaigns\campaigns.component.ts" /> <TypeScriptCompile Include="Client\modules\campaigns\campaigns.component.ts" />
<TypeScriptCompile Include="Client\modules\campaigns\campaigns.module.ts" /> <TypeScriptCompile Include="Client\modules\campaigns\campaigns.module.ts" />
<TypeScriptCompile Include="Client\modules\campaigns\campaigns.service.ts" /> <TypeScriptCompile Include="Client\modules\campaigns\campaigns.service.ts" />
<TypeScriptCompile Include="Client\modules\catalog\catalog.component.ts" /> <TypeScriptCompile Include="Client\modules\catalog\catalog.component.ts" />
<TypeScriptCompile Include="Client\modules\catalog\catalog.module.ts" /> <TypeScriptCompile Include="Client\modules\catalog\catalog.module.ts" />
<TypeScriptCompile Include="Client\modules\catalog\catalog.service.ts" /> <TypeScriptCompile Include="Client\modules\catalog\catalog.service.ts" />
<TypeScriptCompile Include="Client\modules\orders\orders-detail\orders-detail.component.ts" /> <TypeScriptCompile Include="Client\modules\orders\orders-detail\orders-detail.component.ts" />
<TypeScriptCompile Include="Client\modules\orders\orders-new\orders-new.component.ts" /> <TypeScriptCompile Include="Client\modules\orders\orders-new\orders-new.component.ts" />
<TypeScriptCompile Include="Client\modules\orders\orders.component.ts" /> <TypeScriptCompile Include="Client\modules\orders\orders.component.ts" />
<TypeScriptCompile Include="Client\modules\orders\orders.module.ts" /> <TypeScriptCompile Include="Client\modules\orders\orders.module.ts" />
<TypeScriptCompile Include="Client\modules\orders\orders.service.ts" /> <TypeScriptCompile Include="Client\modules\orders\orders.service.ts" />
<TypeScriptCompile Include="Client\modules\shared\components\header\header.ts" /> <TypeScriptCompile Include="Client\modules\shared\components\header\header.ts" />
<TypeScriptCompile Include="Client\modules\shared\components\identity\identity.ts" /> <TypeScriptCompile Include="Client\modules\shared\components\identity\identity.ts" />
<TypeScriptCompile Include="Client\modules\shared\components\page-not-found\page-not-found.component.spec.ts" /> <TypeScriptCompile Include="Client\modules\shared\components\page-not-found\page-not-found.component.spec.ts" />
<TypeScriptCompile Include="Client\modules\shared\components\page-not-found\page-not-found.component.ts" /> <TypeScriptCompile Include="Client\modules\shared\components\page-not-found\page-not-found.component.ts" />
<TypeScriptCompile Include="Client\modules\shared\components\pager\pager.ts" /> <TypeScriptCompile Include="Client\modules\shared\components\pager\pager.ts" />
<TypeScriptCompile Include="Client\modules\shared\models\basket.model.ts" /> <TypeScriptCompile Include="Client\modules\shared\models\basket.model.ts" />
<TypeScriptCompile Include="Client\modules\shared\models\basketCheckout.model.ts" /> <TypeScriptCompile Include="Client\modules\shared\models\basketCheckout.model.ts" />
<TypeScriptCompile Include="Client\modules\shared\models\basketItem.model.ts" /> <TypeScriptCompile Include="Client\modules\shared\models\basketItem.model.ts" />
<TypeScriptCompile Include="Client\modules\shared\models\campaign.model.ts" /> <TypeScriptCompile Include="Client\modules\shared\models\campaign.model.ts" />
<TypeScriptCompile Include="Client\modules\shared\models\campaignItem.model.ts" /> <TypeScriptCompile Include="Client\modules\shared\models\campaignItem.model.ts" />
<TypeScriptCompile Include="Client\modules\shared\models\catalog.model.ts" /> <TypeScriptCompile Include="Client\modules\shared\models\catalog.model.ts" />
<TypeScriptCompile Include="Client\modules\shared\models\catalogBrand.model.ts" /> <TypeScriptCompile Include="Client\modules\shared\models\catalogBrand.model.ts" />
<TypeScriptCompile Include="Client\modules\shared\models\catalogItem.model.ts" /> <TypeScriptCompile Include="Client\modules\shared\models\catalogItem.model.ts" />
<TypeScriptCompile Include="Client\modules\shared\models\catalogType.model.ts" /> <TypeScriptCompile Include="Client\modules\shared\models\catalogType.model.ts" />
<TypeScriptCompile Include="Client\modules\shared\models\configuration.model.ts" /> <TypeScriptCompile Include="Client\modules\shared\models\configuration.model.ts" />
<TypeScriptCompile Include="Client\modules\shared\models\identity.model.ts" /> <TypeScriptCompile Include="Client\modules\shared\models\identity.model.ts" />
<TypeScriptCompile Include="Client\modules\shared\models\order-detail.model.ts" /> <TypeScriptCompile Include="Client\modules\shared\models\order-detail.model.ts" />
<TypeScriptCompile Include="Client\modules\shared\models\order.model.ts" /> <TypeScriptCompile Include="Client\modules\shared\models\order.model.ts" />
<TypeScriptCompile Include="Client\modules\shared\models\orderItem.model.ts" /> <TypeScriptCompile Include="Client\modules\shared\models\orderItem.model.ts" />
<TypeScriptCompile Include="Client\modules\shared\models\pager.model.ts" /> <TypeScriptCompile Include="Client\modules\shared\models\pager.model.ts" />
<TypeScriptCompile Include="Client\modules\shared\pipes\uppercase.pipe.spec.ts" /> <TypeScriptCompile Include="Client\modules\shared\pipes\uppercase.pipe.spec.ts" />
<TypeScriptCompile Include="Client\modules\shared\pipes\uppercase.pipe.ts" /> <TypeScriptCompile Include="Client\modules\shared\pipes\uppercase.pipe.ts" />
<TypeScriptCompile Include="Client\modules\shared\services\basket.wrapper.service.ts" /> <TypeScriptCompile Include="Client\modules\shared\services\basket.wrapper.service.ts" />
<TypeScriptCompile Include="Client\modules\shared\services\configuration.service.ts" /> <TypeScriptCompile Include="Client\modules\shared\services\configuration.service.ts" />
<TypeScriptCompile Include="Client\modules\shared\services\data.service.ts" /> <TypeScriptCompile Include="Client\modules\shared\services\data.service.ts" />
<TypeScriptCompile Include="Client\modules\shared\services\notification.service.ts" /> <TypeScriptCompile Include="Client\modules\shared\services\notification.service.ts" />
<TypeScriptCompile Include="Client\modules\shared\services\security.service.ts" /> <TypeScriptCompile Include="Client\modules\shared\services\security.service.ts" />
<TypeScriptCompile Include="Client\modules\shared\services\signalr.service.ts" /> <TypeScriptCompile Include="Client\modules\shared\services\signalr.service.ts" />
<TypeScriptCompile Include="Client\modules\shared\services\storage.service.ts" /> <TypeScriptCompile Include="Client\modules\shared\services\storage.service.ts" />
<TypeScriptCompile Include="Client\modules\shared\shared.module.ts" /> <TypeScriptCompile Include="Client\modules\shared\shared.module.ts" />
<TypeScriptCompile Include="Client\polyfills.ts" /> <TypeScriptCompile Include="Client\polyfills.ts" />
<TypeScriptCompile Include="Client\test.ts" /> <TypeScriptCompile Include="Client\test.ts" />
<TypeScriptCompile Include="Client\typings.d.ts" /> <TypeScriptCompile Include="Client\typings.d.ts" />
</ItemGroup> </ItemGroup>
<ProjectExtensions> <ItemGroup>
<VisualStudio> <Content Update="Setup\DotNet Foundation CA.pfx">
<UserProperties package-lock_1json__JSONSchema="http://json.schemastore.org/bower" /> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</VisualStudio> </Content>
</ProjectExtensions> <Content Update="Setup\eShopOnContainers.pfx">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
</Project> </Project>

View File

@ -1,20 +1,28 @@
{ {
"IdentityUrl": "http://localhost:5105", "IdentityUrl": "https://localhost:4105",
"MarketingUrl": "http://localhost:5110", "MarketingUrl": "http://localhost:5110",
"CallBackUrl": "http://localhost:5104/", "CallBackUrl": "https://localhost:4104/",
"PurchaseUrl": "http://localhost:5200", "PurchaseUrl": "http://localhost:5200",
"UseCustomizationData": true, "UseCustomizationData": true,
"IsClusterEnv": "False", "IsClusterEnv": "False",
"ActivateCampaignDetailFunction": true, "ActivateCampaignDetailFunction": true,
"Logging": { "Logging": {
"IncludeScopes": false, "IncludeScopes": false,
"LogLevel": { "LogLevel": {
"Default": "Debug", "Default": "Debug",
"System": "Information", "System": "Information",
"Microsoft": "Information" "Microsoft": "Information"
} }
}, },
"ApplicationInsights": { "ApplicationInsights": {
"InstrumentationKey": "" "InstrumentationKey": ""
} },
"Kestrel": {
"Certificates": {
"Default": {
"Path": "./Setup/eShopOnContainers.pfx",
"Password": "D0tNet@"
}
}
}
} }

View File

@ -1,12 +1,13 @@
FROM microsoft/dotnet:2.1-aspnetcore-runtime AS base FROM microsoft/dotnet:2.1.3-aspnetcore-runtime AS base
WORKDIR /app WORKDIR /app
EXPOSE 80 EXPOSE 80
FROM microsoft/dotnet:2.1-sdk AS build FROM microsoft/dotnet:2.1.401-sdk AS build
WORKDIR /src WORKDIR /src
COPY . . COPY . .
WORKDIR /src/src/Web/WebStatus WORKDIR /src/src/Web/WebStatus
RUN dotnet restore -nowarn:msb3202,nu1503 RUN dotnet restore -nowarn:msb3202,nu1503
COPY src/Web/WebMVC/synergydev.pfx /root/.aspnet/https/
RUN dotnet build --no-restore -c Release -o /app RUN dotnet build --no-restore -c Release -o /app
FROM build AS publish FROM build AS publish

View File

@ -13,7 +13,8 @@
"launchBrowser": true, "launchBrowser": true,
"environmentVariables": { "environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development" "ASPNETCORE_ENVIRONMENT": "Development"
} },
"use64Bit": true
}, },
"WebStatus": { "WebStatus": {
"commandName": "Project", "commandName": "Project",

View File

@ -1,110 +1,111 @@
using System; using Microsoft.ApplicationInsights.Extensibility;
using System.Collections.Generic; using Microsoft.ApplicationInsights.ServiceFabric;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using WebStatus.Extensions; using WebStatus.Extensions;
using Microsoft.ApplicationInsights.Extensibility;
using Microsoft.ApplicationInsights.ServiceFabric; using TimeSpan = System.TimeSpan;
namespace WebStatus namespace WebStatus
{ {
public class Startup public class Startup
{ {
public Startup(IConfiguration configuration) public Startup(IConfiguration configuration)
{ {
Configuration = configuration; Configuration = configuration;
} }
public IConfiguration Configuration { get; } public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container. // This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services) public void ConfigureServices(IServiceCollection services)
{ {
RegisterAppInsights(services); RegisterAppInsights(services);
services.AddOptions(); services.AddOptions();
// Add framework services. // Add framework services.
services.AddHealthChecks(checks => services.AddHealthChecks(checks =>
{ {
var minutes = 1; var minutes = 1;
if (int.TryParse(Configuration["HealthCheck:Timeout"], out var minutesParsed)) if (int.TryParse(Configuration["HealthCheck:Timeout"], out int minutesParsed))
{ {
minutes = minutesParsed; minutes = minutesParsed;
} }
checks.AddUrlCheckIfNotNull(Configuration["OrderingUrl"], TimeSpan.FromMinutes(minutes)); checks.AddUrlCheckIfNotNull(Configuration["OrderingUrl"], TimeSpan.FromMinutes(minutes));
checks.AddUrlCheckIfNotNull(Configuration["OrderingBackgroundTasksUrl"], TimeSpan.FromMinutes(minutes)); checks.AddUrlCheckIfNotNull(Configuration["OrderingBackgroundTasksUrl"], TimeSpan.FromMinutes(minutes));
checks.AddUrlCheckIfNotNull(Configuration["BasketUrl"], TimeSpan.Zero); //No cache for this HealthCheck, better just for demos checks.AddUrlCheckIfNotNull(Configuration["BasketUrl"], TimeSpan.Zero); //No cache for this HealthCheck, better just for demos
checks.AddUrlCheckIfNotNull(Configuration["CatalogUrl"], TimeSpan.FromMinutes(minutes)); checks.AddUrlCheckIfNotNull(Configuration["CatalogUrl"], TimeSpan.FromMinutes(minutes));
checks.AddUrlCheckIfNotNull(Configuration["IdentityUrl"], TimeSpan.FromMinutes(minutes)); checks.AddUrlCheckIfNotNull(Configuration["IdentityUrl"], TimeSpan.FromMinutes(minutes));
checks.AddUrlCheckIfNotNull(Configuration["LocationsUrl"], TimeSpan.FromMinutes(minutes)); checks.AddUrlCheckIfNotNull(Configuration["LocationsUrl"], TimeSpan.FromMinutes(minutes));
checks.AddUrlCheckIfNotNull(Configuration["MarketingUrl"], TimeSpan.FromMinutes(minutes)); checks.AddUrlCheckIfNotNull(Configuration["MarketingUrl"], TimeSpan.FromMinutes(minutes));
checks.AddUrlCheckIfNotNull(Configuration["PaymentUrl"], TimeSpan.FromMinutes(minutes)); checks.AddUrlCheckIfNotNull(Configuration["PaymentUrl"], TimeSpan.FromMinutes(minutes));
checks.AddUrlCheckIfNotNull(Configuration["mvc"], TimeSpan.Zero); //No cache for this HealthCheck, better just for demos checks.AddUrlCheckIfNotNull(Configuration["mvc"], TimeSpan.Zero); //No cache for this HealthCheck, better just for demos
checks.AddUrlCheckIfNotNull(Configuration["spa"], TimeSpan.Zero); //No cache for this HealthCheck, better just for demos checks.AddUrlCheckIfNotNull(Configuration["spa"], TimeSpan.Zero); //No cache for this HealthCheck, better just for demos
}); });
services.AddMvc(); services
} .AddMvc()
.SetCompatibilityVersion(Microsoft.AspNetCore.Mvc.CompatibilityVersion.Version_2_1)
;
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline. // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{ {
loggerFactory.AddAzureWebAppDiagnostics(); loggerFactory.AddAzureWebAppDiagnostics();
loggerFactory.AddApplicationInsights(app.ApplicationServices, LogLevel.Trace); loggerFactory.AddApplicationInsights(app.ApplicationServices, LogLevel.Trace);
if (env.IsDevelopment()) if (env.IsDevelopment())
{ {
app.UseDeveloperExceptionPage(); app.UseDeveloperExceptionPage();
} }
else else
{ {
app.UseExceptionHandler("/Home/Error"); app.UseExceptionHandler("/Home/Error");
} }
var pathBase = Configuration["PATH_BASE"]; var pathBase = Configuration["PATH_BASE"];
if (!string.IsNullOrEmpty(pathBase)) if (!string.IsNullOrEmpty(pathBase))
{ {
app.UsePathBase(pathBase); app.UsePathBase(pathBase);
} }
#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously #pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously
app.Map("/liveness", lapp => lapp.Run(async ctx => ctx.Response.StatusCode = 200)); app.Map("/liveness", lapp => lapp.Run(async ctx => ctx.Response.StatusCode = 200));
#pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously #pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously
app.UseStaticFiles(); app.UseStaticFiles();
app.UseMvc(routes => app.UseMvc(routes =>
{ {
routes.MapRoute( routes.MapRoute(
name: "default", name: "default",
template: "{controller=Home}/{action=Index}/{id?}"); template: "{controller=Home}/{action=Index}/{id?}");
}); });
} }
private void RegisterAppInsights(IServiceCollection services) private void RegisterAppInsights(IServiceCollection services)
{ {
services.AddApplicationInsightsTelemetry(Configuration); services.AddApplicationInsightsTelemetry(Configuration);
var orchestratorType = Configuration.GetValue<string>("OrchestratorType"); var orchestratorType = Configuration.GetValue<string>("OrchestratorType");
if (orchestratorType?.ToUpper() == "K8S") if (orchestratorType?.ToUpper() == "K8S")
{ {
// Enable K8s telemetry initializer // Enable K8s telemetry initializer
services.EnableKubernetes(); services.EnableKubernetes();
} }
if (orchestratorType?.ToUpper() == "SF") if (orchestratorType?.ToUpper() == "SF")
{ {
// Enable SF telemetry initializer // Enable SF telemetry initializer
services.AddSingleton<ITelemetryInitializer>((serviceProvider) => services.AddSingleton<ITelemetryInitializer>((serviceProvider) =>
new FabricTelemetryInitializer()); new FabricTelemetryInitializer());
} }
} }
} }
} }

View File

@ -1,22 +1,23 @@
<Project Sdk="Microsoft.NET.Sdk.Web"> <Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup> <PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework> <TargetFramework>netcoreapp2.1</TargetFramework>
<AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback> <RuntimeFrameworkVersion>2.1.3</RuntimeFrameworkVersion>
<DockerComposeProjectPath>..\..\..\docker-compose.dcproj</DockerComposeProjectPath> <AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback>
</PropertyGroup> <DockerComposeProjectPath>..\..\..\docker-compose.dcproj</DockerComposeProjectPath>
<ItemGroup> </PropertyGroup>
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.2.1" /> <ItemGroup>
<PackageReference Include="Microsoft.ApplicationInsights.DependencyCollector" Version="2.6.1" /> <PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.4.1" />
<PackageReference Include="Microsoft.ApplicationInsights.Kubernetes" Version="1.0.0-beta8" /> <PackageReference Include="Microsoft.ApplicationInsights.DependencyCollector" Version="2.7.2" />
<PackageReference Include="Microsoft.ApplicationInsights.ServiceFabric" Version="2.1.1-beta1" /> <PackageReference Include="Microsoft.ApplicationInsights.Kubernetes" Version="1.0.0-beta8" />
<PackageReference Include="Microsoft.Extensions.Logging.AzureAppServices" Version="2.1.0" /> <PackageReference Include="Microsoft.ApplicationInsights.ServiceFabric" Version="2.1.1" />
<PackageReference Include="Microsoft.AspNetCore.App" Version="2.1.0" /> <PackageReference Include="Microsoft.Extensions.Logging.AzureAppServices" Version="2.1.1" />
<PackageReference Include="Microsoft.Web.LibraryManager.Build" Version="1.0.113" /> <PackageReference Include="Microsoft.AspNetCore.App" Version="2.1.3" />
</ItemGroup> <PackageReference Include="Microsoft.Web.LibraryManager.Build" Version="1.0.113" />
</ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\..\BuildingBlocks\HealthChecks\src\Microsoft.AspNetCore.HealthChecks\Microsoft.AspNetCore.HealthChecks.csproj" /> <ProjectReference Include="..\..\BuildingBlocks\HealthChecks\src\Microsoft.AspNetCore.HealthChecks\Microsoft.AspNetCore.HealthChecks.csproj" />
<ProjectReference Include="..\..\BuildingBlocks\HealthChecks\src\Microsoft.Extensions.HealthChecks\Microsoft.Extensions.HealthChecks.csproj" /> <ProjectReference Include="..\..\BuildingBlocks\HealthChecks\src\Microsoft.Extensions.HealthChecks\Microsoft.Extensions.HealthChecks.csproj" />
</ItemGroup> </ItemGroup>
</Project> </Project>