diff --git a/docker-compose.override.yml b/docker-compose.override.yml
index d523b328a..98ad11c62 100644
--- a/docker-compose.override.yml
+++ b/docker-compose.override.yml
@@ -80,7 +80,6 @@ services:
- UseCustomizationData=True
- AzureServiceBusEnabled=False
- CheckUpdateTime=30000
- - GracePeriodTime=1
- ApplicationInsights__InstrumentationKey=${INSTRUMENTATION_KEY}
- OrchestratorType=${ORCHESTRATOR_TYPE}
- UseLoadTest=${USE_LOADTEST:-False}
diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml
index 06dcbde6f..4bf465565 100644
--- a/docker-compose.prod.yml
+++ b/docker-compose.prod.yml
@@ -85,7 +85,6 @@ services:
- UseCustomizationData=True
- AzureServiceBusEnabled=False
- CheckUpdateTime=30000
- - GracePeriodTime=1
- ApplicationInsights__InstrumentationKey=${INSTRUMENTATION_KEY}
- OrchestratorType=${ORCHESTRATOR_TYPE}
- UseLoadTest=${USE_LOADTEST:-False}
diff --git a/docker-compose.yml b/docker-compose.yml
index 414d9a1ef..67879bcd7 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -1,6 +1,25 @@
version: '3.4'
services:
+ sql.data:
+ image: microsoft/mssql-server-linux:2017-latest
+
+ nosql.data:
+ image: mongo
+
+ basket.data:
+ image: redis:alpine
+
+ rabbitmq:
+ image: rabbitmq:3-management-alpine
+
+ identity.api:
+ image: eshop/identity.api:${TAG:-latest}
+ build:
+ context: .
+ dockerfile: src/Services/Identity/Identity.API/Dockerfile
+ depends_on:
+ - sql.data
basket.api:
image: eshop/basket.api:${TAG:-latest}
@@ -21,14 +40,6 @@ services:
- sql.data
- rabbitmq
- identity.api:
- image: eshop/identity.api:${TAG:-latest}
- build:
- context: .
- dockerfile: src/Services/Identity/Identity.API/Dockerfile
- depends_on:
- - sql.data
-
ordering.api:
image: eshop/ordering.api:${TAG:-latest}
build:
@@ -58,36 +69,6 @@ services:
- identity.api
- rabbitmq
- webspa:
- image: eshop/webspa:${TAG:-latest}
- build:
- context: .
- dockerfile: src/Web/WebSPA/Dockerfile
- depends_on:
- - catalog.api
- - ordering.api
- - identity.api
- - basket.api
- - marketing.api
-
- webmvc:
- image: eshop/webmvc:${TAG:-latest}
- build:
- context: .
- dockerfile: src/Web/WebMVC/Dockerfile
- depends_on:
- - catalog.api
- - ordering.api
- - identity.api
- - basket.api
- - marketing.api
-
- webstatus:
- image: eshop/webstatus:${TAG:-latest}
- build:
- context: .
- dockerfile: src/Web/WebStatus/Dockerfile
-
payment.api:
image: eshop/payment.api:${TAG:-latest}
build:
@@ -105,57 +86,135 @@ services:
- nosql.data
- rabbitmq
- sql.data:
- image: microsoft/mssql-server-linux:2017-latest
-
- nosql.data:
- image: mongo
-
- basket.data:
- image: redis:alpine
-
- rabbitmq:
- image: rabbitmq:3-management-alpine
-
mobileshoppingapigw:
image: eshop/ocelotapigw:${TAG:-latest}
build:
context: .
dockerfile: src/ApiGateways/ApiGw-Base/Dockerfile
+ depends_on:
+ - nosql.data
+ - sql.data
+ - identity.api
+ - rabbitmq
+ - ordering.api
+ - marketing.api
+ - catalog.api
+ - basket.api
mobilemarketingapigw:
image: eshop/ocelotapigw:${TAG:-latest}
build:
context: .
dockerfile: src/ApiGateways/ApiGw-Base/Dockerfile
+ depends_on:
+ - nosql.data
+ - sql.data
+ - identity.api
+ - rabbitmq
+ - ordering.api
+ - marketing.api
+ - catalog.api
+ - basket.api
webshoppingapigw:
image: eshop/ocelotapigw:${TAG:-latest}
build:
context: .
dockerfile: src/ApiGateways/ApiGw-Base/Dockerfile
+ depends_on:
+ - nosql.data
+ - sql.data
+ - identity.api
+ - rabbitmq
+ - ordering.api
+ - marketing.api
+ - catalog.api
+ - basket.api
webmarketingapigw:
image: eshop/ocelotapigw:${TAG:-latest}
build:
context: .
dockerfile: src/ApiGateways/ApiGw-Base/Dockerfile
+ depends_on:
+ - nosql.data
+ - sql.data
+ - identity.api
+ - rabbitmq
+ - ordering.api
+ - marketing.api
+ - catalog.api
+ - basket.api
mobileshoppingagg:
image: eshop/mobileshoppingagg:${TAG:-latest}
build:
context: .
dockerfile: src/ApiGateways/Mobile.Bff.Shopping/aggregator/Dockerfile
+ depends_on:
+ - nosql.data
+ - sql.data
+ - identity.api
+ - rabbitmq
+ - ordering.api
+ - marketing.api
+ - catalog.api
+ - basket.api
webshoppingagg:
image: eshop/webshoppingagg:${TAG:-latest}
build:
context: .
dockerfile: src/ApiGateways/Web.Bff.Shopping/aggregator/Dockerfile
+ depends_on:
+ - nosql.data
+ - sql.data
+ - identity.api
+ - rabbitmq
+ - ordering.api
+ - marketing.api
+ - catalog.api
+ - basket.api
ordering.signalrhub:
image: eshop/ordering.signalrhub:${TAG:-latest}
build:
context: .
dockerfile: src/Services/Ordering/Ordering.SignalrHub/Dockerfile
+ depends_on:
+ - nosql.data
+ - sql.data
+ - identity.api
+ - rabbitmq
+ - ordering.api
+ - marketing.api
+ - catalog.api
+ - basket.api
+
+ webstatus:
+ image: eshop/webstatus:${TAG:-latest}
+ build:
+ context: .
+ dockerfile: src/Web/WebStatus/Dockerfile
+
+ webspa:
+ image: eshop/webspa:${TAG:-latest}
+ build:
+ context: .
+ dockerfile: src/Web/WebSPA/Dockerfile
+ depends_on:
+ - webshoppingagg
+ - webshoppingapigw
+ - webmarketingapigw
+
+
+ webmvc:
+ image: eshop/webmvc:${TAG:-latest}
+ build:
+ context: .
+ dockerfile: src/Web/WebMVC/Dockerfile
+ depends_on:
+ - webshoppingagg
+ - webshoppingapigw
+ - webmarketingapigw
diff --git a/eShopOnContainers-ServicesAndWebApps.sln b/eShopOnContainers-ServicesAndWebApps.sln
index f127af6d9..f9e3e654e 100644
--- a/eShopOnContainers-ServicesAndWebApps.sln
+++ b/eShopOnContainers-ServicesAndWebApps.sln
@@ -68,10 +68,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Health
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WebStatus", "src\Web\WebStatus\WebStatus.csproj", "{C0A7918D-B4F2-4E7F-8DE2-1E5279EF079F}"
EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Resilience", "Resilience", "{FBF43D93-F2E7-4FF8-B4AB-186895949B88}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Resilience.Http", "src\BuildingBlocks\Resilience\Resilience.Http\Resilience.Http.csproj", "{D1C47FF1-91F1-4CAF-9ABB-AD642B821502}"
-EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Payment", "Payment", "{022E145D-1593-47EE-9608-8E323D3C63F5}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Payment.API", "src\Services\Payment\Payment.API\Payment.API.csproj", "{1A01AF82-6FCB-464C-B39C-F127AEBD315D}"
@@ -130,7 +126,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Web.Shopping.HttpAggregator
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ordering.BackgroundTasks", "src\Services\Ordering\Ordering.BackgroundTasks\Ordering.BackgroundTasks.csproj", "{7D63ED4A-3EDA-4BBA-8BBA-F46BD6430931}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ordering.SignalrHub", "src\Services\Ordering\Ordering.SignalrHub\Ordering.SignalrHub.csproj", "{E1D2B260-4E7F-4A88-BC13-9910F7C44623}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ordering.SignalrHub", "src\Services\Ordering\Ordering.SignalrHub\Ordering.SignalrHub.csproj", "{E1D2B260-4E7F-4A88-BC13-9910F7C44623}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -866,54 +862,6 @@ Global
{C0A7918D-B4F2-4E7F-8DE2-1E5279EF079F}.Release|x64.Build.0 = Release|Any CPU
{C0A7918D-B4F2-4E7F-8DE2-1E5279EF079F}.Release|x86.ActiveCfg = Release|Any CPU
{C0A7918D-B4F2-4E7F-8DE2-1E5279EF079F}.Release|x86.Build.0 = Release|Any CPU
- {D1C47FF1-91F1-4CAF-9ABB-AD642B821502}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
- {D1C47FF1-91F1-4CAF-9ABB-AD642B821502}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
- {D1C47FF1-91F1-4CAF-9ABB-AD642B821502}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU
- {D1C47FF1-91F1-4CAF-9ABB-AD642B821502}.Ad-Hoc|ARM.Build.0 = Debug|Any CPU
- {D1C47FF1-91F1-4CAF-9ABB-AD642B821502}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
- {D1C47FF1-91F1-4CAF-9ABB-AD642B821502}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
- {D1C47FF1-91F1-4CAF-9ABB-AD642B821502}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
- {D1C47FF1-91F1-4CAF-9ABB-AD642B821502}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
- {D1C47FF1-91F1-4CAF-9ABB-AD642B821502}.Ad-Hoc|x64.ActiveCfg = Debug|Any CPU
- {D1C47FF1-91F1-4CAF-9ABB-AD642B821502}.Ad-Hoc|x64.Build.0 = Debug|Any CPU
- {D1C47FF1-91F1-4CAF-9ABB-AD642B821502}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU
- {D1C47FF1-91F1-4CAF-9ABB-AD642B821502}.Ad-Hoc|x86.Build.0 = Debug|Any CPU
- {D1C47FF1-91F1-4CAF-9ABB-AD642B821502}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
- {D1C47FF1-91F1-4CAF-9ABB-AD642B821502}.AppStore|Any CPU.Build.0 = Debug|Any CPU
- {D1C47FF1-91F1-4CAF-9ABB-AD642B821502}.AppStore|ARM.ActiveCfg = Debug|Any CPU
- {D1C47FF1-91F1-4CAF-9ABB-AD642B821502}.AppStore|ARM.Build.0 = Debug|Any CPU
- {D1C47FF1-91F1-4CAF-9ABB-AD642B821502}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
- {D1C47FF1-91F1-4CAF-9ABB-AD642B821502}.AppStore|iPhone.Build.0 = Debug|Any CPU
- {D1C47FF1-91F1-4CAF-9ABB-AD642B821502}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
- {D1C47FF1-91F1-4CAF-9ABB-AD642B821502}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
- {D1C47FF1-91F1-4CAF-9ABB-AD642B821502}.AppStore|x64.ActiveCfg = Debug|Any CPU
- {D1C47FF1-91F1-4CAF-9ABB-AD642B821502}.AppStore|x64.Build.0 = Debug|Any CPU
- {D1C47FF1-91F1-4CAF-9ABB-AD642B821502}.AppStore|x86.ActiveCfg = Debug|Any CPU
- {D1C47FF1-91F1-4CAF-9ABB-AD642B821502}.AppStore|x86.Build.0 = Debug|Any CPU
- {D1C47FF1-91F1-4CAF-9ABB-AD642B821502}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {D1C47FF1-91F1-4CAF-9ABB-AD642B821502}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {D1C47FF1-91F1-4CAF-9ABB-AD642B821502}.Debug|ARM.ActiveCfg = Debug|Any CPU
- {D1C47FF1-91F1-4CAF-9ABB-AD642B821502}.Debug|ARM.Build.0 = Debug|Any CPU
- {D1C47FF1-91F1-4CAF-9ABB-AD642B821502}.Debug|iPhone.ActiveCfg = Debug|Any CPU
- {D1C47FF1-91F1-4CAF-9ABB-AD642B821502}.Debug|iPhone.Build.0 = Debug|Any CPU
- {D1C47FF1-91F1-4CAF-9ABB-AD642B821502}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
- {D1C47FF1-91F1-4CAF-9ABB-AD642B821502}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
- {D1C47FF1-91F1-4CAF-9ABB-AD642B821502}.Debug|x64.ActiveCfg = Debug|Any CPU
- {D1C47FF1-91F1-4CAF-9ABB-AD642B821502}.Debug|x64.Build.0 = Debug|Any CPU
- {D1C47FF1-91F1-4CAF-9ABB-AD642B821502}.Debug|x86.ActiveCfg = Debug|Any CPU
- {D1C47FF1-91F1-4CAF-9ABB-AD642B821502}.Debug|x86.Build.0 = Debug|Any CPU
- {D1C47FF1-91F1-4CAF-9ABB-AD642B821502}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {D1C47FF1-91F1-4CAF-9ABB-AD642B821502}.Release|Any CPU.Build.0 = Release|Any CPU
- {D1C47FF1-91F1-4CAF-9ABB-AD642B821502}.Release|ARM.ActiveCfg = Release|Any CPU
- {D1C47FF1-91F1-4CAF-9ABB-AD642B821502}.Release|ARM.Build.0 = Release|Any CPU
- {D1C47FF1-91F1-4CAF-9ABB-AD642B821502}.Release|iPhone.ActiveCfg = Release|Any CPU
- {D1C47FF1-91F1-4CAF-9ABB-AD642B821502}.Release|iPhone.Build.0 = Release|Any CPU
- {D1C47FF1-91F1-4CAF-9ABB-AD642B821502}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
- {D1C47FF1-91F1-4CAF-9ABB-AD642B821502}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
- {D1C47FF1-91F1-4CAF-9ABB-AD642B821502}.Release|x64.ActiveCfg = Release|Any CPU
- {D1C47FF1-91F1-4CAF-9ABB-AD642B821502}.Release|x64.Build.0 = Release|Any CPU
- {D1C47FF1-91F1-4CAF-9ABB-AD642B821502}.Release|x86.ActiveCfg = Release|Any CPU
- {D1C47FF1-91F1-4CAF-9ABB-AD642B821502}.Release|x86.Build.0 = Release|Any CPU
{1A01AF82-6FCB-464C-B39C-F127AEBD315D}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
{1A01AF82-6FCB-464C-B39C-F127AEBD315D}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
{1A01AF82-6FCB-464C-B39C-F127AEBD315D}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU
@@ -1617,8 +1565,6 @@ Global
{A81ECBC2-6B00-4DCD-8388-469174033379} = {DB0EFB20-B024-4E5E-A75C-52143C131D25}
{942ED6E8-0050-495F-A0EA-01E97F63760C} = {A81ECBC2-6B00-4DCD-8388-469174033379}
{C0A7918D-B4F2-4E7F-8DE2-1E5279EF079F} = {E279BF0F-7F66-4F3A-A3AB-2CDA66C1CD04}
- {FBF43D93-F2E7-4FF8-B4AB-186895949B88} = {DB0EFB20-B024-4E5E-A75C-52143C131D25}
- {D1C47FF1-91F1-4CAF-9ABB-AD642B821502} = {FBF43D93-F2E7-4FF8-B4AB-186895949B88}
{022E145D-1593-47EE-9608-8E323D3C63F5} = {91CF7717-08AB-4E65-B10E-0B426F01E2E8}
{1A01AF82-6FCB-464C-B39C-F127AEBD315D} = {022E145D-1593-47EE-9608-8E323D3C63F5}
{22A0F9C1-2D4A-4107-95B7-8459E6688BC5} = {A81ECBC2-6B00-4DCD-8388-469174033379}
diff --git a/eShopOnContainers.sln b/eShopOnContainers.sln
index ebee1f162..83125a051 100644
--- a/eShopOnContainers.sln
+++ b/eShopOnContainers.sln
@@ -67,10 +67,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Health
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WebStatus", "src\Web\WebStatus\WebStatus.csproj", "{C0A7918D-B4F2-4E7F-8DE2-1E5279EF079F}"
EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Resilience", "Resilience", "{FBF43D93-F2E7-4FF8-B4AB-186895949B88}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Resilience.Http", "src\BuildingBlocks\Resilience\Resilience.Http\Resilience.Http.csproj", "{D1C47FF1-91F1-4CAF-9ABB-AD642B821502}"
-EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Payment", "Payment", "{022E145D-1593-47EE-9608-8E323D3C63F5}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Payment.API", "src\Services\Payment\Payment.API\Payment.API.csproj", "{1A01AF82-6FCB-464C-B39C-F127AEBD315D}"
@@ -857,54 +853,6 @@ Global
{C0A7918D-B4F2-4E7F-8DE2-1E5279EF079F}.Release|x64.Build.0 = Release|Any CPU
{C0A7918D-B4F2-4E7F-8DE2-1E5279EF079F}.Release|x86.ActiveCfg = Release|Any CPU
{C0A7918D-B4F2-4E7F-8DE2-1E5279EF079F}.Release|x86.Build.0 = Release|Any CPU
- {D1C47FF1-91F1-4CAF-9ABB-AD642B821502}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
- {D1C47FF1-91F1-4CAF-9ABB-AD642B821502}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
- {D1C47FF1-91F1-4CAF-9ABB-AD642B821502}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU
- {D1C47FF1-91F1-4CAF-9ABB-AD642B821502}.Ad-Hoc|ARM.Build.0 = Debug|Any CPU
- {D1C47FF1-91F1-4CAF-9ABB-AD642B821502}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
- {D1C47FF1-91F1-4CAF-9ABB-AD642B821502}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
- {D1C47FF1-91F1-4CAF-9ABB-AD642B821502}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
- {D1C47FF1-91F1-4CAF-9ABB-AD642B821502}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
- {D1C47FF1-91F1-4CAF-9ABB-AD642B821502}.Ad-Hoc|x64.ActiveCfg = Debug|Any CPU
- {D1C47FF1-91F1-4CAF-9ABB-AD642B821502}.Ad-Hoc|x64.Build.0 = Debug|Any CPU
- {D1C47FF1-91F1-4CAF-9ABB-AD642B821502}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU
- {D1C47FF1-91F1-4CAF-9ABB-AD642B821502}.Ad-Hoc|x86.Build.0 = Debug|Any CPU
- {D1C47FF1-91F1-4CAF-9ABB-AD642B821502}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
- {D1C47FF1-91F1-4CAF-9ABB-AD642B821502}.AppStore|Any CPU.Build.0 = Debug|Any CPU
- {D1C47FF1-91F1-4CAF-9ABB-AD642B821502}.AppStore|ARM.ActiveCfg = Debug|Any CPU
- {D1C47FF1-91F1-4CAF-9ABB-AD642B821502}.AppStore|ARM.Build.0 = Debug|Any CPU
- {D1C47FF1-91F1-4CAF-9ABB-AD642B821502}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
- {D1C47FF1-91F1-4CAF-9ABB-AD642B821502}.AppStore|iPhone.Build.0 = Debug|Any CPU
- {D1C47FF1-91F1-4CAF-9ABB-AD642B821502}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
- {D1C47FF1-91F1-4CAF-9ABB-AD642B821502}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
- {D1C47FF1-91F1-4CAF-9ABB-AD642B821502}.AppStore|x64.ActiveCfg = Debug|Any CPU
- {D1C47FF1-91F1-4CAF-9ABB-AD642B821502}.AppStore|x64.Build.0 = Debug|Any CPU
- {D1C47FF1-91F1-4CAF-9ABB-AD642B821502}.AppStore|x86.ActiveCfg = Debug|Any CPU
- {D1C47FF1-91F1-4CAF-9ABB-AD642B821502}.AppStore|x86.Build.0 = Debug|Any CPU
- {D1C47FF1-91F1-4CAF-9ABB-AD642B821502}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {D1C47FF1-91F1-4CAF-9ABB-AD642B821502}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {D1C47FF1-91F1-4CAF-9ABB-AD642B821502}.Debug|ARM.ActiveCfg = Debug|Any CPU
- {D1C47FF1-91F1-4CAF-9ABB-AD642B821502}.Debug|ARM.Build.0 = Debug|Any CPU
- {D1C47FF1-91F1-4CAF-9ABB-AD642B821502}.Debug|iPhone.ActiveCfg = Debug|Any CPU
- {D1C47FF1-91F1-4CAF-9ABB-AD642B821502}.Debug|iPhone.Build.0 = Debug|Any CPU
- {D1C47FF1-91F1-4CAF-9ABB-AD642B821502}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
- {D1C47FF1-91F1-4CAF-9ABB-AD642B821502}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
- {D1C47FF1-91F1-4CAF-9ABB-AD642B821502}.Debug|x64.ActiveCfg = Debug|Any CPU
- {D1C47FF1-91F1-4CAF-9ABB-AD642B821502}.Debug|x64.Build.0 = Debug|Any CPU
- {D1C47FF1-91F1-4CAF-9ABB-AD642B821502}.Debug|x86.ActiveCfg = Debug|Any CPU
- {D1C47FF1-91F1-4CAF-9ABB-AD642B821502}.Debug|x86.Build.0 = Debug|Any CPU
- {D1C47FF1-91F1-4CAF-9ABB-AD642B821502}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {D1C47FF1-91F1-4CAF-9ABB-AD642B821502}.Release|Any CPU.Build.0 = Release|Any CPU
- {D1C47FF1-91F1-4CAF-9ABB-AD642B821502}.Release|ARM.ActiveCfg = Release|Any CPU
- {D1C47FF1-91F1-4CAF-9ABB-AD642B821502}.Release|ARM.Build.0 = Release|Any CPU
- {D1C47FF1-91F1-4CAF-9ABB-AD642B821502}.Release|iPhone.ActiveCfg = Release|Any CPU
- {D1C47FF1-91F1-4CAF-9ABB-AD642B821502}.Release|iPhone.Build.0 = Release|Any CPU
- {D1C47FF1-91F1-4CAF-9ABB-AD642B821502}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
- {D1C47FF1-91F1-4CAF-9ABB-AD642B821502}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
- {D1C47FF1-91F1-4CAF-9ABB-AD642B821502}.Release|x64.ActiveCfg = Release|Any CPU
- {D1C47FF1-91F1-4CAF-9ABB-AD642B821502}.Release|x64.Build.0 = Release|Any CPU
- {D1C47FF1-91F1-4CAF-9ABB-AD642B821502}.Release|x86.ActiveCfg = Release|Any CPU
- {D1C47FF1-91F1-4CAF-9ABB-AD642B821502}.Release|x86.Build.0 = Release|Any CPU
{1A01AF82-6FCB-464C-B39C-F127AEBD315D}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
{1A01AF82-6FCB-464C-B39C-F127AEBD315D}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
{1A01AF82-6FCB-464C-B39C-F127AEBD315D}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU
@@ -1840,8 +1788,6 @@ Global
{A81ECBC2-6B00-4DCD-8388-469174033379} = {DB0EFB20-B024-4E5E-A75C-52143C131D25}
{942ED6E8-0050-495F-A0EA-01E97F63760C} = {A81ECBC2-6B00-4DCD-8388-469174033379}
{C0A7918D-B4F2-4E7F-8DE2-1E5279EF079F} = {E279BF0F-7F66-4F3A-A3AB-2CDA66C1CD04}
- {FBF43D93-F2E7-4FF8-B4AB-186895949B88} = {DB0EFB20-B024-4E5E-A75C-52143C131D25}
- {D1C47FF1-91F1-4CAF-9ABB-AD642B821502} = {FBF43D93-F2E7-4FF8-B4AB-186895949B88}
{022E145D-1593-47EE-9608-8E323D3C63F5} = {91CF7717-08AB-4E65-B10E-0B426F01E2E8}
{1A01AF82-6FCB-464C-B39C-F127AEBD315D} = {022E145D-1593-47EE-9608-8E323D3C63F5}
{22A0F9C1-2D4A-4107-95B7-8459E6688BC5} = {A81ECBC2-6B00-4DCD-8388-469174033379}
diff --git a/global.json b/global.json
index 00b3f36f2..97e2836a2 100644
--- a/global.json
+++ b/global.json
@@ -1,5 +1,5 @@
-{
- "sdk": {
- "version": "2.1.4"
- }
-}
\ No newline at end of file
+// {
+// "sdk": {
+// "version": "2.1.4"
+// }
+// }
\ No newline at end of file
diff --git a/src/ApiGateways/ApiGw-Base/Dockerfile b/src/ApiGateways/ApiGw-Base/Dockerfile
index 7f0cf43a6..7fdd5f073 100644
--- a/src/ApiGateways/ApiGw-Base/Dockerfile
+++ b/src/ApiGateways/ApiGw-Base/Dockerfile
@@ -1,8 +1,8 @@
-FROM microsoft/aspnetcore:2.0 AS base
+FROM microsoft/dotnet:2.1-aspnetcore-runtime AS base
WORKDIR /app
EXPOSE 80
-FROM microsoft/aspnetcore-build:2.0 AS build
+FROM microsoft/dotnet:2.1-sdk AS build
WORKDIR /src
COPY src/ApiGateways/ApiGw-Base/OcelotApiGw.csproj src/ApiGateways/ApiGw-Base/
RUN dotnet restore src/ApiGateways/ApiGw-Base/
diff --git a/src/ApiGateways/ApiGw-Base/OcelotApiGw.csproj b/src/ApiGateways/ApiGw-Base/OcelotApiGw.csproj
index d72d014b4..d3b1a049b 100644
--- a/src/ApiGateways/ApiGw-Base/OcelotApiGw.csproj
+++ b/src/ApiGateways/ApiGw-Base/OcelotApiGw.csproj
@@ -1,7 +1,7 @@
-
+
- netcoreapp2.0
+ netcoreapp2.1
@@ -9,8 +9,7 @@
-
+
-
diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Dockerfile b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Dockerfile
index 273743cee..7787dd159 100644
--- a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Dockerfile
+++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Dockerfile
@@ -1,12 +1,12 @@
-FROM microsoft/aspnetcore:2.0.5 AS base
+FROM microsoft/dotnet:2.1-aspnetcore-runtime AS base
WORKDIR /app
EXPOSE 80
-FROM microsoft/aspnetcore-build:2.0 AS build
+FROM microsoft/dotnet:2.1-sdk AS build
WORKDIR /src
COPY . .
-RUN dotnet restore -nowarn:msb3202,nu1503
WORKDIR /src/src/ApiGateways/Mobile.Bff.Shopping/aggregator
+RUN dotnet restore -nowarn:msb3202,nu1503
RUN dotnet build --no-restore -c Release -o /app
FROM build AS publish
diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Infrastructure/HttpClientAuthorizationDelegatingHandler.cs b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Infrastructure/HttpClientAuthorizationDelegatingHandler.cs
new file mode 100644
index 000000000..967a8c826
--- /dev/null
+++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Infrastructure/HttpClientAuthorizationDelegatingHandler.cs
@@ -0,0 +1,49 @@
+using Microsoft.AspNetCore.Authentication;
+using Microsoft.AspNetCore.Http;
+using System.Collections.Generic;
+using System.Net.Http;
+using System.Net.Http.Headers;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Infrastructure
+{
+ public class HttpClientAuthorizationDelegatingHandler
+ : DelegatingHandler
+ {
+ private readonly IHttpContextAccessor _httpContextAccesor;
+
+ public HttpClientAuthorizationDelegatingHandler(IHttpContextAccessor httpContextAccesor)
+ {
+ _httpContextAccesor = httpContextAccesor;
+ }
+
+ protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
+ {
+ var authorizationHeader = _httpContextAccesor.HttpContext
+ .Request.Headers["Authorization"];
+
+ if (!string.IsNullOrEmpty(authorizationHeader))
+ {
+ request.Headers.Add("Authorization", new List() { authorizationHeader });
+ }
+
+ var token = await GetToken();
+
+ if (token != null)
+ {
+ request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token);
+ }
+
+ return await base.SendAsync(request, cancellationToken);
+ }
+
+ async Task GetToken()
+ {
+ const string ACCESS_TOKEN = "access_token";
+
+ return await _httpContextAccesor.HttpContext
+ .GetTokenAsync(ACCESS_TOKEN);
+ }
+ }
+}
diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Mobile.Shopping.HttpAggregator.csproj b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Mobile.Shopping.HttpAggregator.csproj
index bd6d73950..d49c6a18f 100644
--- a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Mobile.Shopping.HttpAggregator.csproj
+++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Mobile.Shopping.HttpAggregator.csproj
@@ -1,7 +1,7 @@
-
+
- netcoreapp2.0
+ netcoreapp2.1
Mobile.Shopping.HttpAggregator
Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator
..\..\..\docker-compose.dcproj
@@ -12,16 +12,9 @@
-
+
-
-
-
-
-
-
-
-
+
diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Services/BasketService.cs b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Services/BasketService.cs
index b00fbb52c..8339ee44b 100644
--- a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Services/BasketService.cs
+++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Services/BasketService.cs
@@ -1,53 +1,41 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading.Tasks;
-using Microsoft.AspNetCore.Authentication;
-using Microsoft.AspNetCore.Http;
-using Microsoft.eShopOnContainers.BuildingBlocks.Resilience.Http;
+using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Config;
+using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Models;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
-using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Config;
-using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Models;
+using System.Net.Http;
+using System.Threading.Tasks;
namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Services
{
public class BasketService : IBasketService
{
- private readonly IHttpClient _apiClient;
+ private readonly HttpClient _httpClient;
private readonly ILogger _logger;
private readonly UrlsConfig _urls;
- private readonly IHttpContextAccessor _httpContextAccessor;
- public BasketService(IHttpClient httpClient, IHttpContextAccessor httpContextAccessor, ILogger logger, IOptionsSnapshot config)
+ public BasketService(HttpClient httpClient, ILogger logger, IOptions config)
{
- _apiClient = httpClient;
+ _httpClient = httpClient;
_logger = logger;
_urls = config.Value;
- _httpContextAccessor = httpContextAccessor;
}
public async Task GetById(string id)
{
- var token = await GetUserTokenAsync();
- var data = await _apiClient.GetStringAsync(_urls.Basket + UrlsConfig.BasketOperations.GetItemById(id), token);
+ var data = await _httpClient.GetStringAsync(_urls.Basket + UrlsConfig.BasketOperations.GetItemById(id));
+
var basket = !string.IsNullOrEmpty(data) ? JsonConvert.DeserializeObject(data) : null;
+
return basket;
}
public async Task Update(BasketData currentBasket)
{
- var token = await GetUserTokenAsync();
- var data = await _apiClient.PostAsync(_urls.Basket + UrlsConfig.BasketOperations.UpdateBasket(), currentBasket, token);
- int i = 0;
- }
+ var basketContent = new StringContent(JsonConvert.SerializeObject(currentBasket), System.Text.Encoding.UTF8, "application/json");
- async Task GetUserTokenAsync()
- {
- var context = _httpContextAccessor.HttpContext;
- return await context.GetTokenAsync("access_token");
+ var data = await _httpClient.PostAsync(_urls.Basket + UrlsConfig.BasketOperations.UpdateBasket(), basketContent);
}
}
}
diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Services/CatalogService.cs b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Services/CatalogService.cs
index d37b67679..6c59f0c49 100644
--- a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Services/CatalogService.cs
+++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Services/CatalogService.cs
@@ -1,43 +1,41 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading.Tasks;
-using Microsoft.eShopOnContainers.BuildingBlocks.Resilience.Http;
+using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Config;
+using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Models;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
-using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Config;
-using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Models;
+using System.Collections.Generic;
+using System.Net.Http;
+using System.Threading.Tasks;
namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Services
{
public class CatalogService : ICatalogService
{
-
- private readonly IHttpClient _apiClient;
+ private readonly HttpClient _httpClient;
private readonly ILogger _logger;
private readonly UrlsConfig _urls;
- public CatalogService(IHttpClient httpClient, ILogger logger, IOptionsSnapshot config)
+ public CatalogService(HttpClient httpClient, ILogger logger, IOptions config)
{
- _apiClient = httpClient;
+ _httpClient = httpClient;
_logger = logger;
_urls = config.Value;
}
public async Task GetCatalogItem(int id)
{
- var data = await _apiClient.GetStringAsync(_urls.Catalog + UrlsConfig.CatalogOperations.GetItemById(id));
- var item = JsonConvert.DeserializeObject(data);
- return item;
+ var stringContent = await _httpClient.GetStringAsync(_urls.Catalog + UrlsConfig.CatalogOperations.GetItemById(id));
+ var catalogItem = JsonConvert.DeserializeObject(stringContent);
+
+ return catalogItem;
}
public async Task> GetCatalogItems(IEnumerable ids)
{
- var data = await _apiClient.GetStringAsync(_urls.Catalog + UrlsConfig.CatalogOperations.GetItemsById(ids));
- var item = JsonConvert.DeserializeObject(data);
- return item;
+ var stringContent = await _httpClient.GetStringAsync(_urls.Catalog + UrlsConfig.CatalogOperations.GetItemsById(ids));
+ var catalogItems = JsonConvert.DeserializeObject(stringContent);
+ return catalogItems;
}
}
}
diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Services/OrderApiClient.cs b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Services/OrderApiClient.cs
index 2659e11cc..03644c110 100644
--- a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Services/OrderApiClient.cs
+++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Services/OrderApiClient.cs
@@ -1,24 +1,20 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading.Tasks;
-using Microsoft.eShopOnContainers.BuildingBlocks.Resilience.Http;
+using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Config;
+using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Models;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
-using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Config;
-using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Models;
+using System.Net.Http;
+using System.Threading.Tasks;
namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Services
{
public class OrderApiClient : IOrderApiClient
{
-
- private readonly IHttpClient _apiClient;
+ private readonly HttpClient _apiClient;
private readonly ILogger _logger;
private readonly UrlsConfig _urls;
- public OrderApiClient(IHttpClient httpClient, ILogger logger, IOptionsSnapshot config)
+ public OrderApiClient(HttpClient httpClient, ILogger logger, IOptions config)
{
_apiClient = httpClient;
_logger = logger;
@@ -27,11 +23,15 @@ namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Services
public async Task GetOrderDraftFromBasket(BasketData basket)
{
- var url = _urls.Orders + UrlsConfig.OrdersOperations.GetOrderDraft();
- var response = await _apiClient.PostAsync(url, basket);
+ var uri = _urls.Orders + UrlsConfig.OrdersOperations.GetOrderDraft();
+ var content = new StringContent(JsonConvert.SerializeObject(basket), System.Text.Encoding.UTF8, "application/json");
+ var response = await _apiClient.PostAsync(uri, content);
+
response.EnsureSuccessStatusCode();
- var jsonResponse = await response.Content.ReadAsStringAsync();
- return JsonConvert.DeserializeObject(jsonResponse);
+
+ var ordersDraftResponse = await response.Content.ReadAsStringAsync();
+
+ return JsonConvert.DeserializeObject(ordersDraftResponse);
}
}
}
diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Startup.cs b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Startup.cs
index 73b736519..1d24e8312 100644
--- a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Startup.cs
+++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Startup.cs
@@ -1,21 +1,21 @@
-using System;
-using System.Collections.Generic;
-using System.IdentityModel.Tokens.Jwt;
-using System.Linq;
-using System.Threading.Tasks;
-using Microsoft.AspNetCore.Authentication.JwtBearer;
+using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
-using Microsoft.eShopOnContainers.BuildingBlocks.Resilience.Http;
+using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Config;
+using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Filters.Basket.API.Infrastructure.Filters;
+using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Infrastructure;
+using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Services;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
-using Microsoft.Extensions.Options;
-using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Config;
-using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Filters.Basket.API.Infrastructure.Filters;
-using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Services;
+using Polly;
+using Polly.Extensions.Http;
using Swashbuckle.AspNetCore.Swagger;
+using System;
+using System.Collections.Generic;
+using System.IdentityModel.Tokens.Jwt;
+using System.Net.Http;
namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator
{
@@ -31,84 +31,16 @@ namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
- services.AddSingleton();
- services.AddSingleton();
- services.AddTransient();
- services.AddTransient();
- services.AddTransient();
-
- services.AddOptions();
- services.Configure(Configuration.GetSection("urls"));
-
- services.AddMvc();
-
- services.AddSwaggerGen(options =>
- {
- options.DescribeAllEnumsAsStrings();
- options.SwaggerDoc("v1", new Swashbuckle.AspNetCore.Swagger.Info
- {
- Title = "Shopping Aggregator for Mobile Clients",
- Version = "v1",
- Description = "Shopping Aggregator for Mobile Clients",
- TermsOfService = "Terms Of Service"
- });
-
- options.AddSecurityDefinition("oauth2", new OAuth2Scheme
- {
- Type = "oauth2",
- Flow = "implicit",
- AuthorizationUrl = $"{Configuration.GetValue("IdentityUrlExternal")}/connect/authorize",
- TokenUrl = $"{Configuration.GetValue("IdentityUrlExternal")}/connect/token",
- Scopes = new Dictionary()
- {
- { "mobileshoppingagg", "Shopping Aggregator for Mobile Clients" }
- }
- });
-
- options.OperationFilter();
- });
-
- services.AddCors(options =>
- {
- options.AddPolicy("CorsPolicy",
- builder => builder.AllowAnyOrigin()
- .AllowAnyMethod()
- .AllowAnyHeader()
- .AllowCredentials());
- });
-
-
- JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
- var identityUrl = Configuration.GetValue("urls:identity");
- services.AddAuthentication(options =>
- {
- options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
- options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
-
- }).AddJwtBearer(options =>
- {
- options.Authority = identityUrl;
- options.RequireHttpsMetadata = false;
- options.Audience = "mobileshoppingagg";
- options.Events = new JwtBearerEvents()
- {
- OnAuthenticationFailed = async ctx =>
- {
- int i = 0;
- },
- OnTokenValidated = async ctx =>
- {
- int i = 0;
- }
- };
- });
+ services.AddCustomMvc(Configuration)
+ .AddCustomAuthentication(Configuration)
+ .AddHttpServices();
}
// 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)
{
-
var pathBase = Configuration["PATH_BASE"];
+
if (!string.IsNullOrEmpty(pathBase))
{
loggerFactory.CreateLogger("init").LogDebug($"Using PATH BASE '{pathBase}'");
@@ -131,8 +63,122 @@ namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator
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");
});
+ }
+ }
+
+ public static class ServiceCollectionExtensions
+ {
+ public static IServiceCollection AddCustomMvc(this IServiceCollection services, IConfiguration configuration)
+ {
+ services.AddOptions();
+ services.Configure(configuration.GetSection("urls"));
+
+ services.AddMvc();
+
+ services.AddSwaggerGen(options =>
+ {
+ options.DescribeAllEnumsAsStrings();
+ options.SwaggerDoc("v1", new Swashbuckle.AspNetCore.Swagger.Info
+ {
+ Title = "Shopping Aggregator for Mobile Clients",
+ Version = "v1",
+ Description = "Shopping Aggregator for Mobile Clients",
+ TermsOfService = "Terms Of Service"
+ });
+
+ options.AddSecurityDefinition("oauth2", new OAuth2Scheme
+ {
+ Type = "oauth2",
+ Flow = "implicit",
+ AuthorizationUrl = $"{configuration.GetValue("IdentityUrlExternal")}/connect/authorize",
+ TokenUrl = $"{configuration.GetValue("IdentityUrlExternal")}/connect/token",
+ Scopes = new Dictionary()
+ {
+ { "mobileshoppingagg", "Shopping Aggregator for Mobile Clients" }
+ }
+ });
+
+ options.OperationFilter();
+ });
+
+ services.AddCors(options =>
+ {
+ options.AddPolicy("CorsPolicy",
+ builder => builder.AllowAnyOrigin()
+ .AllowAnyMethod()
+ .AllowAnyHeader()
+ .AllowCredentials());
+ });
+
+ return services;
+ }
+ public static IServiceCollection AddCustomAuthentication(this IServiceCollection services, IConfiguration configuration)
+ {
+ JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
+ var identityUrl = configuration.GetValue("urls:identity");
+ services.AddAuthentication(options =>
+ {
+ options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
+ options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
+
+ }).AddJwtBearer(options =>
+ {
+ options.Authority = identityUrl;
+ options.RequireHttpsMetadata = false;
+ options.Audience = "mobileshoppingagg";
+ options.Events = new JwtBearerEvents()
+ {
+ OnAuthenticationFailed = async ctx =>
+ {
+ int i = 0;
+ },
+ OnTokenValidated = async ctx =>
+ {
+ int i = 0;
+ }
+ };
+ });
+
+ return services;
+ }
+ public static IServiceCollection AddHttpServices(this IServiceCollection services)
+ {
+ //register delegating handlers
+ services.AddTransient();
+ services.AddSingleton();
+
+ //register http services
+ services.AddHttpClient()
+ .AddHttpMessageHandler()
+ .AddPolicyHandler(GetRetryPolicy())
+ .AddPolicyHandler(GetCircuitBreakerPolicy());
+
+ services.AddHttpClient()
+ .AddPolicyHandler(GetRetryPolicy())
+ .AddPolicyHandler(GetCircuitBreakerPolicy());
+
+ services.AddHttpClient()
+ .AddPolicyHandler(GetRetryPolicy())
+ .AddPolicyHandler(GetCircuitBreakerPolicy());
+
+ return services;
+ }
+
+ static IAsyncPolicy GetRetryPolicy()
+ {
+ return HttpPolicyExtensions
+ .HandleTransientHttpError()
+ .OrResult(msg => msg.StatusCode == System.Net.HttpStatusCode.NotFound)
+ .WaitAndRetryAsync(6, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)));
+
+ }
+ static IAsyncPolicy GetCircuitBreakerPolicy()
+ {
+ return HttpPolicyExtensions
+ .HandleTransientHttpError()
+ .CircuitBreakerAsync(5, TimeSpan.FromSeconds(30));
}
}
}
diff --git a/src/ApiGateways/Web.Bff.Shopping/aggregator/Dockerfile b/src/ApiGateways/Web.Bff.Shopping/aggregator/Dockerfile
index ce6f1b155..d4940d436 100644
--- a/src/ApiGateways/Web.Bff.Shopping/aggregator/Dockerfile
+++ b/src/ApiGateways/Web.Bff.Shopping/aggregator/Dockerfile
@@ -1,12 +1,12 @@
-FROM microsoft/aspnetcore:2.0.5 AS base
+FROM microsoft/dotnet:2.1-aspnetcore-runtime AS base
WORKDIR /app
EXPOSE 80
-FROM microsoft/aspnetcore-build:2.0 AS build
+FROM microsoft/dotnet:2.1-sdk AS build
WORKDIR /src
COPY . .
-RUN dotnet restore -nowarn:msb3202,nu1503
WORKDIR /src/src/ApiGateways/Web.Bff.Shopping/aggregator
+RUN dotnet restore -nowarn:msb3202,nu1503
RUN dotnet build --no-restore -c Release -o /app
FROM build AS publish
diff --git a/src/ApiGateways/Web.Bff.Shopping/aggregator/Infrastructure/HttpClientAuthorizationDelegatingHandler.cs b/src/ApiGateways/Web.Bff.Shopping/aggregator/Infrastructure/HttpClientAuthorizationDelegatingHandler.cs
new file mode 100644
index 000000000..4e54829f8
--- /dev/null
+++ b/src/ApiGateways/Web.Bff.Shopping/aggregator/Infrastructure/HttpClientAuthorizationDelegatingHandler.cs
@@ -0,0 +1,49 @@
+using Microsoft.AspNetCore.Authentication;
+using Microsoft.AspNetCore.Http;
+using System.Collections.Generic;
+using System.Net.Http;
+using System.Net.Http.Headers;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Infrastructure
+{
+ public class HttpClientAuthorizationDelegatingHandler
+ : DelegatingHandler
+ {
+ private readonly IHttpContextAccessor _httpContextAccesor;
+
+ public HttpClientAuthorizationDelegatingHandler(IHttpContextAccessor httpContextAccesor)
+ {
+ _httpContextAccesor = httpContextAccesor;
+ }
+
+ protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
+ {
+ var authorizationHeader = _httpContextAccesor.HttpContext
+ .Request.Headers["Authorization"];
+
+ if (!string.IsNullOrEmpty(authorizationHeader))
+ {
+ request.Headers.Add("Authorization", new List() { authorizationHeader });
+ }
+
+ var token = await GetToken();
+
+ if (token != null)
+ {
+ request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token);
+ }
+
+ return await base.SendAsync(request, cancellationToken);
+ }
+
+ async Task GetToken()
+ {
+ const string ACCESS_TOKEN = "access_token";
+
+ return await _httpContextAccesor.HttpContext
+ .GetTokenAsync(ACCESS_TOKEN);
+ }
+ }
+}
diff --git a/src/ApiGateways/Web.Bff.Shopping/aggregator/Services/BasketService.cs b/src/ApiGateways/Web.Bff.Shopping/aggregator/Services/BasketService.cs
index 5ca89a408..291e98fd3 100644
--- a/src/ApiGateways/Web.Bff.Shopping/aggregator/Services/BasketService.cs
+++ b/src/ApiGateways/Web.Bff.Shopping/aggregator/Services/BasketService.cs
@@ -1,53 +1,39 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading.Tasks;
-using Microsoft.AspNetCore.Authentication;
-using Microsoft.AspNetCore.Http;
-using Microsoft.eShopOnContainers.BuildingBlocks.Resilience.Http;
+using Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Config;
+using Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Models;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
-using Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Config;
-using Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Models;
+using System.Net.Http;
+using System.Threading.Tasks;
namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Services
{
public class BasketService : IBasketService
{
- private readonly IHttpClient _apiClient;
+ private readonly HttpClient _apiClient;
private readonly ILogger _logger;
private readonly UrlsConfig _urls;
- private readonly IHttpContextAccessor _httpContextAccessor;
- public BasketService(IHttpClient httpClient, IHttpContextAccessor httpContextAccessor, ILogger logger, IOptionsSnapshot config)
+ public BasketService(HttpClient httpClient,ILogger logger, IOptions config)
{
_apiClient = httpClient;
_logger = logger;
_urls = config.Value;
- _httpContextAccessor = httpContextAccessor;
}
public async Task GetById(string id)
{
- var token = await GetUserTokenAsync();
- var data = await _apiClient.GetStringAsync(_urls.Basket + UrlsConfig.BasketOperations.GetItemById(id), token);
+ var data = await _apiClient.GetStringAsync(_urls.Basket + UrlsConfig.BasketOperations.GetItemById(id));
var basket = !string.IsNullOrEmpty(data) ? JsonConvert.DeserializeObject(data) : null;
return basket;
}
public async Task Update(BasketData currentBasket)
{
- var token = await GetUserTokenAsync();
- var data = await _apiClient.PostAsync(_urls.Basket + UrlsConfig.BasketOperations.UpdateBasket(), currentBasket, token);
- int i = 0;
- }
+ var basketContent = new StringContent(JsonConvert.SerializeObject(currentBasket), System.Text.Encoding.UTF8, "application/json");
- async Task GetUserTokenAsync()
- {
- var context = _httpContextAccessor.HttpContext;
- return await context.GetTokenAsync("access_token");
+ var data = await _apiClient.PostAsync(_urls.Basket + UrlsConfig.BasketOperations.UpdateBasket(), basketContent);
}
}
}
diff --git a/src/ApiGateways/Web.Bff.Shopping/aggregator/Services/CatalogService.cs b/src/ApiGateways/Web.Bff.Shopping/aggregator/Services/CatalogService.cs
index 46d895f68..ba67b7c1e 100644
--- a/src/ApiGateways/Web.Bff.Shopping/aggregator/Services/CatalogService.cs
+++ b/src/ApiGateways/Web.Bff.Shopping/aggregator/Services/CatalogService.cs
@@ -1,43 +1,42 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading.Tasks;
-using Microsoft.eShopOnContainers.BuildingBlocks.Resilience.Http;
+using Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Config;
+using Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Models;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
-using Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Config;
-using Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Models;
+using System.Collections.Generic;
+using System.Net.Http;
+using System.Threading.Tasks;
namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Services
{
public class CatalogService : ICatalogService
{
- private readonly IHttpClient _apiClient;
+ private readonly HttpClient _httpClient;
private readonly ILogger _logger;
private readonly UrlsConfig _urls;
- public CatalogService(IHttpClient httpClient, ILogger logger, IOptionsSnapshot config)
+ public CatalogService(HttpClient httpClient, ILogger logger, IOptions config)
{
- _apiClient = httpClient;
+ _httpClient = httpClient;
_logger = logger;
_urls = config.Value;
}
public async Task GetCatalogItem(int id)
{
- var data = await _apiClient.GetStringAsync(_urls.Catalog + UrlsConfig.CatalogOperations.GetItemById(id));
- var item = JsonConvert.DeserializeObject(data);
- return item;
+ var stringContent = await _httpClient.GetStringAsync(_urls.Catalog + UrlsConfig.CatalogOperations.GetItemById(id));
+ var catalogItem = JsonConvert.DeserializeObject(stringContent);
+
+ return catalogItem;
}
public async Task> GetCatalogItems(IEnumerable ids)
{
- var data = await _apiClient.GetStringAsync(_urls.Catalog + UrlsConfig.CatalogOperations.GetItemsById(ids));
- var item = JsonConvert.DeserializeObject(data);
- return item;
+ var stringContent = await _httpClient.GetStringAsync(_urls.Catalog + UrlsConfig.CatalogOperations.GetItemsById(ids));
+ var catalogItems = JsonConvert.DeserializeObject(stringContent);
+ return catalogItems;
}
}
}
diff --git a/src/ApiGateways/Web.Bff.Shopping/aggregator/Services/OrderApiClient.cs b/src/ApiGateways/Web.Bff.Shopping/aggregator/Services/OrderApiClient.cs
index 220e9afa9..d43e392d3 100644
--- a/src/ApiGateways/Web.Bff.Shopping/aggregator/Services/OrderApiClient.cs
+++ b/src/ApiGateways/Web.Bff.Shopping/aggregator/Services/OrderApiClient.cs
@@ -1,24 +1,21 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading.Tasks;
-using Microsoft.eShopOnContainers.BuildingBlocks.Resilience.Http;
+using Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Config;
+using Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Models;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
-using Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Config;
-using Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Models;
+using System.Net.Http;
+using System.Threading.Tasks;
namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Services
{
public class OrderApiClient : IOrderApiClient
{
- private readonly IHttpClient _apiClient;
+ private readonly HttpClient _apiClient;
private readonly ILogger _logger;
private readonly UrlsConfig _urls;
- public OrderApiClient(IHttpClient httpClient, ILogger logger, IOptionsSnapshot config)
+ public OrderApiClient(HttpClient httpClient, ILogger logger, IOptions config)
{
_apiClient = httpClient;
_logger = logger;
@@ -28,10 +25,14 @@ namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Services
public async Task GetOrderDraftFromBasket(BasketData basket)
{
var url = _urls.Orders + UrlsConfig.OrdersOperations.GetOrderDraft();
- var response = await _apiClient.PostAsync(url, basket);
+ var content = new StringContent(JsonConvert.SerializeObject(basket), System.Text.Encoding.UTF8, "application/json");
+ var response = await _apiClient.PostAsync(url, content);
+
response.EnsureSuccessStatusCode();
- var jsonResponse = await response.Content.ReadAsStringAsync();
- return JsonConvert.DeserializeObject(jsonResponse);
+
+ var ordersDraftResponse = await response.Content.ReadAsStringAsync();
+
+ return JsonConvert.DeserializeObject(ordersDraftResponse);
}
}
}
diff --git a/src/ApiGateways/Web.Bff.Shopping/aggregator/Startup.cs b/src/ApiGateways/Web.Bff.Shopping/aggregator/Startup.cs
index 17f9f90e6..e4a080289 100644
--- a/src/ApiGateways/Web.Bff.Shopping/aggregator/Startup.cs
+++ b/src/ApiGateways/Web.Bff.Shopping/aggregator/Startup.cs
@@ -1,21 +1,22 @@
-using System;
-using System.Collections.Generic;
-using System.IdentityModel.Tokens.Jwt;
-using System.Linq;
-using System.Threading.Tasks;
-using Microsoft.AspNetCore.Authentication.JwtBearer;
+using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
-using Microsoft.eShopOnContainers.BuildingBlocks.Resilience.Http;
+using Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Config;
+using Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Filters.Basket.API.Infrastructure.Filters;
+using Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Infrastructure;
+using Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Services;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
-using Microsoft.Extensions.Options;
-using Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Config;
-using Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Filters.Basket.API.Infrastructure.Filters;
-using Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Services;
+using Polly;
+using Polly.Extensions.Http;
+using Polly.Timeout;
using Swashbuckle.AspNetCore.Swagger;
+using System;
+using System.Collections.Generic;
+using System.IdentityModel.Tokens.Jwt;
+using System.Net.Http;
namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator
{
@@ -31,55 +32,48 @@ namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
- services.AddSingleton();
- services.AddSingleton();
- services.AddTransient();
- services.AddTransient();
- services.AddTransient();
+ services.AddCustomMvc(Configuration)
+ .AddCustomAuthentication(Configuration)
+ .AddApplicationServices();
+ }
- services.AddOptions();
- services.Configure(Configuration.GetSection("urls"));
-
- services.AddMvc();
-
- services.AddSwaggerGen(options =>
+ // 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)
+ {
+ var pathBase = Configuration["PATH_BASE"];
+ if (!string.IsNullOrEmpty(pathBase))
{
- options.DescribeAllEnumsAsStrings();
- options.SwaggerDoc("v1", new Swashbuckle.AspNetCore.Swagger.Info
- {
- Title = "Shopping Aggregator for Web Clients",
- Version = "v1",
- Description = "Shopping Aggregator for Web Clients",
- TermsOfService = "Terms Of Service"
- });
+ loggerFactory.CreateLogger("init").LogDebug($"Using PATH BASE '{pathBase}'");
+ app.UsePathBase(pathBase);
+ }
- options.AddSecurityDefinition("oauth2", new OAuth2Scheme
- {
- Type = "oauth2",
- Flow = "implicit",
- AuthorizationUrl = $"{Configuration.GetValue("IdentityUrlExternal")}/connect/authorize",
- TokenUrl = $"{Configuration.GetValue("IdentityUrlExternal")}/connect/token",
- Scopes = new Dictionary()
- {
- { "webshoppingagg", "Shopping Aggregator for Web Clients" }
- }
- });
+ app.UseCors("CorsPolicy");
- options.OperationFilter();
- });
-
- services.AddCors(options =>
+ if (env.IsDevelopment())
{
- options.AddPolicy("CorsPolicy",
- builder => builder.AllowAnyOrigin()
- .AllowAnyMethod()
- .AllowAnyHeader()
- .AllowCredentials());
- });
+ app.UseDeveloperExceptionPage();
+ }
+
+ app.UseAuthentication();
+
+ app.UseMvc();
+
+ 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");
+ });
+ }
+ }
+
+ public static class ServiceCollectionExtensions
+ {
+ public static IServiceCollection AddCustomAuthentication(this IServiceCollection services, IConfiguration configuration)
+ {
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
- var identityUrl = Configuration.GetValue("urls:identity");
+ var identityUrl = configuration.GetValue("urls:identity");
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
@@ -102,37 +96,92 @@ namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator
}
};
});
+
+ return services;
+ }
+ public static IServiceCollection AddCustomMvc(this IServiceCollection services, IConfiguration configuration)
+ {
+ services.AddOptions();
+ services.Configure(configuration.GetSection("urls"));
+
+ services.AddMvc();
+
+ services.AddSwaggerGen(options =>
+ {
+ options.DescribeAllEnumsAsStrings();
+ options.SwaggerDoc("v1", new Swashbuckle.AspNetCore.Swagger.Info
+ {
+ Title = "Shopping Aggregator for Web Clients",
+ Version = "v1",
+ Description = "Shopping Aggregator for Web Clients",
+ TermsOfService = "Terms Of Service"
+ });
+
+ options.AddSecurityDefinition("oauth2", new OAuth2Scheme
+ {
+ Type = "oauth2",
+ Flow = "implicit",
+ AuthorizationUrl = $"{configuration.GetValue("IdentityUrlExternal")}/connect/authorize",
+ TokenUrl = $"{configuration.GetValue("IdentityUrlExternal")}/connect/token",
+ Scopes = new Dictionary()
+ {
+ { "webshoppingagg", "Shopping Aggregator for Web Clients" }
+ }
+ });
+
+ options.OperationFilter();
+ });
+
+ services.AddCors(options =>
+ {
+ options.AddPolicy("CorsPolicy",
+ builder => builder.AllowAnyOrigin()
+ .AllowAnyMethod()
+ .AllowAnyHeader()
+ .AllowCredentials());
+ });
+
+ return services;
+ }
+ public static IServiceCollection AddApplicationServices(this IServiceCollection services)
+ {
+ //register delegating handlers
+ services.AddTransient();
+ services.AddSingleton();
+
+ //register http services
+
+ services.AddHttpClient()
+ .AddHttpMessageHandler()
+ .AddPolicyHandler(GetRetryPolicy())
+ .AddPolicyHandler(GetCircuitBreakerPolicy());
+
+ services.AddHttpClient()
+ .AddPolicyHandler(GetRetryPolicy())
+ .AddPolicyHandler(GetCircuitBreakerPolicy());
+
+ services.AddHttpClient()
+ .AddHttpMessageHandler()
+ .AddPolicyHandler(GetRetryPolicy())
+ .AddPolicyHandler(GetCircuitBreakerPolicy());
+
+
+ return services;
}
- // 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)
+ static IAsyncPolicy GetRetryPolicy()
{
+ return HttpPolicyExtensions
+ .HandleTransientHttpError()
+ .OrResult(msg => msg.StatusCode == System.Net.HttpStatusCode.NotFound)
+ .WaitAndRetryAsync(6, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)));
- var pathBase = Configuration["PATH_BASE"];
- if (!string.IsNullOrEmpty(pathBase))
- {
- loggerFactory.CreateLogger("init").LogDebug($"Using PATH BASE '{pathBase}'");
- app.UsePathBase(pathBase);
- }
-
- app.UseCors("CorsPolicy");
-
- if (env.IsDevelopment())
- {
- app.UseDeveloperExceptionPage();
- }
-
- app.UseAuthentication();
-
- app.UseMvc();
-
- 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");
- });
-
-
+ }
+ static IAsyncPolicy GetCircuitBreakerPolicy()
+ {
+ return HttpPolicyExtensions
+ .HandleTransientHttpError()
+ .CircuitBreakerAsync(5, TimeSpan.FromSeconds(30));
}
}
}
diff --git a/src/ApiGateways/Web.Bff.Shopping/aggregator/Web.Shopping.HttpAggregator.csproj b/src/ApiGateways/Web.Bff.Shopping/aggregator/Web.Shopping.HttpAggregator.csproj
index 0b6dbf44b..7a0f6cc01 100644
--- a/src/ApiGateways/Web.Bff.Shopping/aggregator/Web.Shopping.HttpAggregator.csproj
+++ b/src/ApiGateways/Web.Bff.Shopping/aggregator/Web.Shopping.HttpAggregator.csproj
@@ -1,7 +1,7 @@
-
+
- netcoreapp2.0
+ netcoreapp2.1
Web.Shopping.HttpAggregator
Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator
..\..\..\docker-compose.dcproj
@@ -12,16 +12,10 @@
-
-
-
-
-
-
-
-
-
-
+
+
+
+
diff --git a/src/BuildingBlocks/EventBus/EventBus/EventBus.csproj b/src/BuildingBlocks/EventBus/EventBus/EventBus.csproj
index b219dcfa1..9704f6ff5 100644
--- a/src/BuildingBlocks/EventBus/EventBus/EventBus.csproj
+++ b/src/BuildingBlocks/EventBus/EventBus/EventBus.csproj
@@ -6,7 +6,7 @@
-
+
\ No newline at end of file
diff --git a/src/BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.csproj b/src/BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.csproj
index d6c9fc8e2..06514ba41 100644
--- a/src/BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.csproj
+++ b/src/BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.csproj
@@ -7,12 +7,12 @@
-
-
-
-
+
+
+
+
-
+
diff --git a/src/BuildingBlocks/EventBus/EventBusServiceBus/EventBusServiceBus.csproj b/src/BuildingBlocks/EventBus/EventBusServiceBus/EventBusServiceBus.csproj
index 8e76a02db..9eb4bd19a 100644
--- a/src/BuildingBlocks/EventBus/EventBusServiceBus/EventBusServiceBus.csproj
+++ b/src/BuildingBlocks/EventBus/EventBusServiceBus/EventBusServiceBus.csproj
@@ -7,9 +7,9 @@
-
-
-
+
+
+
diff --git a/src/BuildingBlocks/EventBus/IntegrationEventLogEF/IntegrationEventLogEF.csproj b/src/BuildingBlocks/EventBus/IntegrationEventLogEF/IntegrationEventLogEF.csproj
index d4f380a14..5ffc3c9eb 100644
--- a/src/BuildingBlocks/EventBus/IntegrationEventLogEF/IntegrationEventLogEF.csproj
+++ b/src/BuildingBlocks/EventBus/IntegrationEventLogEF/IntegrationEventLogEF.csproj
@@ -6,18 +6,12 @@
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
diff --git a/src/BuildingBlocks/HealthChecks/src/Microsoft.AspNetCore.HealthChecks/Microsoft.AspNetCore.HealthChecks.csproj b/src/BuildingBlocks/HealthChecks/src/Microsoft.AspNetCore.HealthChecks/Microsoft.AspNetCore.HealthChecks.csproj
index 5018e198c..ce659345f 100644
--- a/src/BuildingBlocks/HealthChecks/src/Microsoft.AspNetCore.HealthChecks/Microsoft.AspNetCore.HealthChecks.csproj
+++ b/src/BuildingBlocks/HealthChecks/src/Microsoft.AspNetCore.HealthChecks/Microsoft.AspNetCore.HealthChecks.csproj
@@ -13,7 +13,7 @@
-
+
\ No newline at end of file
diff --git a/src/BuildingBlocks/HealthChecks/src/Microsoft.Extensions.HealthChecks.AzureStorage/Microsoft.Extensions.HealthChecks.AzureStorage.csproj b/src/BuildingBlocks/HealthChecks/src/Microsoft.Extensions.HealthChecks.AzureStorage/Microsoft.Extensions.HealthChecks.AzureStorage.csproj
index 007f66f65..844098052 100644
--- a/src/BuildingBlocks/HealthChecks/src/Microsoft.Extensions.HealthChecks.AzureStorage/Microsoft.Extensions.HealthChecks.AzureStorage.csproj
+++ b/src/BuildingBlocks/HealthChecks/src/Microsoft.Extensions.HealthChecks.AzureStorage/Microsoft.Extensions.HealthChecks.AzureStorage.csproj
@@ -16,10 +16,10 @@
-
+
-
+
diff --git a/src/BuildingBlocks/HealthChecks/src/Microsoft.Extensions.HealthChecks.SqlServer/Microsoft.Extensions.HealthChecks.SqlServer.csproj b/src/BuildingBlocks/HealthChecks/src/Microsoft.Extensions.HealthChecks.SqlServer/Microsoft.Extensions.HealthChecks.SqlServer.csproj
index 0aef3c907..6217f6069 100644
--- a/src/BuildingBlocks/HealthChecks/src/Microsoft.Extensions.HealthChecks.SqlServer/Microsoft.Extensions.HealthChecks.SqlServer.csproj
+++ b/src/BuildingBlocks/HealthChecks/src/Microsoft.Extensions.HealthChecks.SqlServer/Microsoft.Extensions.HealthChecks.SqlServer.csproj
@@ -9,7 +9,7 @@
-
+
diff --git a/src/BuildingBlocks/HealthChecks/src/Microsoft.Extensions.HealthChecks/Microsoft.Extensions.HealthChecks.csproj b/src/BuildingBlocks/HealthChecks/src/Microsoft.Extensions.HealthChecks/Microsoft.Extensions.HealthChecks.csproj
index 6c102c33d..5e63cac75 100644
--- a/src/BuildingBlocks/HealthChecks/src/Microsoft.Extensions.HealthChecks/Microsoft.Extensions.HealthChecks.csproj
+++ b/src/BuildingBlocks/HealthChecks/src/Microsoft.Extensions.HealthChecks/Microsoft.Extensions.HealthChecks.csproj
@@ -9,12 +9,12 @@
-
-
+
+
-
+
diff --git a/src/BuildingBlocks/Resilience/Resilience.Http/IHttpClient.cs b/src/BuildingBlocks/Resilience/Resilience.Http/IHttpClient.cs
deleted file mode 100644
index 5ea3003ed..000000000
--- a/src/BuildingBlocks/Resilience/Resilience.Http/IHttpClient.cs
+++ /dev/null
@@ -1,16 +0,0 @@
-using System.Net.Http;
-using System.Threading.Tasks;
-
-namespace Microsoft.eShopOnContainers.BuildingBlocks.Resilience.Http
-{
- public interface IHttpClient
- {
- Task GetStringAsync(string uri, string authorizationToken = null, string authorizationMethod = "Bearer");
-
- Task PostAsync(string uri, T item, string authorizationToken = null, string requestId = null, string authorizationMethod = "Bearer");
-
- Task DeleteAsync(string uri, string authorizationToken = null, string requestId = null, string authorizationMethod = "Bearer");
-
- Task PutAsync(string uri, T item, string authorizationToken = null, string requestId = null, string authorizationMethod = "Bearer");
- }
-}
diff --git a/src/BuildingBlocks/Resilience/Resilience.Http/Resilience.Http.csproj b/src/BuildingBlocks/Resilience/Resilience.Http/Resilience.Http.csproj
deleted file mode 100644
index 276c1a23f..000000000
--- a/src/BuildingBlocks/Resilience/Resilience.Http/Resilience.Http.csproj
+++ /dev/null
@@ -1,15 +0,0 @@
-
-
-
- netstandard2.0
- Microsoft.eShopOnContainers.BuildingBlocks.Resilience.Http
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/src/BuildingBlocks/Resilience/Resilience.Http/ResilientHttpClient.cs b/src/BuildingBlocks/Resilience/Resilience.Http/ResilientHttpClient.cs
deleted file mode 100644
index 9fa38ee8d..000000000
--- a/src/BuildingBlocks/Resilience/Resilience.Http/ResilientHttpClient.cs
+++ /dev/null
@@ -1,191 +0,0 @@
-using Microsoft.Extensions.Logging;
-using Newtonsoft.Json;
-using Polly;
-using Polly.Wrap;
-using System;
-using System.Collections.Concurrent;
-using System.Collections.Generic;
-using System.Linq;
-using System.Net;
-using System.Net.Http;
-using System.Net.Http.Headers;
-using System.Threading.Tasks;
-using Microsoft.AspNetCore.Http;
-
-namespace Microsoft.eShopOnContainers.BuildingBlocks.Resilience.Http
-{
- ///
- /// HttpClient wrapper that integrates Retry and Circuit
- /// breaker policies when invoking HTTP services.
- /// Based on Polly library: https://github.com/App-vNext/Polly
- ///
- public class ResilientHttpClient : IHttpClient
- {
- private readonly HttpClient _client;
- private readonly ILogger _logger;
- private readonly Func> _policyCreator;
- private ConcurrentDictionary _policyWrappers;
- private readonly IHttpContextAccessor _httpContextAccessor;
-
- public ResilientHttpClient(Func> policyCreator, ILogger logger, IHttpContextAccessor httpContextAccessor)
- {
- _client = new HttpClient();
- _logger = logger;
- _policyCreator = policyCreator;
- _policyWrappers = new ConcurrentDictionary();
- _httpContextAccessor = httpContextAccessor;
- }
-
-
- public Task PostAsync(string uri, T item, string authorizationToken = null, string requestId = null, string authorizationMethod = "Bearer")
- {
- return DoPostPutAsync(HttpMethod.Post, uri, item, authorizationToken, requestId, authorizationMethod);
- }
-
- public Task PutAsync(string uri, T item, string authorizationToken = null, string requestId = null, string authorizationMethod = "Bearer")
- {
- return DoPostPutAsync(HttpMethod.Put, uri, item, authorizationToken, requestId, authorizationMethod);
- }
-
- public Task DeleteAsync(string uri, string authorizationToken = null, string requestId = null, string authorizationMethod = "Bearer")
- {
- var origin = GetOriginFromUri(uri);
-
- return HttpInvoker(origin, async () =>
- {
- var requestMessage = new HttpRequestMessage(HttpMethod.Delete, uri);
-
- SetAuthorizationHeader(requestMessage);
-
- if (authorizationToken != null)
- {
- requestMessage.Headers.Authorization = new AuthenticationHeaderValue(authorizationMethod, authorizationToken);
- }
-
- if (requestId != null)
- {
- requestMessage.Headers.Add("x-requestid", requestId);
- }
-
- return await _client.SendAsync(requestMessage);
- });
- }
-
-
- public Task GetStringAsync(string uri, string authorizationToken = null, string authorizationMethod = "Bearer")
- {
- var origin = GetOriginFromUri(uri);
-
- return HttpInvoker(origin, async () =>
- {
- var requestMessage = new HttpRequestMessage(HttpMethod.Get, uri);
-
- SetAuthorizationHeader(requestMessage);
-
- if (authorizationToken != null)
- {
- requestMessage.Headers.Authorization = new AuthenticationHeaderValue(authorizationMethod, authorizationToken);
- }
-
- var response = await _client.SendAsync(requestMessage);
-
- // raise exception if HttpResponseCode 500
- // needed for circuit breaker to track fails
-
- if (response.StatusCode == HttpStatusCode.InternalServerError)
- {
- throw new HttpRequestException();
- }
-
- if (!response.IsSuccessStatusCode)
- {
- return null;
- }
-
- return await response.Content.ReadAsStringAsync();
- });
- }
-
- private Task DoPostPutAsync(HttpMethod method, string uri, T item, string authorizationToken = null, string requestId = null, string authorizationMethod = "Bearer")
- {
- if (method != HttpMethod.Post && method != HttpMethod.Put)
- {
- throw new ArgumentException("Value must be either post or put.", nameof(method));
- }
-
- // a new StringContent must be created for each retry
- // as it is disposed after each call
- var origin = GetOriginFromUri(uri);
-
- return HttpInvoker(origin, async () =>
- {
- var requestMessage = new HttpRequestMessage(method, uri);
-
- SetAuthorizationHeader(requestMessage);
-
- requestMessage.Content = new StringContent(JsonConvert.SerializeObject(item), System.Text.Encoding.UTF8, "application/json");
-
- if (authorizationToken != null)
- {
- requestMessage.Headers.Authorization = new AuthenticationHeaderValue(authorizationMethod, authorizationToken);
- }
-
- if (requestId != null)
- {
- requestMessage.Headers.Add("x-requestid", requestId);
- }
-
- var response = await _client.SendAsync(requestMessage);
-
- // raise exception if HttpResponseCode 500
- // needed for circuit breaker to track fails
-
- if (response.StatusCode == HttpStatusCode.InternalServerError)
- {
- throw new HttpRequestException();
- }
-
- return response;
- });
- }
-
- private async Task HttpInvoker(string origin, Func> action)
- {
- var normalizedOrigin = NormalizeOrigin(origin);
-
- if (!_policyWrappers.TryGetValue(normalizedOrigin, out PolicyWrap policyWrap))
- {
- policyWrap = Policy.WrapAsync(_policyCreator(normalizedOrigin).ToArray());
- _policyWrappers.TryAdd(normalizedOrigin, policyWrap);
- }
-
- // Executes the action applying all
- // the policies defined in the wrapper
- return await policyWrap.ExecuteAsync(action, new Context(normalizedOrigin));
- }
-
-
- private static string NormalizeOrigin(string origin)
- {
- return origin?.Trim()?.ToLower();
- }
-
- private static string GetOriginFromUri(string uri)
- {
- var url = new Uri(uri);
-
- var origin = $"{url.Scheme}://{url.DnsSafeHost}:{url.Port}";
-
- return origin;
- }
-
- private void SetAuthorizationHeader(HttpRequestMessage requestMessage)
- {
- var authorizationHeader = _httpContextAccessor.HttpContext.Request.Headers["Authorization"];
- if (!string.IsNullOrEmpty(authorizationHeader))
- {
- requestMessage.Headers.Add("Authorization", new List() { authorizationHeader });
- }
- }
- }
-}
diff --git a/src/BuildingBlocks/Resilience/Resilience.Http/StandardHttpClient.cs b/src/BuildingBlocks/Resilience/Resilience.Http/StandardHttpClient.cs
deleted file mode 100644
index 578168bff..000000000
--- a/src/BuildingBlocks/Resilience/Resilience.Http/StandardHttpClient.cs
+++ /dev/null
@@ -1,125 +0,0 @@
-using Microsoft.AspNetCore.Http;
-using Microsoft.Extensions.Logging;
-using Newtonsoft.Json;
-using System;
-using System.Collections.Generic;
-using System.Net;
-using System.Net.Http;
-using System.Net.Http.Headers;
-using System.Threading.Tasks;
-
-namespace Microsoft.eShopOnContainers.BuildingBlocks.Resilience.Http
-{
- public class StandardHttpClient : IHttpClient
- {
- private HttpClient _client;
- private ILogger _logger;
- private readonly IHttpContextAccessor _httpContextAccessor;
-
- public StandardHttpClient(ILogger logger, IHttpContextAccessor httpContextAccessor)
- {
- _client = new HttpClient();
- _logger = logger;
- _httpContextAccessor = httpContextAccessor;
- }
-
- public async Task GetStringAsync(string uri, string authorizationToken = null, string authorizationMethod = "Bearer")
- {
- var requestMessage = new HttpRequestMessage(HttpMethod.Get, uri);
-
- SetAuthorizationHeader(requestMessage);
-
- if (authorizationToken != null)
- {
- requestMessage.Headers.Authorization = new AuthenticationHeaderValue(authorizationMethod, authorizationToken);
- }
-
- var response = await _client.SendAsync(requestMessage);
-
- if (!response.IsSuccessStatusCode)
- {
- return null;
- }
-
- return await response.Content.ReadAsStringAsync();
- }
-
- private async Task DoPostPutAsync(HttpMethod method, string uri, T item, string authorizationToken = null, string requestId = null, string authorizationMethod = "Bearer")
- {
- if (method != HttpMethod.Post && method != HttpMethod.Put)
- {
- throw new ArgumentException("Value must be either post or put.", nameof(method));
- }
-
- // a new StringContent must be created for each retry
- // as it is disposed after each call
-
- var requestMessage = new HttpRequestMessage(method, uri);
-
- SetAuthorizationHeader(requestMessage);
-
- requestMessage.Content = new StringContent(JsonConvert.SerializeObject(item), System.Text.Encoding.UTF8, "application/json");
-
- if (authorizationToken != null)
- {
- requestMessage.Headers.Authorization = new AuthenticationHeaderValue(authorizationMethod, authorizationToken);
- }
-
- if (requestId != null)
- {
- requestMessage.Headers.Add("x-requestid", requestId);
- }
-
- var response = await _client.SendAsync(requestMessage);
-
- // raise exception if HttpResponseCode 500
- // needed for circuit breaker to track fails
-
- if (response.StatusCode == HttpStatusCode.InternalServerError)
- {
- throw new HttpRequestException();
- }
-
- return response;
- }
-
-
- public async Task PostAsync(string uri, T item, string authorizationToken = null, string requestId = null, string authorizationMethod = "Bearer")
- {
- return await DoPostPutAsync(HttpMethod.Post, uri, item, authorizationToken, requestId, authorizationMethod);
- }
-
- public async Task PutAsync(string uri, T item, string authorizationToken = null, string requestId = null, string authorizationMethod = "Bearer")
- {
- return await DoPostPutAsync(HttpMethod.Put, uri, item, authorizationToken, requestId, authorizationMethod);
- }
- public async Task DeleteAsync(string uri, string authorizationToken = null, string requestId = null, string authorizationMethod = "Bearer")
- {
- var requestMessage = new HttpRequestMessage(HttpMethod.Delete, uri);
-
- SetAuthorizationHeader(requestMessage);
-
- if (authorizationToken != null)
- {
- requestMessage.Headers.Authorization = new AuthenticationHeaderValue(authorizationMethod, authorizationToken);
- }
-
- if (requestId != null)
- {
- requestMessage.Headers.Add("x-requestid", requestId);
- }
-
- return await _client.SendAsync(requestMessage);
- }
-
- private void SetAuthorizationHeader(HttpRequestMessage requestMessage)
- {
- var authorizationHeader = _httpContextAccessor.HttpContext.Request.Headers["Authorization"];
- if (!string.IsNullOrEmpty(authorizationHeader))
- {
- requestMessage.Headers.Add("Authorization", new List() { authorizationHeader });
- }
- }
- }
-}
-
diff --git a/src/BuildingBlocks/WebHostCustomization/WebHost.Customization/WebHost.Customization.csproj b/src/BuildingBlocks/WebHostCustomization/WebHost.Customization/WebHost.Customization.csproj
index 6a6632379..ad891e6bd 100644
--- a/src/BuildingBlocks/WebHostCustomization/WebHost.Customization/WebHost.Customization.csproj
+++ b/src/BuildingBlocks/WebHostCustomization/WebHost.Customization/WebHost.Customization.csproj
@@ -1,12 +1,12 @@
-
+
- netcoreapp2.0
+ netcoreapp2.1
-
-
+
+
diff --git a/src/BuildingBlocks/WebHostCustomization/WebHost.Customization/WebHostExtensions.cs b/src/BuildingBlocks/WebHostCustomization/WebHost.Customization/WebHostExtensions.cs
index 858506e46..ef80f77cf 100644
--- a/src/BuildingBlocks/WebHostCustomization/WebHost.Customization/WebHostExtensions.cs
+++ b/src/BuildingBlocks/WebHostCustomization/WebHost.Customization/WebHostExtensions.cs
@@ -27,9 +27,9 @@ namespace Microsoft.AspNetCore.Hosting
var retry = Policy.Handle()
.WaitAndRetry(new TimeSpan[]
{
+ TimeSpan.FromSeconds(3),
TimeSpan.FromSeconds(5),
- TimeSpan.FromSeconds(10),
- TimeSpan.FromSeconds(15),
+ TimeSpan.FromSeconds(8),
});
retry.Execute(() =>
diff --git a/src/Services/Basket/Basket.API/Basket.API.csproj b/src/Services/Basket/Basket.API/Basket.API.csproj
index 3bc5cee4c..cea7bbedb 100644
--- a/src/Services/Basket/Basket.API/Basket.API.csproj
+++ b/src/Services/Basket/Basket.API/Basket.API.csproj
@@ -1,7 +1,7 @@
- netcoreapp2.0
+ netcoreapp2.1
$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;
..\..\..\..\docker-compose.dcproj
@@ -14,12 +14,14 @@
-
-
-
-
+
+
+
+
-
+
+
+
diff --git a/src/Services/Basket/Basket.API/Controllers/BasketController.cs b/src/Services/Basket/Basket.API/Controllers/BasketController.cs
index b6dd5a4b0..ccb81d25f 100644
--- a/src/Services/Basket/Basket.API/Controllers/BasketController.cs
+++ b/src/Services/Basket/Basket.API/Controllers/BasketController.cs
@@ -36,7 +36,7 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API.Controllers
var basket = await _repository.GetBasketAsync(id);
if (basket == null)
{
- return NotFound();
+ return Ok(new CustomerBasket(id) { });
}
return Ok(basket);
diff --git a/src/Services/Basket/Basket.API/Dockerfile b/src/Services/Basket/Basket.API/Dockerfile
index 03a967a72..7027cfc2d 100644
--- a/src/Services/Basket/Basket.API/Dockerfile
+++ b/src/Services/Basket/Basket.API/Dockerfile
@@ -1,12 +1,12 @@
-FROM microsoft/aspnetcore:2.0.5 AS base
+FROM microsoft/dotnet:2.1-aspnetcore-runtime AS base
WORKDIR /app
EXPOSE 80
-FROM microsoft/aspnetcore-build:2.0.5-2.1.4 AS build
+FROM microsoft/dotnet:2.1-sdk AS build
WORKDIR /src
COPY . .
-RUN dotnet restore -nowarn:msb3202,nu1503
WORKDIR /src/src/Services/Basket/Basket.API
+RUN dotnet restore -nowarn:msb3202,nu1503
RUN dotnet build --no-restore -c Release -o /app
FROM build AS publish
diff --git a/src/Services/Catalog/Catalog.API/Catalog.API.csproj b/src/Services/Catalog/Catalog.API/Catalog.API.csproj
index ad36cf3b7..c654c510e 100644
--- a/src/Services/Catalog/Catalog.API/Catalog.API.csproj
+++ b/src/Services/Catalog/Catalog.API/Catalog.API.csproj
@@ -1,7 +1,7 @@
- netcoreapp2.0
+ netcoreapp2.1
portable
true
Catalog.API
@@ -36,18 +36,15 @@
-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
diff --git a/src/Services/Catalog/Catalog.API/Controllers/CatalogController.cs b/src/Services/Catalog/Catalog.API/Controllers/CatalogController.cs
index 71f700762..20d1b1215 100644
--- a/src/Services/Catalog/Catalog.API/Controllers/CatalogController.cs
+++ b/src/Services/Catalog/Catalog.API/Controllers/CatalogController.cs
@@ -15,6 +15,7 @@ using System.Threading.Tasks;
namespace Microsoft.eShopOnContainers.Services.Catalog.API.Controllers
{
[Route("api/v1/[controller]")]
+ [ApiController]
public class CatalogController : ControllerBase
{
private readonly CatalogContext _catalogContext;
@@ -25,8 +26,8 @@ namespace Microsoft.eShopOnContainers.Services.Catalog.API.Controllers
{
_catalogContext = context ?? throw new ArgumentNullException(nameof(context));
_catalogIntegrationEventService = catalogIntegrationEventService ?? throw new ArgumentNullException(nameof(catalogIntegrationEventService));
-
_settings = settings.Value;
+
((DbContext)context).ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
}
diff --git a/src/Services/Catalog/Catalog.API/Controllers/PicController.cs b/src/Services/Catalog/Catalog.API/Controllers/PicController.cs
index f8e986e50..c7af86eed 100644
--- a/src/Services/Catalog/Catalog.API/Controllers/PicController.cs
+++ b/src/Services/Catalog/Catalog.API/Controllers/PicController.cs
@@ -9,7 +9,7 @@ using System.Threading.Tasks;
// For more information on enabling MVC for empty projects, visit http://go.microsoft.com/fwlink/?LinkID=397860
namespace Microsoft.eShopOnContainers.Services.Catalog.API.Controllers
-{
+{
public class PicController : Controller
{
private readonly IHostingEnvironment _env;
diff --git a/src/Services/Catalog/Catalog.API/Dockerfile b/src/Services/Catalog/Catalog.API/Dockerfile
index a1279db8c..4cbc9c8aa 100644
--- a/src/Services/Catalog/Catalog.API/Dockerfile
+++ b/src/Services/Catalog/Catalog.API/Dockerfile
@@ -1,12 +1,12 @@
-FROM microsoft/aspnetcore:2.0.5 AS base
+FROM microsoft/dotnet:2.1-aspnetcore-runtime AS base
WORKDIR /app
EXPOSE 80
-FROM microsoft/aspnetcore-build:2.0.5-2.1.4 AS build
+FROM microsoft/dotnet:2.1-sdk AS build
WORKDIR /src
COPY . .
-RUN dotnet restore -nowarn:msb3202,nu1503
WORKDIR /src/src/Services/Catalog/Catalog.API
+RUN dotnet restore -nowarn:msb3202,nu1503
RUN dotnet build --no-restore -c Release -o /app
FROM build AS publish
diff --git a/src/Services/Catalog/Catalog.API/Infrastructure/Filters/HttpGlobalExceptionFilter.cs b/src/Services/Catalog/Catalog.API/Infrastructure/Filters/HttpGlobalExceptionFilter.cs
index 41d3f08e1..4c4c746a6 100644
--- a/src/Services/Catalog/Catalog.API/Infrastructure/Filters/HttpGlobalExceptionFilter.cs
+++ b/src/Services/Catalog/Catalog.API/Infrastructure/Filters/HttpGlobalExceptionFilter.cs
@@ -1,6 +1,7 @@
using Catalog.API.Infrastructure.ActionResults;
using Catalog.API.Infrastructure.Exceptions;
using Microsoft.AspNetCore.Hosting;
+using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Logging;
@@ -27,12 +28,16 @@ namespace Catalog.API.Infrastructure.Filters
if (context.Exception.GetType() == typeof(CatalogDomainException))
{
- var json = new JsonErrorResponse
+ var problemDetails = new ValidationProblemDetails()
{
- Messages = new[] { context.Exception.Message }
+ Instance = context.HttpContext.Request.Path,
+ Status = StatusCodes.Status400BadRequest,
+ Detail = "Please refer to the errors property for additional details."
};
- context.Result = new BadRequestObjectResult(json);
+ problemDetails.Errors.Add("DomainValidations", new string[] { context.Exception.Message.ToString() });
+
+ context.Result = new BadRequestObjectResult(problemDetails);
context.HttpContext.Response.StatusCode = (int)HttpStatusCode.BadRequest;
}
else
diff --git a/src/Services/Catalog/Catalog.API/Startup.cs b/src/Services/Catalog/Catalog.API/Startup.cs
index 5eec48959..408f870af 100644
--- a/src/Services/Catalog/Catalog.API/Startup.cs
+++ b/src/Services/Catalog/Catalog.API/Startup.cs
@@ -1,35 +1,37 @@
-namespace Microsoft.eShopOnContainers.Services.Catalog.API
-{
- using Autofac;
- using Autofac.Extensions.DependencyInjection;
- using global::Catalog.API.Infrastructure.Filters;
- using global::Catalog.API.IntegrationEvents;
- using Microsoft.ApplicationInsights.Extensibility;
- using Microsoft.ApplicationInsights.ServiceFabric;
- using Microsoft.AspNetCore.Builder;
- using Microsoft.AspNetCore.Hosting;
- using Microsoft.Azure.ServiceBus;
- using Microsoft.EntityFrameworkCore;
- using Microsoft.EntityFrameworkCore.Diagnostics;
- using Microsoft.eShopOnContainers.BuildingBlocks.EventBus;
- using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions;
- using Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ;
- using Microsoft.eShopOnContainers.BuildingBlocks.EventBusServiceBus;
- using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF;
- using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF.Services;
- using Microsoft.eShopOnContainers.Services.Catalog.API.Infrastructure;
- using Microsoft.eShopOnContainers.Services.Catalog.API.IntegrationEvents.EventHandling;
- using Microsoft.eShopOnContainers.Services.Catalog.API.IntegrationEvents.Events;
- using Microsoft.Extensions.Configuration;
- using Microsoft.Extensions.DependencyInjection;
- using Microsoft.Extensions.HealthChecks;
- using Microsoft.Extensions.Logging;
- using Microsoft.Extensions.Options;
- using RabbitMQ.Client;
- using System;
- using System.Data.Common;
- using System.Reflection;
+using Autofac;
+using Autofac.Extensions.DependencyInjection;
+using global::Catalog.API.Infrastructure.Filters;
+using global::Catalog.API.IntegrationEvents;
+using Microsoft.ApplicationInsights.Extensibility;
+using Microsoft.ApplicationInsights.ServiceFabric;
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.Azure.ServiceBus;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Diagnostics;
+using Microsoft.eShopOnContainers.BuildingBlocks.EventBus;
+using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions;
+using Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ;
+using Microsoft.eShopOnContainers.BuildingBlocks.EventBusServiceBus;
+using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF;
+using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF.Services;
+using Microsoft.eShopOnContainers.Services.Catalog.API.Infrastructure;
+using Microsoft.eShopOnContainers.Services.Catalog.API.IntegrationEvents.EventHandling;
+using Microsoft.eShopOnContainers.Services.Catalog.API.IntegrationEvents.Events;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.HealthChecks;
+using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Options;
+using RabbitMQ.Client;
+using System;
+using System.Data.Common;
+using System.Reflection;
+namespace Microsoft.eShopOnContainers.Services.Catalog.API
+{
public class Startup
{
public Startup(IConfiguration configuration)
@@ -41,21 +43,95 @@
public IServiceProvider ConfigureServices(IServiceCollection services)
{
- // Add framework services.
+ services.AddAppInsight(Configuration)
+ .AddCustomMVC(Configuration)
+ .AddCustomDbContext(Configuration)
+ .AddCustomOptions(Configuration)
+ .AddIntegrationServices(Configuration)
+ .AddEventBus(Configuration)
+ .AddSwagger();
- RegisterAppInsights(services);
+ var container = new ContainerBuilder();
+ container.Populate(services);
+ return new AutofacServiceProvider(container.Build());
+ }
+
+ public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
+ {
+ //Configure logs
+
+ loggerFactory.AddAzureWebAppDiagnostics();
+ loggerFactory.AddApplicationInsights(app.ApplicationServices, LogLevel.Trace);
+
+ var 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
+ 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
+
+ app.UseCors("CorsPolicy");
+
+ app.UseMvcWithDefaultRoute();
+
+ app.UseSwagger()
+ .UseSwaggerUI(c =>
+ {
+ c.SwaggerEndpoint($"{ (!string.IsNullOrEmpty(pathBase) ? pathBase : string.Empty) }/swagger/v1/swagger.json", "Catalog.API V1");
+ });
+
+ ConfigureEventBus(app);
+ }
+
+ protected virtual void ConfigureEventBus(IApplicationBuilder app)
+ {
+ var eventBus = app.ApplicationServices.GetRequiredService();
+ eventBus.Subscribe();
+ eventBus.Subscribe();
+ }
+ }
+
+ public static class CustomExtensionMethods
+ {
+ public static IServiceCollection AddAppInsight(this IServiceCollection services, IConfiguration configuration)
+ {
+ services.AddApplicationInsightsTelemetry(configuration);
+ var orchestratorType = configuration.GetValue("OrchestratorType");
+
+ if (orchestratorType?.ToUpper() == "K8S")
+ {
+ // Enable K8s telemetry initializer
+ services.EnableKubernetes();
+ }
+ if (orchestratorType?.ToUpper() == "SF")
+ {
+ // Enable SF telemetry initializer
+ services.AddSingleton((serviceProvider) =>
+ new FabricTelemetryInitializer());
+ }
+
+ return services;
+ }
+
+ public static IServiceCollection AddCustomMVC(this IServiceCollection services, IConfiguration configuration)
+ {
services.AddHealthChecks(checks =>
{
var minutes = 1;
- if (int.TryParse(Configuration["HealthCheck:Timeout"], out var minutesParsed))
+ if (int.TryParse(configuration["HealthCheck:Timeout"], out var minutesParsed))
{
minutes = minutesParsed;
}
- checks.AddSqlCheck("CatalogDb", Configuration["ConnectionString"], TimeSpan.FromMinutes(minutes));
+ checks.AddSqlCheck("CatalogDb", configuration["ConnectionString"], TimeSpan.FromMinutes(minutes));
- var accountName = Configuration.GetValue("AzureStorageAccountName");
- var accountKey = Configuration.GetValue("AzureStorageAccountKey");
+ var accountName = configuration.GetValue("AzureStorageAccountName");
+ var accountKey = configuration.GetValue("AzureStorageAccountKey");
if (!string.IsNullOrEmpty(accountName) && !string.IsNullOrEmpty(accountKey))
{
checks.AddAzureBlobStorageCheck(accountName, accountKey);
@@ -67,9 +143,23 @@
options.Filters.Add(typeof(HttpGlobalExceptionFilter));
}).AddControllersAsServices();
+ services.AddCors(options =>
+ {
+ options.AddPolicy("CorsPolicy",
+ builder => builder.AllowAnyOrigin()
+ .AllowAnyMethod()
+ .AllowAnyHeader()
+ .AllowCredentials());
+ });
+
+ return services;
+ }
+
+ public static IServiceCollection AddCustomDbContext(this IServiceCollection services, IConfiguration configuration)
+ {
services.AddDbContext(options =>
{
- options.UseSqlServer(Configuration["ConnectionString"],
+ options.UseSqlServer(configuration["ConnectionString"],
sqlServerOptionsAction: sqlOptions =>
{
sqlOptions.MigrationsAssembly(typeof(Startup).GetTypeInfo().Assembly.GetName().Name);
@@ -85,7 +175,7 @@
services.AddDbContext(options =>
{
- options.UseSqlServer(Configuration["ConnectionString"],
+ options.UseSqlServer(configuration["ConnectionString"],
sqlServerOptionsAction: sqlOptions =>
{
sqlOptions.MigrationsAssembly(typeof(Startup).GetTypeInfo().Assembly.GetName().Name);
@@ -94,9 +184,35 @@
});
});
- services.Configure(Configuration);
+ return services;
+ }
- // Add framework services.
+ public static IServiceCollection AddCustomOptions(this IServiceCollection services, IConfiguration configuration)
+ {
+ services.Configure(configuration);
+ services.Configure(options =>
+ {
+ options.InvalidModelStateResponseFactory = context =>
+ {
+ var problemDetails = new ValidationProblemDetails(context.ModelState)
+ {
+ Instance = context.HttpContext.Request.Path,
+ Status = StatusCodes.Status400BadRequest,
+ Detail = "Please refer to the errors property for additional details."
+ };
+
+ return new BadRequestObjectResult(problemDetails)
+ {
+ ContentTypes = { "application/problem+json", "application/problem+xml" }
+ };
+ };
+ });
+
+ return services;
+ }
+
+ public static IServiceCollection AddSwagger(this IServiceCollection services)
+ {
services.AddSwaggerGen(options =>
{
options.DescribeAllEnumsAsStrings();
@@ -109,21 +225,18 @@
});
});
- services.AddCors(options =>
- {
- options.AddPolicy("CorsPolicy",
- builder => builder.AllowAnyOrigin()
- .AllowAnyMethod()
- .AllowAnyHeader()
- .AllowCredentials());
- });
+ return services;
+ }
+
+ public static IServiceCollection AddIntegrationServices(this IServiceCollection services, IConfiguration configuration)
+ {
services.AddTransient>(
- sp => (DbConnection c) => new IntegrationEventLogService(c));
+ sp => (DbConnection c) => new IntegrationEventLogService(c));
services.AddTransient();
- if (Configuration.GetValue("AzureServiceBusEnabled"))
+ if (configuration.GetValue("AzureServiceBusEnabled"))
{
services.AddSingleton(sp =>
{
@@ -144,93 +257,37 @@
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;
- 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);
});
}
- RegisterEventBus(services);
-
- var container = new ContainerBuilder();
- container.Populate(services);
- return new AutofacServiceProvider(container.Build());
-
+ return services;
}
- public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
+ public static IServiceCollection AddEventBus(this IServiceCollection services, IConfiguration configuration)
{
- //Configure logs
+ var subscriptionClientName = configuration["SubscriptionClientName"];
- loggerFactory.AddConsole(Configuration.GetSection("Logging"));
- loggerFactory.AddDebug();
- loggerFactory.AddAzureWebAppDiagnostics();
- loggerFactory.AddApplicationInsights(app.ApplicationServices, LogLevel.Trace);
-
- var 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
- 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
-
- app.UseCors("CorsPolicy");
-
- app.UseMvcWithDefaultRoute();
-
- app.UseSwagger()
- .UseSwaggerUI(c =>
- {
- c.SwaggerEndpoint($"{ (!string.IsNullOrEmpty(pathBase) ? pathBase : string.Empty) }/swagger/v1/swagger.json", "Catalog.API V1");
- });
-
- ConfigureEventBus(app);
- }
-
- private void RegisterAppInsights(IServiceCollection services)
- {
- services.AddApplicationInsightsTelemetry(Configuration);
- var orchestratorType = Configuration.GetValue("OrchestratorType");
-
- if (orchestratorType?.ToUpper() == "K8S")
- {
- // Enable K8s telemetry initializer
- services.EnableKubernetes();
- }
- if (orchestratorType?.ToUpper() == "SF")
- {
- // Enable SF telemetry initializer
- services.AddSingleton((serviceProvider) =>
- new FabricTelemetryInitializer());
- }
- }
-
- private void RegisterEventBus(IServiceCollection services)
- {
- var subscriptionClientName = Configuration["SubscriptionClientName"];
-
- if (Configuration.GetValue("AzureServiceBusEnabled"))
+ if (configuration.GetValue("AzureServiceBusEnabled"))
{
services.AddSingleton(sp =>
{
@@ -254,9 +311,9 @@
var eventBusSubcriptionsManager = sp.GetRequiredService();
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);
@@ -266,12 +323,8 @@
services.AddSingleton();
services.AddTransient();
services.AddTransient();
- }
- protected virtual void ConfigureEventBus(IApplicationBuilder app)
- {
- var eventBus = app.ApplicationServices.GetRequiredService();
- eventBus.Subscribe();
- eventBus.Subscribe();
+
+ return services;
}
}
}
diff --git a/src/Services/Identity/Identity.API/Dockerfile b/src/Services/Identity/Identity.API/Dockerfile
index ddc884cc2..167b2bb25 100644
--- a/src/Services/Identity/Identity.API/Dockerfile
+++ b/src/Services/Identity/Identity.API/Dockerfile
@@ -1,12 +1,26 @@
-FROM microsoft/aspnetcore:2.0.5 AS base
+FROM microsoft/dotnet:2.1-aspnetcore-runtime AS base
WORKDIR /app
EXPOSE 80
-FROM microsoft/aspnetcore-build:2.0.5-2.1.4 AS build
+FROM microsoft/dotnet:2.1-sdk AS sdk-with-node
+ENV NODE_VERSION 8.11.1
+ENV NODE_DOWNLOAD_SHA 0e20787e2eda4cc31336d8327556ebc7417e8ee0a6ba0de96a09b0ec2b841f60
+RUN curl -SL "https://nodejs.org/dist/v${NODE_VERSION}/node-v${NODE_VERSION}-linux-x64.tar.gz" --output nodejs.tar.gz \
+ && echo "$NODE_DOWNLOAD_SHA nodejs.tar.gz" | sha256sum -c - \
+ && tar -xzf "nodejs.tar.gz" -C /usr/local --strip-components=1 \
+ && rm nodejs.tar.gz \
+ && ln -s /usr/local/bin/node /usr/local/bin/nodejs
+
+FROM sdk-with-node AS updated-npm
+RUN npm i -g npm
+
+
+FROM updated-npm as build
+RUN npm install -g bower@1.8.4
WORKDIR /src
COPY . .
-RUN dotnet restore -nowarn:msb3202,nu1503
WORKDIR /src/src/Services/Identity/Identity.API
+RUN dotnet restore -nowarn:msb3202,nu1503
RUN dotnet build --no-restore -c Release -o /app
FROM build AS publish
diff --git a/src/Services/Identity/Identity.API/Identity.API.csproj b/src/Services/Identity/Identity.API/Identity.API.csproj
index 84a87a231..ca31685ab 100644
--- a/src/Services/Identity/Identity.API/Identity.API.csproj
+++ b/src/Services/Identity/Identity.API/Identity.API.csproj
@@ -1,8 +1,7 @@
- netcoreapp2.0
- 2.0.0
+ netcoreapp2.1
aspnet-eShopOnContainers.Identity-90487118-103c-4ff0-b9da-e5e26f7ab0c5
..\..\..\..\docker-compose.dcproj
@@ -16,14 +15,15 @@
-
-
-
-
+
+
+
+
+
-
-
+
+
@@ -32,10 +32,7 @@
-
-
-
-
+
diff --git a/src/Services/Location/Locations.API/Dockerfile b/src/Services/Location/Locations.API/Dockerfile
index e2b64ba2e..12ac0e442 100644
--- a/src/Services/Location/Locations.API/Dockerfile
+++ b/src/Services/Location/Locations.API/Dockerfile
@@ -1,12 +1,12 @@
-FROM microsoft/aspnetcore:2.0.5 AS base
+FROM microsoft/dotnet:2.1-aspnetcore-runtime AS base
WORKDIR /app
EXPOSE 80
-FROM microsoft/aspnetcore-build:2.0.5-2.1.4 AS build
+FROM microsoft/dotnet:2.1-sdk AS build
WORKDIR /src
COPY . .
-RUN dotnet restore -nowarn:msb3202,nu1503
WORKDIR /src/src/Services/Location/Locations.API
+RUN dotnet restore -nowarn:msb3202,nu1503
RUN dotnet build --no-restore -c Release -o /app
FROM build AS publish
diff --git a/src/Services/Location/Locations.API/Locations.API.csproj b/src/Services/Location/Locations.API/Locations.API.csproj
index aef0fe9e9..20dfbda7e 100644
--- a/src/Services/Location/Locations.API/Locations.API.csproj
+++ b/src/Services/Location/Locations.API/Locations.API.csproj
@@ -1,26 +1,24 @@
- netcoreapp2.0
+ netcoreapp2.1
..\..\..\..\docker-compose.dcproj
aspnet-Locations.API-20161122013619
-
-
-
-
+
+
+
+
+
-
-
-
-
-
+
+
diff --git a/src/Services/Marketing/Marketing.API/Dockerfile b/src/Services/Marketing/Marketing.API/Dockerfile
index b30986406..75d698bfe 100644
--- a/src/Services/Marketing/Marketing.API/Dockerfile
+++ b/src/Services/Marketing/Marketing.API/Dockerfile
@@ -1,12 +1,12 @@
-FROM microsoft/aspnetcore:2.0.5 AS base
+FROM microsoft/dotnet:2.1-aspnetcore-runtime AS base
WORKDIR /app
EXPOSE 80
-FROM microsoft/aspnetcore-build:2.0.5-2.1.4 AS build
+FROM microsoft/dotnet:2.1-sdk AS build
WORKDIR /src
COPY . .
-RUN dotnet restore -nowarn:msb3202,nu1503
WORKDIR /src/src/Services/Marketing/Marketing.API
+RUN dotnet restore -nowarn:msb3202,nu1503
RUN dotnet build --no-restore -c Release -o /app
FROM build AS publish
diff --git a/src/Services/Marketing/Marketing.API/Marketing.API.csproj b/src/Services/Marketing/Marketing.API/Marketing.API.csproj
index 36da8fceb..7db4320c5 100644
--- a/src/Services/Marketing/Marketing.API/Marketing.API.csproj
+++ b/src/Services/Marketing/Marketing.API/Marketing.API.csproj
@@ -1,7 +1,7 @@
- netcoreapp2.0
+ netcoreapp2.1
..\..\..\..\docker-compose.dcproj
Microsoft.eShopOnContainers.Services.Marketing.API
$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;
@@ -22,18 +22,16 @@
-
-
-
-
+
+
+
+
+
-
-
-
-
+
diff --git a/src/Services/Ordering/Ordering.API/Application/DomainEventHandlers/OrderCancelled/OrderCancelledDomainEventHandler.cs b/src/Services/Ordering/Ordering.API/Application/DomainEventHandlers/OrderCancelled/OrderCancelledDomainEventHandler.cs
index 24a8245d6..f8a7b06e5 100644
--- a/src/Services/Ordering/Ordering.API/Application/DomainEventHandlers/OrderCancelled/OrderCancelledDomainEventHandler.cs
+++ b/src/Services/Ordering/Ordering.API/Application/DomainEventHandlers/OrderCancelled/OrderCancelledDomainEventHandler.cs
@@ -28,6 +28,7 @@ namespace Ordering.API.Application.DomainEventHandlers.OrderCancelled
_orderRepository = orderRepository ?? throw new ArgumentNullException(nameof(orderRepository));
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
_buyerRepository = buyerRepository ?? throw new ArgumentNullException(nameof(buyerRepository));
+ _orderingIntegrationEventService = orderingIntegrationEventService;
}
public async Task Handle(OrderCancelledDomainEvent orderCancelledDomainEvent, CancellationToken cancellationToken)
diff --git a/src/Services/Ordering/Ordering.API/Application/Queries/IOrderQueries.cs b/src/Services/Ordering/Ordering.API/Application/Queries/IOrderQueries.cs
index 10aaf3415..89cf496e3 100644
--- a/src/Services/Ordering/Ordering.API/Application/Queries/IOrderQueries.cs
+++ b/src/Services/Ordering/Ordering.API/Application/Queries/IOrderQueries.cs
@@ -1,5 +1,6 @@
namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.Queries
{
+ using System;
using System.Collections.Generic;
using System.Threading.Tasks;
@@ -7,7 +8,7 @@
{
Task GetOrderAsync(int id);
- Task> GetOrdersAsync();
+ Task> GetOrdersFromUserAsync(Guid userId);
Task> GetCardTypesAsync();
}
diff --git a/src/Services/Ordering/Ordering.API/Application/Queries/OrderQueries.cs b/src/Services/Ordering/Ordering.API/Application/Queries/OrderQueries.cs
index 59cc8a823..8509e10d3 100644
--- a/src/Services/Ordering/Ordering.API/Application/Queries/OrderQueries.cs
+++ b/src/Services/Ordering/Ordering.API/Application/Queries/OrderQueries.cs
@@ -7,7 +7,7 @@
using System.Collections.Generic;
public class OrderQueries
- :IOrderQueries
+ : IOrderQueries
{
private string _connectionString = string.Empty;
@@ -42,18 +42,20 @@
}
}
- public async Task> GetOrdersAsync()
+ public async Task> GetOrdersFromUserAsync(Guid userId)
{
using (var connection = new SqlConnection(_connectionString))
{
connection.Open();
- return await connection.QueryAsync(@"SELECT o.[Id] as ordernumber,o.[OrderDate] as [date],os.[Name] as [status],SUM(oi.units*oi.unitprice) as total
+ return await connection.QueryAsync(@"SELECT o.[Id] as ordernumber,o.[OrderDate] as [date],os.[Name] as [status], SUM(oi.units*oi.unitprice) as total
FROM [ordering].[Orders] o
LEFT JOIN[ordering].[orderitems] oi ON o.Id = oi.orderid
LEFT JOIN[ordering].[orderstatus] os on o.OrderStatusId = os.Id
+ LEFT JOIN[ordering].[buyers] ob on o.BuyerId = ob.Id
+ WHERE ob.IdentityGuid = @userId
GROUP BY o.[Id], o.[OrderDate], os.[Name]
- ORDER BY o.[Id]");
+ ORDER BY o.[Id]", new { userId });
}
}
diff --git a/src/Services/Ordering/Ordering.API/Controllers/OrdersController.cs b/src/Services/Ordering/Ordering.API/Controllers/OrdersController.cs
index ac179c97f..5542caf11 100644
--- a/src/Services/Ordering/Ordering.API/Controllers/OrdersController.cs
+++ b/src/Services/Ordering/Ordering.API/Controllers/OrdersController.cs
@@ -5,7 +5,6 @@ using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands;
using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Queries;
using Microsoft.eShopOnContainers.Services.Ordering.API.Infrastructure.Services;
using Ordering.API.Application.Commands;
-using Ordering.API.Application.Models;
using System;
using System.Collections.Generic;
using System.Net;
@@ -15,6 +14,7 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.API.Controllers
{
[Route("api/v1/[controller]")]
[Authorize]
+ [ApiController]
public class OrdersController : Controller
{
private readonly IMediator _mediator;
@@ -87,8 +87,8 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.API.Controllers
[ProducesResponseType(typeof(IEnumerable), (int)HttpStatusCode.OK)]
public async Task GetOrders()
{
- var orders = await _orderQueries.GetOrdersAsync();
-
+ var userid = _identityService.GetUserIdentity();
+ var orders = await _orderQueries.GetOrdersFromUserAsync(Guid.Parse(userid));
return Ok(orders);
}
diff --git a/src/Services/Ordering/Ordering.API/Dockerfile b/src/Services/Ordering/Ordering.API/Dockerfile
index 6dc5f8122..78c153641 100644
--- a/src/Services/Ordering/Ordering.API/Dockerfile
+++ b/src/Services/Ordering/Ordering.API/Dockerfile
@@ -1,12 +1,12 @@
-FROM microsoft/aspnetcore:2.0.5 AS base
+FROM microsoft/dotnet:2.1-aspnetcore-runtime AS base
WORKDIR /app
EXPOSE 80
-FROM microsoft/aspnetcore-build:2.0.5-2.1.4 AS build
+FROM microsoft/dotnet:2.1-sdk AS build
WORKDIR /src
COPY . .
-RUN dotnet restore -nowarn:msb3202,nu1503
WORKDIR /src/src/Services/Ordering/Ordering.API
+RUN dotnet restore -nowarn:msb3202,nu1503
RUN dotnet build --no-restore -c Release -o /app
FROM build AS publish
diff --git a/src/Services/Ordering/Ordering.API/Infrastructure/Filters/HttpGlobalExceptionFilter.cs b/src/Services/Ordering/Ordering.API/Infrastructure/Filters/HttpGlobalExceptionFilter.cs
index 69faf8e42..a4ce415ea 100644
--- a/src/Services/Ordering/Ordering.API/Infrastructure/Filters/HttpGlobalExceptionFilter.cs
+++ b/src/Services/Ordering/Ordering.API/Infrastructure/Filters/HttpGlobalExceptionFilter.cs
@@ -3,6 +3,7 @@
using AspNetCore.Mvc;
using global::Ordering.Domain.Exceptions;
using Microsoft.AspNetCore.Hosting;
+ using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.eShopOnContainers.Services.Ordering.API.Infrastructure.ActionResults;
using Microsoft.Extensions.Logging;
@@ -25,16 +26,18 @@
context.Exception,
context.Exception.Message);
- if (context.Exception.GetType() == typeof(OrderingDomainException))
+ if (context.Exception.GetType() == typeof(OrderingDomainException))
{
- var json = new JsonErrorResponse
+ var problemDetails = new ValidationProblemDetails()
{
- Messages = new[] { context.Exception.Message }
+ Instance = context.HttpContext.Request.Path,
+ Status = StatusCodes.Status400BadRequest,
+ Detail = "Please refer to the errors property for additional details."
};
- // Result asigned to a result object but in destiny the response is empty. This is a known bug of .net core 1.1
- //It will be fixed in .net core 1.1.2. See https://github.com/aspnet/Mvc/issues/5594 for more information
- context.Result = new BadRequestObjectResult(json);
+ problemDetails.Errors.Add("DomainValidations", new string[] { context.Exception.Message.ToString() });
+
+ context.Result = new BadRequestObjectResult(problemDetails);
context.HttpContext.Response.StatusCode = (int)HttpStatusCode.BadRequest;
}
else
@@ -52,7 +55,7 @@
// Result asigned to a result object but in destiny the response is empty. This is a known bug of .net core 1.1
// It will be fixed in .net core 1.1.2. See https://github.com/aspnet/Mvc/issues/5594 for more information
context.Result = new InternalServerErrorObjectResult(json);
- context.HttpContext.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
+ context.HttpContext.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
}
context.ExceptionHandled = true;
}
diff --git a/src/Services/Ordering/Ordering.API/Ordering.API.csproj b/src/Services/Ordering/Ordering.API/Ordering.API.csproj
index c95cff6e1..8576e3cc8 100644
--- a/src/Services/Ordering/Ordering.API/Ordering.API.csproj
+++ b/src/Services/Ordering/Ordering.API/Ordering.API.csproj
@@ -1,7 +1,7 @@
- netcoreapp2.0
+ netcoreapp2.1
aspnet-Ordering.API-20161122013547
$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;
..\..\..\..\docker-compose.dcproj
@@ -31,25 +31,21 @@
-
+
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
+
+
-
-
-
-
-
PreserveNewest
diff --git a/src/Services/Ordering/Ordering.API/OrderingSettings.cs b/src/Services/Ordering/Ordering.API/OrderingSettings.cs
index bfe4d0793..af38823ae 100644
--- a/src/Services/Ordering/Ordering.API/OrderingSettings.cs
+++ b/src/Services/Ordering/Ordering.API/OrderingSettings.cs
@@ -7,8 +7,6 @@
public string EventBusConnection { get; set; }
- public int GracePeriodTime { get; set; }
-
public int CheckUpdateTime { get; set; }
}
}
diff --git a/src/Services/Ordering/Ordering.API/Startup.cs b/src/Services/Ordering/Ordering.API/Startup.cs
index 2948a3997..42567641a 100644
--- a/src/Services/Ordering/Ordering.API/Startup.cs
+++ b/src/Services/Ordering/Ordering.API/Startup.cs
@@ -15,6 +15,7 @@
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
+ using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.ServiceBus;
using Microsoft.EntityFrameworkCore;
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus;
@@ -47,144 +48,15 @@
public IServiceProvider ConfigureServices(IServiceCollection services)
{
- RegisterAppInsights(services);
-
- // Add framework services.
- services.AddMvc(options =>
- {
- options.Filters.Add(typeof(HttpGlobalExceptionFilter));
- }).AddControllersAsServices(); //Injecting Controllers themselves thru DI
- //For further info see: http://docs.autofac.org/en/latest/integration/aspnetcore.html#controllers-as-services
-
- services.AddTransient();
-
- services.AddHealthChecks(checks =>
- {
- var minutes = 1;
- if (int.TryParse(Configuration["HealthCheck:Timeout"], out var minutesParsed))
- {
- minutes = minutesParsed;
- }
- checks.AddSqlCheck("OrderingDb", Configuration["ConnectionString"], TimeSpan.FromMinutes(minutes));
- });
-
- services.AddEntityFrameworkSqlServer()
- .AddDbContext(options =>
- {
- options.UseSqlServer(Configuration["ConnectionString"],
- sqlServerOptionsAction: sqlOptions =>
- {
- sqlOptions.MigrationsAssembly(typeof(Startup).GetTypeInfo().Assembly.GetName().Name);
- sqlOptions.EnableRetryOnFailure(maxRetryCount: 10, maxRetryDelay: TimeSpan.FromSeconds(30), errorNumbersToAdd: null);
- });
- },
- ServiceLifetime.Scoped //Showing explicitly that the DbContext is shared across the HTTP request scope (graph of objects started in the HTTP request)
- );
-
- services.AddDbContext(options =>
- {
- options.UseSqlServer(Configuration["ConnectionString"],
- sqlServerOptionsAction: sqlOptions =>
- {
- sqlOptions.MigrationsAssembly(typeof(Startup).GetTypeInfo().Assembly.GetName().Name);
- //Configuring Connection Resiliency: https://docs.microsoft.com/en-us/ef/core/miscellaneous/connection-resiliency
- sqlOptions.EnableRetryOnFailure(maxRetryCount: 10, maxRetryDelay: TimeSpan.FromSeconds(30), errorNumbersToAdd: null);
- });
- });
-
-
- services.Configure(Configuration);
-
- services.AddSwaggerGen(options =>
- {
- options.DescribeAllEnumsAsStrings();
- options.SwaggerDoc("v1", new Swashbuckle.AspNetCore.Swagger.Info
- {
- Title = "Ordering HTTP API",
- Version = "v1",
- Description = "The Ordering Service HTTP API",
- TermsOfService = "Terms Of Service"
- });
-
- options.AddSecurityDefinition("oauth2", new OAuth2Scheme
- {
- Type = "oauth2",
- Flow = "implicit",
- AuthorizationUrl = $"{Configuration.GetValue("IdentityUrlExternal")}/connect/authorize",
- TokenUrl = $"{Configuration.GetValue("IdentityUrlExternal")}/connect/token",
- Scopes = new Dictionary()
- {
- { "orders", "Ordering API" }
- }
- });
-
- options.OperationFilter();
- });
-
- services.AddCors(options =>
- {
- options.AddPolicy("CorsPolicy",
- builder => builder.AllowAnyOrigin()
- .AllowAnyMethod()
- .AllowAnyHeader()
- .AllowCredentials());
- });
-
- // Add application services.
- services.AddSingleton();
- services.AddTransient();
- services.AddTransient>(
- sp => (DbConnection c) => new IntegrationEventLogService(c));
-
- services.AddTransient();
-
- if (Configuration.GetValue("AzureServiceBusEnabled"))
- {
- services.AddSingleton(sp =>
- {
- var logger = sp.GetRequiredService>();
-
- var serviceBusConnectionString = Configuration["EventBusConnection"];
- var serviceBusConnection = new ServiceBusConnectionStringBuilder(serviceBusConnectionString);
-
- return new DefaultServiceBusPersisterConnection(serviceBusConnection, logger);
- });
- }
- else
- {
- services.AddSingleton(sp =>
- {
- var logger = sp.GetRequiredService>();
-
-
- var factory = new ConnectionFactory()
- {
- HostName = Configuration["EventBusConnection"]
- };
-
- if (!string.IsNullOrEmpty(Configuration["EventBusUserName"]))
- {
- factory.UserName = Configuration["EventBusUserName"];
- }
-
- if (!string.IsNullOrEmpty(Configuration["EventBusPassword"]))
- {
- factory.Password = Configuration["EventBusPassword"];
- }
-
- var retryCount = 5;
- if (!string.IsNullOrEmpty(Configuration["EventBusRetryCount"]))
- {
- retryCount = int.Parse(Configuration["EventBusRetryCount"]);
- }
-
- return new DefaultRabbitMQPersistentConnection(factory, logger, retryCount);
- });
- }
-
- RegisterEventBus(services);
- ConfigureAuthService(services);
- services.AddOptions();
+ services.AddApplicationInsights(Configuration)
+ .AddCustomMvc()
+ .AddHealthChecks(Configuration)
+ .AddCustomDbContext(Configuration)
+ .AddCustomSwagger(Configuration)
+ .AddCustomIntegrations(Configuration)
+ .AddCustomConfiguration(Configuration)
+ .AddEventBus(Configuration)
+ .AddCustomAuthentication(Configuration);
//configure autofac
@@ -200,8 +72,6 @@
public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory)
{
- loggerFactory.AddConsole(Configuration.GetSection("Logging"));
- loggerFactory.AddDebug();
loggerFactory.AddAzureWebAppDiagnostics();
loggerFactory.AddApplicationInsights(app.ApplicationServices, LogLevel.Trace);
@@ -219,7 +89,7 @@
app.UseCors("CorsPolicy");
ConfigureAuth(app);
-
+
app.UseMvcWithDefaultRoute();
app.UseSwagger()
@@ -233,23 +103,6 @@
ConfigureEventBus(app);
}
- private void RegisterAppInsights(IServiceCollection services)
- {
- services.AddApplicationInsightsTelemetry(Configuration);
- var orchestratorType = Configuration.GetValue("OrchestratorType");
-
- if (orchestratorType?.ToUpper() == "K8S")
- {
- // Enable K8s telemetry initializer
- services.EnableKubernetes();
- }
- if (orchestratorType?.ToUpper() == "SF")
- {
- // Enable SF telemetry initializer
- services.AddSingleton((serviceProvider) =>
- new FabricTelemetryInitializer());
- }
- }
private void ConfigureEventBus(IApplicationBuilder app)
{
@@ -263,25 +116,6 @@
eventBus.Subscribe>();
}
- private void ConfigureAuthService(IServiceCollection services)
- {
- // prevent from mapping "sub" claim to nameidentifier.
- JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Remove("sub");
-
- var identityUrl = Configuration.GetValue("IdentityUrl");
-
- services.AddAuthentication(options =>
- {
- options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
- options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
-
- }).AddJwtBearer(options =>
- {
- options.Authority = identityUrl;
- options.RequireHttpsMetadata = false;
- options.Audience = "orders";
- });
- }
protected virtual void ConfigureAuth(IApplicationBuilder app)
{
@@ -292,19 +126,219 @@
app.UseAuthentication();
}
+ }
- private void RegisterEventBus(IServiceCollection services)
+ static class CustomExtensionsMethods
+ {
+ public static IServiceCollection AddApplicationInsights(this IServiceCollection services, IConfiguration configuration)
{
- var subscriptionClientName = Configuration["SubscriptionClientName"];
+ services.AddApplicationInsightsTelemetry(configuration);
+ var orchestratorType = configuration.GetValue("OrchestratorType");
- if (Configuration.GetValue("AzureServiceBusEnabled"))
+ if (orchestratorType?.ToUpper() == "K8S")
+ {
+ // Enable K8s telemetry initializer
+ services.EnableKubernetes();
+ }
+ if (orchestratorType?.ToUpper() == "SF")
+ {
+ // Enable SF telemetry initializer
+ services.AddSingleton((serviceProvider) =>
+ new FabricTelemetryInitializer());
+ }
+
+ return services;
+ }
+
+ public static IServiceCollection AddCustomMvc(this IServiceCollection services)
+ {
+ // Add framework services.
+ services.AddMvc(options =>
+ {
+ options.Filters.Add(typeof(HttpGlobalExceptionFilter));
+ }).AddControllersAsServices(); //Injecting Controllers themselves thru DI
+ //For further info see: http://docs.autofac.org/en/latest/integration/aspnetcore.html#controllers-as-services
+
+ services.AddCors(options =>
+ {
+ options.AddPolicy("CorsPolicy",
+ builder => builder.AllowAnyOrigin()
+ .AllowAnyMethod()
+ .AllowAnyHeader()
+ .AllowCredentials());
+ });
+
+ return services;
+ }
+
+ public static IServiceCollection AddHealthChecks(this IServiceCollection services, IConfiguration configuration)
+ {
+ services.AddHealthChecks(checks =>
+ {
+ var minutes = 1;
+ if (int.TryParse(configuration["HealthCheck:Timeout"], out var minutesParsed))
+ {
+ minutes = minutesParsed;
+ }
+ checks.AddSqlCheck("OrderingDb", configuration["ConnectionString"], TimeSpan.FromMinutes(minutes));
+ });
+
+ return services;
+ }
+
+ public static IServiceCollection AddCustomDbContext(this IServiceCollection services, IConfiguration configuration)
+ {
+ services.AddEntityFrameworkSqlServer()
+ .AddDbContext(options =>
+ {
+ options.UseSqlServer(configuration["ConnectionString"],
+ sqlServerOptionsAction: sqlOptions =>
+ {
+ sqlOptions.MigrationsAssembly(typeof(Startup).GetTypeInfo().Assembly.GetName().Name);
+ sqlOptions.EnableRetryOnFailure(maxRetryCount: 10, maxRetryDelay: TimeSpan.FromSeconds(30), errorNumbersToAdd: null);
+ });
+ },
+ ServiceLifetime.Scoped //Showing explicitly that the DbContext is shared across the HTTP request scope (graph of objects started in the HTTP request)
+ );
+
+ services.AddDbContext(options =>
+ {
+ options.UseSqlServer(configuration["ConnectionString"],
+ sqlServerOptionsAction: sqlOptions =>
+ {
+ sqlOptions.MigrationsAssembly(typeof(Startup).GetTypeInfo().Assembly.GetName().Name);
+ //Configuring Connection Resiliency: https://docs.microsoft.com/en-us/ef/core/miscellaneous/connection-resiliency
+ sqlOptions.EnableRetryOnFailure(maxRetryCount: 10, maxRetryDelay: TimeSpan.FromSeconds(30), errorNumbersToAdd: null);
+ });
+ });
+
+ return services;
+ }
+
+ public static IServiceCollection AddCustomSwagger(this IServiceCollection services, IConfiguration configuration)
+ {
+ services.AddSwaggerGen(options =>
+ {
+ options.DescribeAllEnumsAsStrings();
+ options.SwaggerDoc("v1", new Swashbuckle.AspNetCore.Swagger.Info
+ {
+ Title = "Ordering HTTP API",
+ Version = "v1",
+ Description = "The Ordering Service HTTP API",
+ TermsOfService = "Terms Of Service"
+ });
+
+ options.AddSecurityDefinition("oauth2", new OAuth2Scheme
+ {
+ Type = "oauth2",
+ Flow = "implicit",
+ AuthorizationUrl = $"{configuration.GetValue("IdentityUrlExternal")}/connect/authorize",
+ TokenUrl = $"{configuration.GetValue("IdentityUrlExternal")}/connect/token",
+ Scopes = new Dictionary()
+ {
+ { "orders", "Ordering API" }
+ }
+ });
+
+ options.OperationFilter();
+ });
+
+ return services;
+ }
+
+ public static IServiceCollection AddCustomIntegrations(this IServiceCollection services, IConfiguration configuration)
+ {
+ services.AddSingleton();
+ services.AddTransient();
+ services.AddTransient>(
+ sp => (DbConnection c) => new IntegrationEventLogService(c));
+
+ services.AddTransient();
+
+ if (configuration.GetValue("AzureServiceBusEnabled"))
+ {
+ services.AddSingleton(sp =>
+ {
+ var logger = sp.GetRequiredService>();
+
+ var serviceBusConnectionString = configuration["EventBusConnection"];
+ var serviceBusConnection = new ServiceBusConnectionStringBuilder(serviceBusConnectionString);
+
+ return new DefaultServiceBusPersisterConnection(serviceBusConnection, logger);
+ });
+ }
+ else
+ {
+ services.AddSingleton(sp =>
+ {
+ var logger = sp.GetRequiredService>();
+
+
+ var factory = new ConnectionFactory()
+ {
+ HostName = configuration["EventBusConnection"]
+ };
+
+ if (!string.IsNullOrEmpty(configuration["EventBusUserName"]))
+ {
+ factory.UserName = configuration["EventBusUserName"];
+ }
+
+ if (!string.IsNullOrEmpty(configuration["EventBusPassword"]))
+ {
+ factory.Password = configuration["EventBusPassword"];
+ }
+
+ var retryCount = 5;
+ if (!string.IsNullOrEmpty(configuration["EventBusRetryCount"]))
+ {
+ retryCount = int.Parse(configuration["EventBusRetryCount"]);
+ }
+
+ return new DefaultRabbitMQPersistentConnection(factory, logger, retryCount);
+ });
+ }
+
+ return services;
+ }
+
+ public static IServiceCollection AddCustomConfiguration(this IServiceCollection services, IConfiguration configuration)
+ {
+ services.AddOptions();
+ services.Configure(configuration);
+ services.Configure(options =>
+ {
+ options.InvalidModelStateResponseFactory = context =>
+ {
+ var problemDetails = new ValidationProblemDetails(context.ModelState)
+ {
+ Instance = context.HttpContext.Request.Path,
+ Status = StatusCodes.Status400BadRequest,
+ Detail = "Please refer to the errors property for additional details."
+ };
+
+ return new BadRequestObjectResult(problemDetails)
+ {
+ ContentTypes = { "application/problem+json", "application/problem+xml" }
+ };
+ };
+ });
+
+ return services;
+ }
+
+ public static IServiceCollection AddEventBus(this IServiceCollection services, IConfiguration configuration)
+ {
+ var subscriptionClientName = configuration["SubscriptionClientName"];
+
+ if (configuration.GetValue("AzureServiceBusEnabled"))
{
services.AddSingleton(sp =>
{
var serviceBusPersisterConnection = sp.GetRequiredService();
var iLifetimeScope = sp.GetRequiredService();
var logger = sp.GetRequiredService>();
- var eventBusSubcriptionsManager = sp.GetRequiredService();
+ var eventBusSubcriptionsManager = sp.GetRequiredService();
return new EventBusServiceBus(serviceBusPersisterConnection, logger,
eventBusSubcriptionsManager, subscriptionClientName, iLifetimeScope);
@@ -320,9 +354,9 @@
var eventBusSubcriptionsManager = sp.GetRequiredService();
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);
@@ -330,6 +364,30 @@
}
services.AddSingleton();
+
+ return services;
+ }
+
+ public static IServiceCollection AddCustomAuthentication(this IServiceCollection services, IConfiguration configuration)
+ {
+ // prevent from mapping "sub" claim to nameidentifier.
+ JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Remove("sub");
+
+ var identityUrl = configuration.GetValue("IdentityUrl");
+
+ services.AddAuthentication(options =>
+ {
+ options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
+ options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
+
+ }).AddJwtBearer(options =>
+ {
+ options.Authority = identityUrl;
+ options.RequireHttpsMetadata = false;
+ options.Audience = "orders";
+ });
+
+ return services;
}
}
}
diff --git a/src/Services/Ordering/Ordering.API/settings.json b/src/Services/Ordering/Ordering.API/settings.json
index 679cd23f4..ef9b9e03c 100644
--- a/src/Services/Ordering/Ordering.API/settings.json
+++ b/src/Services/Ordering/Ordering.API/settings.json
@@ -12,7 +12,6 @@
},
"AzureServiceBusEnabled": false,
"SubscriptionClientName": "Ordering",
- "GracePeriodTime": "1",
"CheckUpdateTime": "30000",
"ApplicationInsights": {
"InstrumentationKey": ""
diff --git a/src/Services/Ordering/Ordering.BackgroundTasks/Dockerfile b/src/Services/Ordering/Ordering.BackgroundTasks/Dockerfile
index a675d59ef..0c01dcb96 100644
--- a/src/Services/Ordering/Ordering.BackgroundTasks/Dockerfile
+++ b/src/Services/Ordering/Ordering.BackgroundTasks/Dockerfile
@@ -1,12 +1,12 @@
-FROM microsoft/aspnetcore:2.0.5 AS base
+FROM microsoft/dotnet:2.1-aspnetcore-runtime AS base
WORKDIR /app
EXPOSE 80
-FROM microsoft/aspnetcore-build:2.0.5-2.1.4 AS build
+FROM microsoft/dotnet:2.1-sdk AS build
WORKDIR /src
COPY . .
-RUN dotnet restore -nowarn:msb3202,nu1503
WORKDIR /src/src/Services/Ordering/Ordering.BackgroundTasks
+RUN dotnet restore -nowarn:msb3202,nu1503
RUN dotnet build --no-restore -c Release -o /app
FROM build AS publish
diff --git a/src/Services/Ordering/Ordering.BackgroundTasks/Ordering.BackgroundTasks.csproj b/src/Services/Ordering/Ordering.BackgroundTasks/Ordering.BackgroundTasks.csproj
index f2a7ad465..5ca8b4b3b 100644
--- a/src/Services/Ordering/Ordering.BackgroundTasks/Ordering.BackgroundTasks.csproj
+++ b/src/Services/Ordering/Ordering.BackgroundTasks/Ordering.BackgroundTasks.csproj
@@ -1,23 +1,22 @@
-
+
- netcoreapp2.0
+ netcoreapp2.1
$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;
..\..\..\..\docker-compose.dcproj
-
+
+
+
+
-
-
-
-
-
+
diff --git a/src/Services/Ordering/Ordering.BackgroundTasks/Startup.cs b/src/Services/Ordering/Ordering.BackgroundTasks/Startup.cs
index bb7ae0902..2bc085dbf 100644
--- a/src/Services/Ordering/Ordering.BackgroundTasks/Startup.cs
+++ b/src/Services/Ordering/Ordering.BackgroundTasks/Startup.cs
@@ -110,7 +110,7 @@ namespace Ordering.BackgroundTasks
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
- public void Configure(IApplicationBuilder app, IHostingEnvironment env)
+ public void Configure(IApplicationBuilder app, Microsoft.AspNetCore.Hosting.IHostingEnvironment env)
{
#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously
diff --git a/src/Services/Ordering/Ordering.Infrastructure/Ordering.Infrastructure.csproj b/src/Services/Ordering/Ordering.Infrastructure/Ordering.Infrastructure.csproj
index e4731db13..72cd00442 100644
--- a/src/Services/Ordering/Ordering.Infrastructure/Ordering.Infrastructure.csproj
+++ b/src/Services/Ordering/Ordering.Infrastructure/Ordering.Infrastructure.csproj
@@ -9,9 +9,9 @@
-
-
-
+
+
+
diff --git a/src/Services/Ordering/Ordering.SignalrHub/Dockerfile b/src/Services/Ordering/Ordering.SignalrHub/Dockerfile
index 005eea8cf..367b8db36 100644
--- a/src/Services/Ordering/Ordering.SignalrHub/Dockerfile
+++ b/src/Services/Ordering/Ordering.SignalrHub/Dockerfile
@@ -1,18 +1,16 @@
-FROM microsoft/aspnetcore:2.0 AS base
+FROM microsoft/dotnet:2.1-aspnetcore-runtime AS base
WORKDIR /app
EXPOSE 80
-FROM microsoft/aspnetcore-build:2.0 AS build
+FROM microsoft/dotnet:2.1-sdk AS build
WORKDIR /src
-COPY eShopOnContainers-ServicesAndWebApps.sln ./
-COPY src/Services/Ordering/Ordering.SignalrHub/Ordering.SignalrHub.csproj src/Services/Ordering/Ordering.SignalrHub/
-RUN dotnet restore -nowarn:msb3202,nu1503
COPY . .
WORKDIR /src/src/Services/Ordering/Ordering.SignalrHub
-RUN dotnet build Ordering.SignalrHub.csproj -c Release -o /app
+RUN dotnet restore -nowarn:msb3202,nu1503
+RUN dotnet build --no-restore Ordering.SignalrHub.csproj -c Release -o /app
FROM build AS publish
-RUN dotnet publish Ordering.SignalrHub.csproj -c Release -o /app
+RUN dotnet publish --no-restore Ordering.SignalrHub.csproj -c Release -o /app
FROM base AS final
WORKDIR /app
diff --git a/src/Services/Ordering/Ordering.SignalrHub/NotificationHub.cs b/src/Services/Ordering/Ordering.SignalrHub/NotificationHub.cs
index 8a4c1c90f..5fd6f3eb9 100644
--- a/src/Services/Ordering/Ordering.SignalrHub/NotificationHub.cs
+++ b/src/Services/Ordering/Ordering.SignalrHub/NotificationHub.cs
@@ -13,13 +13,13 @@ namespace Ordering.SignalrHub
public override async Task OnConnectedAsync()
{
- await Groups.AddAsync(Context.ConnectionId, Context.User.Identity.Name);
+ await Groups.AddToGroupAsync(Context.ConnectionId, Context.User.Identity.Name);
await base.OnConnectedAsync();
}
public override async Task OnDisconnectedAsync(Exception ex)
{
- await Groups.RemoveAsync(Context.ConnectionId, Context.User.Identity.Name);
+ await Groups.AddToGroupAsync(Context.ConnectionId, Context.User.Identity.Name);
await base.OnDisconnectedAsync(ex);
}
}
diff --git a/src/Services/Ordering/Ordering.SignalrHub/Ordering.SignalrHub.csproj b/src/Services/Ordering/Ordering.SignalrHub/Ordering.SignalrHub.csproj
index 8b8aa5832..fad53bbcf 100644
--- a/src/Services/Ordering/Ordering.SignalrHub/Ordering.SignalrHub.csproj
+++ b/src/Services/Ordering/Ordering.SignalrHub/Ordering.SignalrHub.csproj
@@ -1,7 +1,7 @@
-
+
- netcoreapp2.0
+ netcoreapp2.1
..\..\..\..\docker-compose.dcproj
@@ -11,10 +11,15 @@
-
-
-
-
+
+
+
+
+
+
+
+
+
diff --git a/src/Services/Ordering/Ordering.SignalrHub/Startup.cs b/src/Services/Ordering/Ordering.SignalrHub/Startup.cs
index b2bc2346a..25a8b22d9 100644
--- a/src/Services/Ordering/Ordering.SignalrHub/Startup.cs
+++ b/src/Services/Ordering/Ordering.SignalrHub/Startup.cs
@@ -134,7 +134,7 @@ namespace Ordering.SignalrHub
app.UseSignalR(routes =>
{
routes.MapHub("/notificationhub", options =>
- options.Transports = Microsoft.AspNetCore.Http.Connections.TransportType.All);
+ options.Transports = Microsoft.AspNetCore.Http.Connections.HttpTransports.All);
});
ConfigureEventBus(app);
diff --git a/src/Services/Payment/Payment.API/Dockerfile b/src/Services/Payment/Payment.API/Dockerfile
index 7b19579c1..d644417c6 100644
--- a/src/Services/Payment/Payment.API/Dockerfile
+++ b/src/Services/Payment/Payment.API/Dockerfile
@@ -1,12 +1,12 @@
-FROM microsoft/aspnetcore:2.0.5 AS base
+FROM microsoft/dotnet:2.1-aspnetcore-runtime AS base
WORKDIR /app
EXPOSE 80
-FROM microsoft/aspnetcore-build:2.0.5-2.1.4 AS build
+FROM microsoft/dotnet:2.1-sdk AS build
WORKDIR /src
COPY . .
-RUN dotnet restore -nowarn:msb3202,nu1503
WORKDIR /src/src/Services/Payment/Payment.API
+RUN dotnet restore -nowarn:msb3202,nu1503
RUN dotnet build --no-restore -c Release -o /app
FROM build AS publish
diff --git a/src/Services/Payment/Payment.API/Payment.API.csproj b/src/Services/Payment/Payment.API/Payment.API.csproj
index 278dcc6cb..061e5f237 100644
--- a/src/Services/Payment/Payment.API/Payment.API.csproj
+++ b/src/Services/Payment/Payment.API/Payment.API.csproj
@@ -1,7 +1,7 @@
- netcoreapp2.0
+ netcoreapp2.1
..\..\..\..\docker-compose.dcproj
$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;
@@ -9,13 +9,11 @@
-
-
-
-
-
-
-
+
+
+
+
+
diff --git a/src/Web/WebMVC/AppSettings.cs b/src/Web/WebMVC/AppSettings.cs
index 30403aa9d..a705c5a90 100644
--- a/src/Web/WebMVC/AppSettings.cs
+++ b/src/Web/WebMVC/AppSettings.cs
@@ -7,9 +7,8 @@ namespace Microsoft.eShopOnContainers.WebMVC
{
public class AppSettings
{
- public Connectionstrings ConnectionStrings { get; set; }
+ //public Connectionstrings ConnectionStrings { get; set; }
public string MarketingUrl { get; set; }
-
public string PurchaseUrl { get; set; }
public string SignalrHubUrl { get; set; }
public bool ActivateCampaignDetailFunction { get; set; }
diff --git a/src/Web/WebMVC/Controllers/CartController.cs b/src/Web/WebMVC/Controllers/CartController.cs
index 660da1d56..30ac77e8b 100644
--- a/src/Web/WebMVC/Controllers/CartController.cs
+++ b/src/Web/WebMVC/Controllers/CartController.cs
@@ -71,7 +71,6 @@ namespace Microsoft.eShopOnContainers.WebMVC.Controllers
{
var user = _appUserParser.Parse(HttpContext.User);
await _basketSvc.AddItemToBasket(user, productDetails.Id);
- //await _basketSvc.AddItemToBasket(user, product);
}
return RedirectToAction("Index", "Catalog");
}
diff --git a/src/Web/WebMVC/Controllers/OrderController.cs b/src/Web/WebMVC/Controllers/OrderController.cs
index a5bf4785e..cb5234e3c 100644
--- a/src/Web/WebMVC/Controllers/OrderController.cs
+++ b/src/Web/WebMVC/Controllers/OrderController.cs
@@ -1,14 +1,9 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading.Tasks;
+using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.eShopOnContainers.WebMVC.Services;
using Microsoft.eShopOnContainers.WebMVC.ViewModels;
-using Microsoft.AspNetCore.Authorization;
-using System.Net.Http;
using Polly.CircuitBreaker;
-using WebMVC.Models;
+using System.Threading.Tasks;
namespace Microsoft.eShopOnContainers.WebMVC.Controllers
{
@@ -52,11 +47,12 @@ namespace Microsoft.eShopOnContainers.WebMVC.Controllers
return RedirectToAction("Index");
}
}
- catch(BrokenCircuitException)
+ catch (BrokenCircuitException)
{
ModelState.AddModelError("Error", "It was not possible to create a new order, please try later on. (Business Msg Due to Circuit-Breaker)");
}
- return View("Create", model);
+
+ return View("Create", model);
}
public async Task Cancel(string orderId)
diff --git a/src/Web/WebMVC/Controllers/TestController.cs b/src/Web/WebMVC/Controllers/TestController.cs
index 1b35d5d2b..2cf053126 100644
--- a/src/Web/WebMVC/Controllers/TestController.cs
+++ b/src/Web/WebMVC/Controllers/TestController.cs
@@ -1,12 +1,9 @@
-using Microsoft.AspNetCore.Authentication;
-using Microsoft.AspNetCore.Authorization;
+using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
-using Microsoft.eShopOnContainers.BuildingBlocks.Resilience.Http;
using Microsoft.eShopOnContainers.WebMVC.Services;
using Microsoft.eShopOnContainers.WebMVC.ViewModels;
-using System;
-using System.Collections.Generic;
-using System.Linq;
+using Newtonsoft.Json;
+using System.Net.Http;
using System.Threading.Tasks;
namespace WebMVC.Controllers
@@ -14,6 +11,7 @@ namespace WebMVC.Controllers
class TestPayload
{
public int CatalogItemId { get; set; }
+
public string BasketId { get; set; }
public int Quantity { get; set; }
@@ -22,9 +20,10 @@ namespace WebMVC.Controllers
[Authorize]
public class TestController : Controller
{
- private readonly IHttpClient _client;
+ private readonly IHttpClientFactory _client;
private readonly IIdentityParser _appUserParser;
- public TestController(IHttpClient client, IIdentityParser identityParser)
+
+ public TestController(IHttpClientFactory client, IIdentityParser identityParser)
{
_client = client;
_appUserParser = identityParser;
@@ -33,18 +32,24 @@ namespace WebMVC.Controllers
public async Task Ocelot()
{
var url = "http://apigw/shopping/api/v1/basket/items";
+
var payload = new TestPayload()
{
CatalogItemId = 1,
Quantity = 1,
BasketId = _appUserParser.Parse(User).Id
};
- var token = await HttpContext.GetTokenAsync("access_token");
- var response = await _client.PostAsync(url, payload, token);
-
+
+ var content = new StringContent(JsonConvert.SerializeObject(payload), System.Text.Encoding.UTF8, "application/json");
+
+
+ var response = await _client.CreateClient(nameof(IBasketService))
+ .PostAsync(url, content);
+
if (response.IsSuccessStatusCode)
{
var str = await response.Content.ReadAsStringAsync();
+
return Ok(str);
}
else
diff --git a/src/Web/WebMVC/Dockerfile b/src/Web/WebMVC/Dockerfile
index a903387c8..bf104e83b 100644
--- a/src/Web/WebMVC/Dockerfile
+++ b/src/Web/WebMVC/Dockerfile
@@ -1,12 +1,25 @@
-FROM microsoft/aspnetcore:2.0.5 AS base
+FROM microsoft/dotnet:2.1-aspnetcore-runtime AS base
WORKDIR /app
EXPOSE 80
-FROM microsoft/aspnetcore-build:2.0.5-2.1.4 AS build
+FROM microsoft/dotnet:2.1-sdk AS sdk-with-node
+ENV NODE_VERSION 8.11.1
+ENV NODE_DOWNLOAD_SHA 0e20787e2eda4cc31336d8327556ebc7417e8ee0a6ba0de96a09b0ec2b841f60
+RUN curl -SL "https://nodejs.org/dist/v${NODE_VERSION}/node-v${NODE_VERSION}-linux-x64.tar.gz" --output nodejs.tar.gz \
+ && echo "$NODE_DOWNLOAD_SHA nodejs.tar.gz" | sha256sum -c - \
+ && tar -xzf "nodejs.tar.gz" -C /usr/local --strip-components=1 \
+ && rm nodejs.tar.gz \
+ && ln -s /usr/local/bin/node /usr/local/bin/nodejs
+
+FROM sdk-with-node AS updated-npm
+RUN npm i -g npm
+
+FROM updated-npm as build
+RUN npm install -g bower@1.8.4
WORKDIR /src
COPY . .
-RUN dotnet restore -nowarn:msb3202,nu1503
WORKDIR /src/src/Web/WebMVC
+RUN dotnet restore -nowarn:msb3202,nu1503
RUN dotnet build --no-restore -c Release -o /app
FROM build AS publish
diff --git a/src/Web/WebMVC/Infrastructure/HttpClientAuthorizationDelegatingHandler.cs b/src/Web/WebMVC/Infrastructure/HttpClientAuthorizationDelegatingHandler.cs
new file mode 100644
index 000000000..255bd1649
--- /dev/null
+++ b/src/Web/WebMVC/Infrastructure/HttpClientAuthorizationDelegatingHandler.cs
@@ -0,0 +1,49 @@
+using Microsoft.AspNetCore.Authentication;
+using Microsoft.AspNetCore.Http;
+using System.Collections.Generic;
+using System.Net.Http;
+using System.Net.Http.Headers;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace WebMVC.Infrastructure
+{
+ public class HttpClientAuthorizationDelegatingHandler
+ : DelegatingHandler
+ {
+ private readonly IHttpContextAccessor _httpContextAccesor;
+
+ public HttpClientAuthorizationDelegatingHandler(IHttpContextAccessor httpContextAccesor)
+ {
+ _httpContextAccesor = httpContextAccesor;
+ }
+
+ protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
+ {
+ var authorizationHeader = _httpContextAccesor.HttpContext
+ .Request.Headers["Authorization"];
+
+ if (!string.IsNullOrEmpty(authorizationHeader))
+ {
+ request.Headers.Add("Authorization", new List() { authorizationHeader });
+ }
+
+ var token = await GetToken();
+
+ if (token != null)
+ {
+ request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token);
+ }
+
+ return await base.SendAsync(request, cancellationToken);
+ }
+
+ async Task GetToken()
+ {
+ const string ACCESS_TOKEN = "access_token";
+
+ return await _httpContextAccesor.HttpContext
+ .GetTokenAsync(ACCESS_TOKEN);
+ }
+ }
+}
diff --git a/src/Web/WebMVC/Infrastructure/HttpClientRequestIdDelegatingHandler.cs b/src/Web/WebMVC/Infrastructure/HttpClientRequestIdDelegatingHandler.cs
new file mode 100644
index 000000000..17e4591a1
--- /dev/null
+++ b/src/Web/WebMVC/Infrastructure/HttpClientRequestIdDelegatingHandler.cs
@@ -0,0 +1,26 @@
+using System;
+using System.Net.Http;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace WebMVC.Infrastructure
+{
+ public class HttpClientRequestIdDelegatingHandler
+ : DelegatingHandler
+ {
+
+ public HttpClientRequestIdDelegatingHandler()
+ {
+ }
+
+ protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
+ {
+ if (request.Method == HttpMethod.Post || request.Method == HttpMethod.Put)
+ {
+ request.Headers.Add("x-requestid", Guid.NewGuid().ToString());
+ }
+
+ return await base.SendAsync(request, cancellationToken);
+ }
+ }
+}
diff --git a/src/Web/WebMVC/Infrastructure/IResilientHttpClientFactory.cs b/src/Web/WebMVC/Infrastructure/IResilientHttpClientFactory.cs
deleted file mode 100644
index aa1d31c9b..000000000
--- a/src/Web/WebMVC/Infrastructure/IResilientHttpClientFactory.cs
+++ /dev/null
@@ -1,10 +0,0 @@
-using Microsoft.eShopOnContainers.BuildingBlocks.Resilience.Http;
-using System;
-
-namespace Microsoft.eShopOnContainers.WebMVC.Infrastructure
-{
- public interface IResilientHttpClientFactory
- {
- ResilientHttpClient CreateResilientHttpClient();
- }
-}
\ No newline at end of file
diff --git a/src/Web/WebMVC/Infrastructure/ResilientHttpClientFactory.cs b/src/Web/WebMVC/Infrastructure/ResilientHttpClientFactory.cs
deleted file mode 100644
index 43eac7b30..000000000
--- a/src/Web/WebMVC/Infrastructure/ResilientHttpClientFactory.cs
+++ /dev/null
@@ -1,66 +0,0 @@
-using Microsoft.AspNetCore.Http;
-using Microsoft.eShopOnContainers.BuildingBlocks.Resilience.Http;
-using Microsoft.Extensions.Logging;
-using Polly;
-using System;
-using System.Net.Http;
-
-namespace Microsoft.eShopOnContainers.WebMVC.Infrastructure
-{
- public class ResilientHttpClientFactory : IResilientHttpClientFactory
- {
- private readonly ILogger _logger;
- private readonly int _retryCount;
- private readonly int _exceptionsAllowedBeforeBreaking;
- private readonly IHttpContextAccessor _httpContextAccessor;
-
- public ResilientHttpClientFactory(ILogger logger, IHttpContextAccessor httpContextAccessor, int exceptionsAllowedBeforeBreaking = 5, int retryCount = 6)
- {
- _logger = logger;
- _exceptionsAllowedBeforeBreaking = exceptionsAllowedBeforeBreaking;
- _retryCount = retryCount;
- _httpContextAccessor = httpContextAccessor;
- }
-
-
- public ResilientHttpClient CreateResilientHttpClient()
- => new ResilientHttpClient((origin) => CreatePolicies(), _logger, _httpContextAccessor);
-
- private Policy[] CreatePolicies()
- => new Policy[]
- {
- Policy.Handle()
- .WaitAndRetryAsync(
- // number of retries
- _retryCount,
- // exponential backofff
- retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)),
- // on retry
- (exception, timeSpan, retryCount, context) =>
- {
- var msg = $"Retry {retryCount} implemented with Polly's RetryPolicy " +
- $"of {context.PolicyKey} " +
- $"at {context.ExecutionKey}, " +
- $"due to: {exception}.";
- _logger.LogWarning(msg);
- _logger.LogDebug(msg);
- }),
- Policy.Handle()
- .CircuitBreakerAsync(
- // number of exceptions before breaking circuit
- _exceptionsAllowedBeforeBreaking,
- // time circuit opened before retry
- TimeSpan.FromMinutes(1),
- (exception, duration) =>
- {
- // on circuit opened
- _logger.LogTrace("Circuit breaker opened");
- },
- () =>
- {
- // on circuit closed
- _logger.LogTrace("Circuit breaker reset");
- })
- };
- }
-}
diff --git a/src/Web/WebMVC/Services/BasketService.cs b/src/Web/WebMVC/Services/BasketService.cs
index 54287a796..7dffd934b 100644
--- a/src/Web/WebMVC/Services/BasketService.cs
+++ b/src/Web/WebMVC/Services/BasketService.cs
@@ -1,11 +1,9 @@
-using Microsoft.AspNetCore.Authentication;
-using Microsoft.AspNetCore.Http;
-using Microsoft.eShopOnContainers.BuildingBlocks.Resilience.Http;
-using Microsoft.eShopOnContainers.WebMVC.ViewModels;
+using Microsoft.eShopOnContainers.WebMVC.ViewModels;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using System.Collections.Generic;
using System.Linq;
+using System.Net.Http;
using System.Threading.Tasks;
using WebMVC.Infrastructure;
using WebMVC.Models;
@@ -14,42 +12,40 @@ namespace Microsoft.eShopOnContainers.WebMVC.Services
{
public class BasketService : IBasketService
{
- private readonly IOptionsSnapshot _settings;
- private readonly IHttpClient _apiClient;
+ private readonly IOptions _settings;
+ private readonly HttpClient _apiClient;
private readonly string _basketByPassUrl;
private readonly string _purchaseUrl;
- private readonly IHttpContextAccessor _httpContextAccesor;
private readonly string _bffUrl;
- public BasketService(IOptionsSnapshot settings,
- IHttpContextAccessor httpContextAccesor, IHttpClient httpClient)
+ public BasketService(HttpClient httpClient, IOptions settings)
{
+ _apiClient = httpClient;
_settings = settings;
+
_basketByPassUrl = $"{_settings.Value.PurchaseUrl}/api/v1/b/basket";
_purchaseUrl = $"{_settings.Value.PurchaseUrl}/api/v1";
- _httpContextAccesor = httpContextAccesor;
- _apiClient = httpClient;
}
public async Task GetBasket(ApplicationUser user)
{
- var token = await GetUserTokenAsync();
- var getBasketUri = API.Basket.GetBasket(_basketByPassUrl, user.Id);
+ var uri = API.Basket.GetBasket(_basketByPassUrl, user.Id);
- var dataString = await _apiClient.GetStringAsync(getBasketUri, token);
+ var responseString = await _apiClient.GetStringAsync(uri);
- return string.IsNullOrEmpty(dataString) ?
- new Basket() { BuyerId = user.Id} :
- JsonConvert.DeserializeObject(dataString);
+ return string.IsNullOrEmpty(responseString) ?
+ new Basket() { BuyerId = user.Id } :
+ JsonConvert.DeserializeObject(responseString);
}
public async Task UpdateBasket(Basket basket)
{
- var token = await GetUserTokenAsync();
- var updateBasketUri = API.Basket.UpdateBasket(_basketByPassUrl);
+ var uri = API.Basket.UpdateBasket(_basketByPassUrl);
- var response = await _apiClient.PostAsync(updateBasketUri, basket, token);
+ var basketContent = new StringContent(JsonConvert.SerializeObject(basket), System.Text.Encoding.UTF8, "application/json");
+
+ var response = await _apiClient.PostAsync(uri, basketContent);
response.EnsureSuccessStatusCode();
@@ -58,65 +54,64 @@ namespace Microsoft.eShopOnContainers.WebMVC.Services
public async Task Checkout(BasketDTO basket)
{
- var token = await GetUserTokenAsync();
- var updateBasketUri = API.Basket.CheckoutBasket(_basketByPassUrl);
+ var uri = API.Basket.CheckoutBasket(_basketByPassUrl);
+ var basketContent = new StringContent(JsonConvert.SerializeObject(basket), System.Text.Encoding.UTF8, "application/json");
- var response = await _apiClient.PostAsync(updateBasketUri, basket, token);
+ var response = await _apiClient.PostAsync(uri, basketContent);
response.EnsureSuccessStatusCode();
}
public async Task SetQuantities(ApplicationUser user, Dictionary quantities)
{
+ var uri = API.Purchase.UpdateBasketItem(_purchaseUrl);
- var token = await GetUserTokenAsync();
- var updateBasketUri = API.Purchase.UpdateBasketItem(_purchaseUrl);
- var userId = user.Id;
-
- var response = await _apiClient.PutAsync(updateBasketUri, new
+ var basketUpdate = new
{
- BasketId = userId,
+ BasketId = user.Id,
Updates = quantities.Select(kvp => new
{
BasketItemId = kvp.Key,
NewQty = kvp.Value
}).ToArray()
- }, token);
+ };
+
+ var basketContent = new StringContent(JsonConvert.SerializeObject(basketUpdate), System.Text.Encoding.UTF8, "application/json");
+
+ var response = await _apiClient.PutAsync(uri, basketContent);
response.EnsureSuccessStatusCode();
+
var jsonResponse = await response.Content.ReadAsStringAsync();
+
return JsonConvert.DeserializeObject(jsonResponse);
}
public async Task GetOrderDraft(string basketId)
{
- var token = await GetUserTokenAsync();
- var draftOrderUri = API.Purchase.GetOrderDraft(_purchaseUrl, basketId);
- var json = await _apiClient.GetStringAsync(draftOrderUri, token);
- return JsonConvert.DeserializeObject(json);
+ var uri = API.Purchase.GetOrderDraft(_purchaseUrl, basketId);
+
+ var responseString = await _apiClient.GetStringAsync(uri);
+
+ var response = JsonConvert.DeserializeObject(responseString);
+
+ return response;
}
-
-
public async Task AddItemToBasket(ApplicationUser user, int productId)
{
- var token = await GetUserTokenAsync();
- var updateBasketUri = API.Purchase.AddItemToBasket(_purchaseUrl);
- var userId = user.Id;
+ var uri = API.Purchase.AddItemToBasket(_purchaseUrl);
- var response = await _apiClient.PostAsync(updateBasketUri, new
+ var newItem = new
{
CatalogItemId = productId,
- BasketId = userId,
+ BasketId = user.Id,
Quantity = 1
- }, token);
+ };
- }
+ var basketContent = new StringContent(JsonConvert.SerializeObject(newItem), System.Text.Encoding.UTF8, "application/json");
- async Task GetUserTokenAsync()
- {
- var context = _httpContextAccesor.HttpContext;
- return await context.GetTokenAsync("access_token");
+ var response = await _apiClient.PostAsync(uri, basketContent);
}
}
}
diff --git a/src/Web/WebMVC/Services/CampaignService.cs b/src/Web/WebMVC/Services/CampaignService.cs
index 7d61c9e7a..6521fd4ae 100644
--- a/src/Web/WebMVC/Services/CampaignService.cs
+++ b/src/Web/WebMVC/Services/CampaignService.cs
@@ -1,69 +1,49 @@
namespace Microsoft.eShopOnContainers.WebMVC.Services
{
using global::WebMVC.Infrastructure;
- using AspNetCore.Authentication;
- using AspNetCore.Http;
- using BuildingBlocks.Resilience.Http;
- using ViewModels;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
- using System;
+ using System.Net.Http;
using System.Threading.Tasks;
+ using ViewModels;
public class CampaignService : ICampaignService
{
- private readonly IOptionsSnapshot _settings;
- private readonly IHttpClient _apiClient;
+ private readonly IOptions _settings;
+ private readonly HttpClient _httpClient;
private readonly ILogger _logger;
private readonly string _remoteServiceBaseUrl;
- private readonly IHttpContextAccessor _httpContextAccesor;
- public CampaignService(IOptionsSnapshot settings, IHttpClient httpClient,
- ILogger logger, IHttpContextAccessor httpContextAccesor)
+ public CampaignService(IOptions settings, HttpClient httpClient, ILogger logger)
{
_settings = settings;
- _apiClient = httpClient;
+ _httpClient = httpClient;
_logger = logger;
_remoteServiceBaseUrl = $"{_settings.Value.MarketingUrl}/api/v1/m/campaigns/";
- _httpContextAccesor = httpContextAccesor ?? throw new ArgumentNullException(nameof(httpContextAccesor));
}
public async Task GetCampaigns(int pageSize, int pageIndex)
{
- var allCampaignItemsUri = API.Marketing.GetAllCampaigns(_remoteServiceBaseUrl,
- pageSize, pageIndex);
+ var uri = API.Marketing.GetAllCampaigns(_remoteServiceBaseUrl, pageSize, pageIndex);
- var authorizationToken = await GetUserTokenAsync();
- var dataString = await _apiClient.GetStringAsync(allCampaignItemsUri, authorizationToken);
+ var responseString = await _httpClient.GetStringAsync(uri);
- var response = JsonConvert.DeserializeObject(dataString);
+ var response = JsonConvert.DeserializeObject(responseString);
return response;
}
public async Task GetCampaignById(int id)
{
- var campaignByIdItemUri = API.Marketing.GetAllCampaignById(_remoteServiceBaseUrl, id);
+ var uri = API.Marketing.GetAllCampaignById(_remoteServiceBaseUrl, id);
- var authorizationToken = await GetUserTokenAsync();
- var dataString = await _apiClient.GetStringAsync(campaignByIdItemUri, authorizationToken);
+ var responseString = await _httpClient.GetStringAsync(uri);
- var response = JsonConvert.DeserializeObject(dataString);
+ var response = JsonConvert.DeserializeObject(responseString);
return response;
}
-
- private string GetUserIdentity()
- {
- return _httpContextAccesor.HttpContext.User.FindFirst("sub").Value;
- }
-
- private async Task GetUserTokenAsync()
- {
- var context = _httpContextAccesor.HttpContext;
- return await context.GetTokenAsync("access_token");
- }
}
}
\ No newline at end of file
diff --git a/src/Web/WebMVC/Services/CatalogService.cs b/src/Web/WebMVC/Services/CatalogService.cs
index 5b6fbe26b..d4899b453 100644
--- a/src/Web/WebMVC/Services/CatalogService.cs
+++ b/src/Web/WebMVC/Services/CatalogService.cs
@@ -1,11 +1,11 @@
using Microsoft.AspNetCore.Mvc.Rendering;
-using Microsoft.eShopOnContainers.BuildingBlocks.Resilience.Http;
using Microsoft.eShopOnContainers.WebMVC.ViewModels;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.Collections.Generic;
+using System.Net.Http;
using System.Threading.Tasks;
using WebMVC.Infrastructure;
@@ -13,16 +13,16 @@ namespace Microsoft.eShopOnContainers.WebMVC.Services
{
public class CatalogService : ICatalogService
{
- private readonly IOptionsSnapshot _settings;
- private readonly IHttpClient _apiClient;
+ private readonly IOptions _settings;
+ private readonly HttpClient _httpClient;
private readonly ILogger _logger;
private readonly string _remoteServiceBaseUrl;
- public CatalogService(IOptionsSnapshot settings, IHttpClient httpClient, ILogger logger)
+ public CatalogService(HttpClient httpClient, ILogger logger, IOptions settings)
{
+ _httpClient = httpClient;
_settings = settings;
- _apiClient = httpClient;
_logger = logger;
_remoteServiceBaseUrl = $"{_settings.Value.PurchaseUrl}/api/v1/c/catalog/";
@@ -30,25 +30,26 @@ namespace Microsoft.eShopOnContainers.WebMVC.Services
public async Task GetCatalogItems(int page, int take, int? brand, int? type)
{
- var allcatalogItemsUri = API.Catalog.GetAllCatalogItems(_remoteServiceBaseUrl, page, take, brand, type);
+ var uri = API.Catalog.GetAllCatalogItems(_remoteServiceBaseUrl, page, take, brand, type);
- var dataString = await _apiClient.GetStringAsync(allcatalogItemsUri);
+ var responseString = await _httpClient.GetStringAsync(uri);
- var response = JsonConvert.DeserializeObject(dataString);
+ var catalog = JsonConvert.DeserializeObject(responseString);
- return response;
+ return catalog;
}
public async Task> GetBrands()
{
- var getBrandsUri = API.Catalog.GetAllBrands(_remoteServiceBaseUrl);
+ var uri = API.Catalog.GetAllBrands(_remoteServiceBaseUrl);
- var dataString = await _apiClient.GetStringAsync(getBrandsUri);
+ var responseString = await _httpClient.GetStringAsync(uri);
var items = new List();
+
items.Add(new SelectListItem() { Value = null, Text = "All", Selected = true });
- var brands = JArray.Parse(dataString);
+ var brands = JArray.Parse(responseString);
foreach (var brand in brands.Children())
{
@@ -64,14 +65,14 @@ namespace Microsoft.eShopOnContainers.WebMVC.Services
public async Task> GetTypes()
{
- var getTypesUri = API.Catalog.GetAllTypes(_remoteServiceBaseUrl);
+ var uri = API.Catalog.GetAllTypes(_remoteServiceBaseUrl);
- var dataString = await _apiClient.GetStringAsync(getTypesUri);
+ var responseString = await _httpClient.GetStringAsync(uri);
var items = new List();
items.Add(new SelectListItem() { Value = null, Text = "All", Selected = true });
- var brands = JArray.Parse(dataString);
+ var brands = JArray.Parse(responseString);
foreach (var brand in brands.Children())
{
items.Add(new SelectListItem()
@@ -80,6 +81,7 @@ namespace Microsoft.eShopOnContainers.WebMVC.Services
Text = brand.Value("type")
});
}
+
return items;
}
}
diff --git a/src/Web/WebMVC/Services/LocationService.cs b/src/Web/WebMVC/Services/LocationService.cs
index 8bbdf743a..3e58ef125 100644
--- a/src/Web/WebMVC/Services/LocationService.cs
+++ b/src/Web/WebMVC/Services/LocationService.cs
@@ -1,11 +1,9 @@
-using Microsoft.AspNetCore.Authentication;
-using Microsoft.AspNetCore.Http;
-using Microsoft.eShopOnContainers.BuildingBlocks.Resilience.Http;
-using Microsoft.eShopOnContainers.WebMVC;
+using Microsoft.eShopOnContainers.WebMVC;
using Microsoft.eShopOnContainers.WebMVC.Services;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
-using System;
+using Newtonsoft.Json;
+using System.Net.Http;
using System.Threading.Tasks;
using WebMVC.Infrastructure;
using WebMVC.Models;
@@ -14,36 +12,27 @@ namespace WebMVC.Services
{
public class LocationService : ILocationService
{
- private readonly IOptionsSnapshot _settings;
- private readonly IHttpClient _apiClient;
+ private readonly IOptions _settings;
+ private readonly HttpClient _httpClient;
private readonly ILogger _logger;
private readonly string _remoteServiceBaseUrl;
- private readonly IHttpContextAccessor _httpContextAccesor;
- public LocationService(IOptionsSnapshot settings, IHttpClient httpClient,
- ILogger logger, IHttpContextAccessor httpContextAccesor)
+ public LocationService(HttpClient httpClient, IOptions settings, ILogger logger)
{
+ _httpClient = httpClient;
_settings = settings;
- _apiClient = httpClient;
_logger = logger;
_remoteServiceBaseUrl = $"{_settings.Value.MarketingUrl}/api/v1/l/locations/";
- _httpContextAccesor = httpContextAccesor ?? throw new ArgumentNullException(nameof(httpContextAccesor));
}
public async Task CreateOrUpdateUserLocation(LocationDTO location)
{
- var createOrUpdateUserLocationUri = API.Locations.CreateOrUpdateUserLocation(_remoteServiceBaseUrl);
+ var uri = API.Locations.CreateOrUpdateUserLocation(_remoteServiceBaseUrl);
+ var locationContent = new StringContent(JsonConvert.SerializeObject(location), System.Text.Encoding.UTF8, "application/json");
- var authorizationToken = await GetUserTokenAsync();
- var response = await _apiClient.PostAsync(createOrUpdateUserLocationUri, location, authorizationToken);
+ var response = await _httpClient.PostAsync(uri, locationContent);
response.EnsureSuccessStatusCode();
- }
-
- private async Task GetUserTokenAsync()
- {
- var context = _httpContextAccesor.HttpContext;
- return await context.GetTokenAsync("access_token");
}
}
}
diff --git a/src/Web/WebMVC/Services/OrderingService.cs b/src/Web/WebMVC/Services/OrderingService.cs
index ec9d2e8fd..e3d24422f 100644
--- a/src/Web/WebMVC/Services/OrderingService.cs
+++ b/src/Web/WebMVC/Services/OrderingService.cs
@@ -1,11 +1,9 @@
-using Microsoft.AspNetCore.Authentication;
-using Microsoft.AspNetCore.Http;
-using Microsoft.eShopOnContainers.BuildingBlocks.Resilience.Http;
-using Microsoft.eShopOnContainers.WebMVC.ViewModels;
+using Microsoft.eShopOnContainers.WebMVC.ViewModels;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
+using System.Net.Http;
using System.Threading.Tasks;
using WebMVC.Infrastructure;
using WebMVC.Models;
@@ -14,69 +12,54 @@ namespace Microsoft.eShopOnContainers.WebMVC.Services
{
public class OrderingService : IOrderingService
{
- private IHttpClient _apiClient;
+ private HttpClient _httpClient;
private readonly string _remoteServiceBaseUrl;
- private readonly IOptionsSnapshot _settings;
- private readonly IHttpContextAccessor _httpContextAccesor;
+ private readonly IOptions _settings;
- public OrderingService(IOptionsSnapshot settings, IHttpContextAccessor httpContextAccesor, IHttpClient httpClient)
+
+ public OrderingService(HttpClient httpClient, IOptions settings)
{
- _remoteServiceBaseUrl = $"{settings.Value.PurchaseUrl}/api/v1/o/orders";
+ _httpClient = httpClient;
_settings = settings;
- _httpContextAccesor = httpContextAccesor;
- _apiClient = httpClient;
+
+ _remoteServiceBaseUrl = $"{settings.Value.PurchaseUrl}/api/v1/o/orders";
}
async public Task GetOrder(ApplicationUser user, string id)
{
- var token = await GetUserTokenAsync();
- var getOrderUri = API.Order.GetOrder(_remoteServiceBaseUrl, id);
+ var uri = API.Order.GetOrder(_remoteServiceBaseUrl, id);
- var dataString = await _apiClient.GetStringAsync(getOrderUri, token);
+ var responseString = await _httpClient.GetStringAsync(uri);
- var response = JsonConvert.DeserializeObject(dataString);
+ var response = JsonConvert.DeserializeObject(responseString);
return response;
}
async public Task> GetMyOrders(ApplicationUser user)
{
- var token = await GetUserTokenAsync();
- var allMyOrdersUri = API.Order.GetAllMyOrders(_remoteServiceBaseUrl);
+ var uri = API.Order.GetAllMyOrders(_remoteServiceBaseUrl);
- var dataString = await _apiClient.GetStringAsync(allMyOrdersUri, token);
- var response = JsonConvert.DeserializeObject>(dataString);
+ var responseString = await _httpClient.GetStringAsync(uri);
+
+ var response = JsonConvert.DeserializeObject>(responseString);
return response;
}
- public Order MapUserInfoIntoOrder(ApplicationUser user, Order order)
- {
- order.City = user.City;
- order.Street = user.Street;
- order.State = user.State;
- order.Country = user.Country;
- order.ZipCode = user.ZipCode;
- order.CardNumber = user.CardNumber;
- order.CardHolderName = user.CardHolderName;
- order.CardExpiration = new DateTime(int.Parse("20" + user.Expiration.Split('/')[1]), int.Parse(user.Expiration.Split('/')[0]), 1);
- order.CardSecurityNumber = user.SecurityNumber;
-
- return order;
- }
async public Task CancelOrder(string orderId)
{
- var token = await GetUserTokenAsync();
var order = new OrderDTO()
{
OrderNumber = orderId
};
- var cancelOrderUri = API.Order.CancelOrder(_remoteServiceBaseUrl);
-
- var response = await _apiClient.PutAsync(cancelOrderUri, order, token, Guid.NewGuid().ToString());
+ var uri = API.Order.CancelOrder(_remoteServiceBaseUrl);
+ var orderContent = new StringContent(JsonConvert.SerializeObject(order), System.Text.Encoding.UTF8, "application/json");
+
+ var response = await _httpClient.PutAsync(uri, orderContent);
if (response.StatusCode == System.Net.HttpStatusCode.InternalServerError)
{
@@ -88,15 +71,15 @@ namespace Microsoft.eShopOnContainers.WebMVC.Services
async public Task ShipOrder(string orderId)
{
- var token = await GetUserTokenAsync();
var order = new OrderDTO()
{
OrderNumber = orderId
};
- var shipOrderUri = API.Order.ShipOrder(_remoteServiceBaseUrl);
+ var uri = API.Order.ShipOrder(_remoteServiceBaseUrl);
+ var orderContent = new StringContent(JsonConvert.SerializeObject(order), System.Text.Encoding.UTF8, "application/json");
- var response = await _apiClient.PutAsync(shipOrderUri, order, token, Guid.NewGuid().ToString());
+ var response = await _httpClient.PutAsync(uri, orderContent);
if (response.StatusCode == System.Net.HttpStatusCode.InternalServerError)
{
@@ -120,6 +103,22 @@ namespace Microsoft.eShopOnContainers.WebMVC.Services
destination.CardSecurityNumber = original.CardSecurityNumber;
}
+ public Order MapUserInfoIntoOrder(ApplicationUser user, Order order)
+ {
+ order.City = user.City;
+ order.Street = user.Street;
+ order.State = user.State;
+ order.Country = user.Country;
+ order.ZipCode = user.ZipCode;
+
+ order.CardNumber = user.CardNumber;
+ order.CardHolderName = user.CardHolderName;
+ order.CardExpiration = new DateTime(int.Parse("20" + user.Expiration.Split('/')[1]), int.Parse(user.Expiration.Split('/')[0]), 1);
+ order.CardSecurityNumber = user.SecurityNumber;
+
+ return order;
+ }
+
public BasketDTO MapOrderToBasket(Order order)
{
order.CardExpirationApiFormat();
@@ -140,18 +139,5 @@ namespace Microsoft.eShopOnContainers.WebMVC.Services
RequestId = order.RequestId
};
}
-
- void SetFakeIdToProducts(Order order)
- {
- var id = 1;
- order.OrderItems.ForEach(x => { x.ProductId = id; id++; });
- }
-
- async Task GetUserTokenAsync()
- {
- var context = _httpContextAccesor.HttpContext;
-
- return await context.GetTokenAsync("access_token");
- }
}
}
diff --git a/src/Web/WebMVC/Startup.cs b/src/Web/WebMVC/Startup.cs
index a83bfa644..9c1c0a3b8 100644
--- a/src/Web/WebMVC/Startup.cs
+++ b/src/Web/WebMVC/Startup.cs
@@ -6,17 +6,18 @@ using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.DataProtection;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
-using Microsoft.eShopOnContainers.BuildingBlocks.Resilience.Http;
-using Microsoft.eShopOnContainers.WebMVC.Infrastructure;
using Microsoft.eShopOnContainers.WebMVC.Services;
using Microsoft.eShopOnContainers.WebMVC.ViewModels;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.HealthChecks;
using Microsoft.Extensions.Logging;
+using Polly;
+using Polly.Extensions.Http;
using StackExchange.Redis;
using System;
using System.IdentityModel.Tokens.Jwt;
+using System.Net.Http;
using WebMVC.Infrastructure;
using WebMVC.Infrastructure.Middlewares;
using WebMVC.Services;
@@ -32,107 +33,15 @@ namespace Microsoft.eShopOnContainers.WebMVC
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 IoC container.
public void ConfigureServices(IServiceCollection services)
{
- RegisterAppInsights(services);
-
- services.AddMvc();
-
- services.AddSession();
-
- if (Configuration.GetValue("IsClusterEnv") == bool.TrueString)
- {
- services.AddDataProtection(opts =>
- {
- opts.ApplicationDiscriminator = "eshop.webmvc";
- })
- .PersistKeysToRedis(ConnectionMultiplexer.Connect(Configuration["DPConnectionString"]), "DataProtection-Keys");
- }
-
- services.Configure(Configuration);
-
- services.AddHealthChecks(checks =>
- {
- var minutes = 1;
- if (int.TryParse(Configuration["HealthCheck:Timeout"], out var minutesParsed))
- {
- minutes = minutesParsed;
- }
-
- checks.AddUrlCheck(Configuration["CatalogUrlHC"], 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["IdentityUrlHC"], TimeSpan.FromMinutes(minutes));
- checks.AddUrlCheck(Configuration["MarketingUrlHC"], TimeSpan.FromMinutes(minutes));
- });
-
- // Add application services.
- services.AddSingleton();
- services.AddTransient();
- services.AddTransient();
- services.AddTransient();
- services.AddTransient();
- services.AddTransient();
- services.AddTransient, IdentityParser>();
-
- if (Configuration.GetValue("UseResilientHttp") == bool.TrueString)
- {
- services.AddSingleton(sp =>
- {
- var logger = sp.GetRequiredService>();
- var httpContextAccessor = sp.GetRequiredService();
-
- var retryCount = 6;
- if (!string.IsNullOrEmpty(Configuration["HttpClientRetryCount"]))
- {
- retryCount = int.Parse(Configuration["HttpClientRetryCount"]);
- }
-
- var exceptionsAllowedBeforeBreaking = 5;
- if (!string.IsNullOrEmpty(Configuration["HttpClientExceptionsAllowedBeforeBreaking"]))
- {
- exceptionsAllowedBeforeBreaking = int.Parse(Configuration["HttpClientExceptionsAllowedBeforeBreaking"]);
- }
-
- return new ResilientHttpClientFactory(logger, httpContextAccessor, exceptionsAllowedBeforeBreaking, retryCount);
- });
- services.AddSingleton(sp => sp.GetService().CreateResilientHttpClient());
- }
- else
- {
- services.AddSingleton();
- }
- var useLoadTest = Configuration.GetValue("UseLoadTest");
- var identityUrl = Configuration.GetValue("IdentityUrl");
- var callBackUrl = Configuration.GetValue("CallBackUrl");
-
- // Add Authentication services
-
- services.AddAuthentication(options => {
- options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
- options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
- })
- .AddCookie()
- .AddOpenIdConnect(options => {
- options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
- options.Authority = identityUrl.ToString();
- options.SignedOutRedirectUri = callBackUrl.ToString();
- options.ClientId = useLoadTest ? "mvctest" : "mvc";
- options.ClientSecret = "secret";
- options.ResponseType = useLoadTest ? "code id_token token" : "code id_token";
- options.SaveTokens = true;
- options.GetClaimsFromUserInfoEndpoint = true;
- options.RequireHttpsMetadata = false;
- options.Scope.Add("openid");
- options.Scope.Add("profile");
- options.Scope.Add("orders");
- options.Scope.Add("basket");
- options.Scope.Add("marketing");
- options.Scope.Add("locations");
- options.Scope.Add("webshoppingagg");
- options.Scope.Add("orders.signalrhub");
- });
+ services.AddAppInsight(Configuration)
+ .AddHealthChecks(Configuration)
+ .AddCustomMvc(Configuration)
+ .AddHttpClientServices(Configuration)
+ //.AddHttpClientLogging(Configuration) //Opt-in HttpClientLogging config
+ .AddCustomAuthentication(Configuration);
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
@@ -140,15 +49,12 @@ namespace Microsoft.eShopOnContainers.WebMVC
{
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
- loggerFactory.AddConsole(Configuration.GetSection("Logging"));
- loggerFactory.AddDebug();
loggerFactory.AddAzureWebAppDiagnostics();
loggerFactory.AddApplicationInsights(app.ApplicationServices, LogLevel.Trace);
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
- app.UseBrowserLink();
}
else
{
@@ -174,7 +80,7 @@ namespace Microsoft.eShopOnContainers.WebMVC
{
app.UseMiddleware();
}
-
+
app.UseAuthentication();
var log = loggerFactory.CreateLogger("identity");
@@ -192,23 +98,184 @@ namespace Microsoft.eShopOnContainers.WebMVC
template: "{controller=Error}/{action=Error}");
});
}
+ }
- private void RegisterAppInsights(IServiceCollection services)
+ static class ServiceCollectionExtensions
+ {
+
+ public static IServiceCollection AddAppInsight(this IServiceCollection services, IConfiguration configuration)
{
- services.AddApplicationInsightsTelemetry(Configuration);
- var orchestratorType = Configuration.GetValue("OrchestratorType");
+ services.AddApplicationInsightsTelemetry(configuration);
+ var orchestratorType = configuration.GetValue