diff --git a/README.md b/README.md
index 4637f13ce..a181dcdb4 100644
--- a/README.md
+++ b/README.md
@@ -9,13 +9,11 @@ Sample .NET Core reference application, powered by Microsoft, based on a simplif
**NEWS / ANNOUNCEMENTS**
Do you want to be up-to-date on .NET Architecture guidance and reference apps like eShopOnContainers? --> Subscribe by "WATCHING" this new GitHub repo: https://github.com/dotnet-architecture/News
-## Updated for .NET Core 2.0 "wave" of technologies
-eShopOnContainers is updated to .NET Core 2.0 "wave". Not just compilation but also new recommended code in EF Core 2.0, ASP.NET Core 2.0, and other new related versions.
+## Updated for .NET Core 2.0 and 2.1 "wave" of technologies
+eShopOnContainers is updated to .NET Core 2.0 and 2.1 "wave". Not just compilation but also new recommended code in EF Core, ASP.NET Core, and other new related versions.
The **dockerfiles** in the solution have also been updated and now support [**Docker Multi-Stage**](https://blogs.msdn.microsoft.com/stevelasker/2017/09/11/net-and-multistage-dockerfiles/) since mid-December 2017.
-For a list on the new .NET Core 2.0 related implemented features, see this [blog post](https://blogs.msdn.microsoft.com/dotnet/2017/08/02/microservices-and-docker-containers-architecture-patterns-and-development-guidance/).
-
>**PLEASE** Read our [branch guide](./branch-guide.md) to know about our branching policy
> ### DISCLAIMER
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/docs-kb/README.md b/docs-kb/README.md
new file mode 100644
index 000000000..ad5fbd79f
--- /dev/null
+++ b/docs-kb/README.md
@@ -0,0 +1,6 @@
+eShopOnContainers Knowledge Base
+================================
+
+This folder contains a set of posts created mostly from [issues on the repo](https://github.com/dotnet-architecture/eShopOnContainers/issues), in order to offer a brief introduction as well as links to deepen the knowledge on a given subject related to the application.
+
+[Simplified CQRS and DDD](simplified-cqrs-ddd/post.md)
diff --git a/docs-kb/simplified-cqrs-ddd/devenv_2018-05-22_18-00-24.png b/docs-kb/simplified-cqrs-ddd/devenv_2018-05-22_18-00-24.png
new file mode 100644
index 000000000..e1b073019
Binary files /dev/null and b/docs-kb/simplified-cqrs-ddd/devenv_2018-05-22_18-00-24.png differ
diff --git a/docs-kb/simplified-cqrs-ddd/devenv_2018-05-22_18-13-35.png b/docs-kb/simplified-cqrs-ddd/devenv_2018-05-22_18-13-35.png
new file mode 100644
index 000000000..7c6258a17
Binary files /dev/null and b/docs-kb/simplified-cqrs-ddd/devenv_2018-05-22_18-13-35.png differ
diff --git a/docs-kb/simplified-cqrs-ddd/devenv_2018-05-22_18-22-23.png b/docs-kb/simplified-cqrs-ddd/devenv_2018-05-22_18-22-23.png
new file mode 100644
index 000000000..ad667c138
Binary files /dev/null and b/docs-kb/simplified-cqrs-ddd/devenv_2018-05-22_18-22-23.png differ
diff --git a/docs-kb/simplified-cqrs-ddd/devenv_2018-05-22_18-40-25.png b/docs-kb/simplified-cqrs-ddd/devenv_2018-05-22_18-40-25.png
new file mode 100644
index 000000000..d32e4b6a8
Binary files /dev/null and b/docs-kb/simplified-cqrs-ddd/devenv_2018-05-22_18-40-25.png differ
diff --git a/docs-kb/simplified-cqrs-ddd/devenv_2018-05-22_18-48-36.png b/docs-kb/simplified-cqrs-ddd/devenv_2018-05-22_18-48-36.png
new file mode 100644
index 000000000..db42f1e81
Binary files /dev/null and b/docs-kb/simplified-cqrs-ddd/devenv_2018-05-22_18-48-36.png differ
diff --git a/docs-kb/simplified-cqrs-ddd/devenv_2018-05-22_18-52-58.png b/docs-kb/simplified-cqrs-ddd/devenv_2018-05-22_18-52-58.png
new file mode 100644
index 000000000..5047148d5
Binary files /dev/null and b/docs-kb/simplified-cqrs-ddd/devenv_2018-05-22_18-52-58.png differ
diff --git a/docs-kb/simplified-cqrs-ddd/devenv_2018-05-22_19-11-30.png b/docs-kb/simplified-cqrs-ddd/devenv_2018-05-22_19-11-30.png
new file mode 100644
index 000000000..ab42b4278
Binary files /dev/null and b/docs-kb/simplified-cqrs-ddd/devenv_2018-05-22_19-11-30.png differ
diff --git a/docs-kb/simplified-cqrs-ddd/post.md b/docs-kb/simplified-cqrs-ddd/post.md
new file mode 100644
index 000000000..be7f9e176
--- /dev/null
+++ b/docs-kb/simplified-cqrs-ddd/post.md
@@ -0,0 +1,93 @@
+Simplified CQRS and DDD
+=======================
+
+CQRS, for Command and Query Responsibility Segregation, is an architectural pattern that, in very simple terms, has two different ways to handle the application model.
+
+**Commands** are responsible for **changing** the application state, i.e. creating, updating and deleting entities (data).
+
+**Queries** are responsible for **reading** the application state, e.g. to display information to the user.
+
+**Commands** are made thinking about the Domain rules, restrictions and transaction boundaries.
+
+**Queries** are made thinking about the presentation layer, the client UI.
+
+When handling **commands**, the application model is usually represented by DDD constructs, e.g. Root aggregates, entities, value objects, etc., and there are usually some sort of rules that restrict the allowed state changes, e.g. An order has to be paid before dispatching.
+
+When handling **queries**, the application model is usually represented by entities and relations and can be read much like SQL queries to display information.
+
+Queries don't change state, so they can be run as much as required and will always return the same values (as long as the application state hasn't changed), i.e. queries are "idempotent".
+
+Why the separation? because the rules for **changing** the model can impose unnecessary constraints for **reading** the model, e.g. you might allow to change order items only before dispatching so the order is like the gate-keeper (root aggregate) to access the order items, but you might also want to view all orders for some catalog item, so you have to be able to access the order items first (in a read only way).
+
+In this simplified CQRS approach both the DDD model and the query model use the same database.
+
+**Commands** and **Queries** are located in the Application layer, because:
+
+1. It's where the composition of domain root aggregates occur (commands) and
+2. It's close to the UI requirements and has access to the whole database of the microservice (queries).
+
+Ideally, root aggregates are ignorant of each other and it's the Application layer's responsibility to compose coordinated actions by means of domain events, because it knows about all root aggregates.
+
+Regarding **queries**, in a similar analysis, the Application layer knows about all entities and relationships in the database, beyond the restrictions of the root aggregates.
+
+Code
+----
+
+### CQRS
+The CQRS pattern can be checked in the Ordering service:
+
+Commands and queries are clearly separated in the application layer (Ordering.API).
+
+**Solution Explorer [Ordering.API]:**
+![](devenv_2018-05-22_18-00-24.png)
+
+Commands are basically read only Data Transfer Objects (DTO) that contain all data that's required to execute the operation.
+
+**CreateOrderCommand:**
+![](devenv_2018-05-22_18-13-35.png)
+
+Each command has a specific command handler that's responsible for executing the operations intended for the command.
+
+**CreateOrderCommandHandler:**
+![](devenv_2018-05-22_18-22-23.png)
+
+In this case:
+
+1. Creates an Order object (root aggregate)
+2. Adds the order items using the root aggregate method
+3. Adds the order through the repository
+4. Saves the order
+
+Queries, on the other hand, just return whatever the UI needs, could be a domain object or collections of specific DTOs.
+
+**IOrderQueries:**
+![](devenv_2018-05-22_18-40-25.png)
+
+And they are implemented as plain SQL queries, in this case using [Dapper](http://dapper-tutorial.net/ as the ORM.
+
+**OrderQueries:**
+![](devenv_2018-05-22_18-48-36.png)
+
+There can even be specific ViewModels or DTOs just to get the query results.
+
+**OrderViewModel:**
+![](devenv_2018-05-22_19-11-30.png)
+
+### DDD
+The DDD pattern can be checked in the domain layer (Ordering.Domain)
+
+**Solution Explorer [Ordering.Domain + Ordering.Infrastructure]:**
+![](devenv_2018-05-22_18-52-58.png)
+
+There you can see the Buyer aggregate and the Order aggregate, as well as the repository implementations in Ordering.Infrastructure.
+
+Command handlers from the application layer use the root aggregates from the Domain layer and the repository implementations from the Infrastructure layer, the latter through Dependency Injection.
+
+Further reading
+---------------
+
+* **Issue #592 - [Question] Ordering Queries**
https://github.com/dotnet-architecture/eShopOnContainers/issues/592
+
+* **Applying simplified CQRS and DDD patterns in a microservice**
+https://docs.microsoft.com/en-us/dotnet/standard/microservices-architecture/microservice-ddd-cqrs-patterns/apply-simplified-microservice-cqrs-ddd-patterns
+
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..386035de8 100644
--- a/global.json
+++ b/global.json
@@ -1,5 +1,5 @@
{
"sdk": {
- "version": "2.1.4"
+ "version": "2.1.300"
}
}
\ 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.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.Infrastructure;
using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Services;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Logging;
+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,14 +31,47 @@ 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.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}'");
+ 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.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.Configure(configuration.GetSection("urls"));
services.AddMvc();
@@ -57,8 +90,8 @@ namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator
{
Type = "oauth2",
Flow = "implicit",
- AuthorizationUrl = $"{Configuration.GetValue("IdentityUrlExternal")}/connect/authorize",
- TokenUrl = $"{Configuration.GetValue("IdentityUrlExternal")}/connect/token",
+ AuthorizationUrl = $"{configuration.GetValue("IdentityUrlExternal")}/connect/authorize",
+ TokenUrl = $"{configuration.GetValue("IdentityUrlExternal")}/connect/token",
Scopes = new Dictionary()
{
{ "mobileshoppingagg", "Shopping Aggregator for Mobile Clients" }
@@ -77,9 +110,12 @@ namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator
.AllowCredentials());
});
-
+ return services;
+ }
+ 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 +138,47 @@ namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator
}
};
});
- }
- // 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)
+ return services;
+ }
+ public static IServiceCollection AddHttpServices(this IServiceCollection services)
{
+ //register delegating handlers
+ services.AddTransient();
+ services.AddSingleton();
- var pathBase = Configuration["PATH_BASE"];
- if (!string.IsNullOrEmpty(pathBase))
- {
- loggerFactory.CreateLogger("init").LogDebug($"Using PATH BASE '{pathBase}'");
- app.UsePathBase(pathBase);
- }
+ //register http services
+ services.AddHttpClient()
+ .AddHttpMessageHandler()
+ .AddPolicyHandler(GetRetryPolicy())
+ .AddPolicyHandler(GetCircuitBreakerPolicy());
- app.UseCors("CorsPolicy");
+ services.AddHttpClient()
+ .AddPolicyHandler(GetRetryPolicy())
+ .AddPolicyHandler(GetCircuitBreakerPolicy());
- if (env.IsDevelopment())
- {
- app.UseDeveloperExceptionPage();
- }
+ services.AddHttpClient()
+ .AddPolicyHandler(GetRetryPolicy())
+ .AddPolicyHandler(GetCircuitBreakerPolicy());
- 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.Mobile.Shopping.HttpAggregatorwaggerui", "", "", "Purchase BFF Swagger UI");
- });
+ 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.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.Infrastructure;
using Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Services;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Logging;
+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,14 +32,77 @@ 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();
+ }
+
+ // 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}'");
+ 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");
+ });
+
+
+ }
+ }
+
+ public static class ServiceCollectionExtensions
+ {
+ 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 = "webshoppingagg";
+ options.Events = new JwtBearerEvents()
+ {
+ OnAuthenticationFailed = async ctx =>
+ {
+ int i = 0;
+ },
+ OnTokenValidated = async ctx =>
+ {
+ int i = 0;
+ }
+ };
+ });
+ return services;
+ }
+ public static IServiceCollection AddCustomMvc(this IServiceCollection services, IConfiguration configuration)
+ {
services.AddOptions();
- services.Configure(Configuration.GetSection("urls"));
+ services.Configure(configuration.GetSection("urls"));
services.AddMvc();
@@ -57,8 +121,8 @@ namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator
{
Type = "oauth2",
Flow = "implicit",
- AuthorizationUrl = $"{Configuration.GetValue("IdentityUrlExternal")}/connect/authorize",
- TokenUrl = $"{Configuration.GetValue("IdentityUrlExternal")}/connect/token",
+ AuthorizationUrl = $"{configuration.GetValue("IdentityUrlExternal")}/connect/authorize",
+ TokenUrl = $"{configuration.GetValue("IdentityUrlExternal")}/connect/token",
Scopes = new Dictionary()
{
{ "webshoppingagg", "Shopping Aggregator for Web Clients" }
@@ -77,62 +141,47 @@ namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator
.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 = "webshoppingagg";
- options.Events = new JwtBearerEvents()
- {
- OnAuthenticationFailed = async ctx =>
- {
- int i = 0;
- },
- OnTokenValidated = async ctx =>
- {
- int i = 0;
- }
- };
- });
+ 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)
+ public static IServiceCollection AddApplicationServices(this IServiceCollection services)
{
+ //register delegating handlers
+ services.AddTransient();
+ services.AddSingleton();
- var pathBase = Configuration["PATH_BASE"];
- if (!string.IsNullOrEmpty(pathBase))
- {
- loggerFactory.CreateLogger("init").LogDebug($"Using PATH BASE '{pathBase}'");
- app.UsePathBase(pathBase);
- }
-
- app.UseCors("CorsPolicy");
+ //register http services
+
+ services.AddHttpClient()
+ .AddHttpMessageHandler()
+ .AddPolicyHandler(GetRetryPolicy())
+ .AddPolicyHandler(GetCircuitBreakerPolicy());
- if (env.IsDevelopment())
- {
- app.UseDeveloperExceptionPage();
- }
+ services.AddHttpClient()
+ .AddPolicyHandler(GetRetryPolicy())
+ .AddPolicyHandler(GetCircuitBreakerPolicy());
- app.UseAuthentication();
+ services.AddHttpClient()
+ .AddHttpMessageHandler()
+ .AddPolicyHandler(GetRetryPolicy())
+ .AddPolicyHandler(GetCircuitBreakerPolicy());
- 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");
- });
+ 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/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/Mobile/eShopOnContainers/eShopOnContainers.Core/eShopOnContainers.Core.csproj b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/eShopOnContainers.Core.csproj
index 26fb0d89a..99606079f 100644
--- a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/eShopOnContainers.Core.csproj
+++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/eShopOnContainers.Core.csproj
@@ -11,7 +11,7 @@
-
+
diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Droid/Resources/Resource.Designer.cs b/src/Mobile/eShopOnContainers/eShopOnContainers.Droid/Resources/Resource.Designer.cs
index 074729b61..b3aa8d16c 100644
--- a/src/Mobile/eShopOnContainers/eShopOnContainers.Droid/Resources/Resource.Designer.cs
+++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Droid/Resources/Resource.Designer.cs
@@ -2274,9 +2274,27 @@ namespace eShopOnContainers.Droid
// aapt resource value: 0x7f020054
public const int avd_hide_password = 2130837588;
+ // aapt resource value: 0x7f020127
+ public const int avd_hide_password_1 = 2130837799;
+
+ // aapt resource value: 0x7f020128
+ public const int avd_hide_password_2 = 2130837800;
+
+ // aapt resource value: 0x7f020129
+ public const int avd_hide_password_3 = 2130837801;
+
// aapt resource value: 0x7f020055
public const int avd_show_password = 2130837589;
+ // aapt resource value: 0x7f02012a
+ public const int avd_show_password_1 = 2130837802;
+
+ // aapt resource value: 0x7f02012b
+ public const int avd_show_password_2 = 2130837803;
+
+ // aapt resource value: 0x7f02012c
+ public const int avd_show_password_3 = 2130837804;
+
// aapt resource value: 0x7f020056
public const int background = 2130837590;
diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Droid/eShopOnContainers.Droid.csproj b/src/Mobile/eShopOnContainers/eShopOnContainers.Droid/eShopOnContainers.Droid.csproj
index 92e2df581..85f339a43 100644
--- a/src/Mobile/eShopOnContainers/eShopOnContainers.Droid/eShopOnContainers.Droid.csproj
+++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Droid/eShopOnContainers.Droid.csproj
@@ -1,7 +1,7 @@
-
-
+
+
Debug
AnyCPU
@@ -58,6 +58,9 @@
SdkOnly
+
+ ..\..\..\..\packages\Xamarin.Forms.3.0.0.482510\lib\MonoAndroid10\FormsViewGroup.dll
+
@@ -181,20 +184,17 @@
..\..\..\..\packages\PCLCrypto.2.0.147\lib\MonoAndroid23\PCLCrypto.dll
-
- ..\..\..\..\packages\Xamarin.Forms.2.5.0.122203\lib\MonoAndroid10\FormsViewGroup.dll
-
-
- ..\..\..\..\packages\Xamarin.Forms.2.5.0.122203\lib\MonoAndroid10\Xamarin.Forms.Core.dll
+
+ ..\..\..\..\packages\Xamarin.Forms.3.0.0.482510\lib\MonoAndroid10\Xamarin.Forms.Core.dll
-
- ..\..\..\..\packages\Xamarin.Forms.2.5.0.122203\lib\MonoAndroid10\Xamarin.Forms.Platform.Android.dll
+
+ ..\..\..\..\packages\Xamarin.Forms.3.0.0.482510\lib\MonoAndroid10\Xamarin.Forms.Platform.dll
-
- ..\..\..\..\packages\Xamarin.Forms.2.5.0.122203\lib\MonoAndroid10\Xamarin.Forms.Platform.dll
+
+ ..\..\..\..\packages\Xamarin.Forms.3.0.0.482510\lib\MonoAndroid10\Xamarin.Forms.Platform.Android.dll
-
- ..\..\..\..\packages\Xamarin.Forms.2.5.0.122203\lib\MonoAndroid10\Xamarin.Forms.Xaml.dll
+
+ ..\..\..\..\packages\Xamarin.Forms.3.0.0.482510\lib\MonoAndroid10\Xamarin.Forms.Xaml.dll
@@ -368,9 +368,7 @@
eShopOnContainers.Core
-
-
-
+
@@ -387,10 +385,20 @@
-
-
-
+
+
+ This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Droid/packages.config b/src/Mobile/eShopOnContainers/eShopOnContainers.Droid/packages.config
index 2efab0dea..239ab79f5 100644
--- a/src/Mobile/eShopOnContainers/eShopOnContainers.Droid/packages.config
+++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Droid/packages.config
@@ -10,7 +10,7 @@
-
+
@@ -84,8 +84,8 @@
-
+
-
+
\ No newline at end of file
diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.TestRunner.Droid/Resources/Resource.Designer.cs b/src/Mobile/eShopOnContainers/eShopOnContainers.TestRunner.Droid/Resources/Resource.Designer.cs
index cf88d1538..694a01864 100644
--- a/src/Mobile/eShopOnContainers/eShopOnContainers.TestRunner.Droid/Resources/Resource.Designer.cs
+++ b/src/Mobile/eShopOnContainers/eShopOnContainers.TestRunner.Droid/Resources/Resource.Designer.cs
@@ -2268,9 +2268,27 @@ namespace eShopOnContainers.TestRunner.Droid
// aapt resource value: 0x7f020053
public const int avd_hide_password = 2130837587;
+ // aapt resource value: 0x7f020112
+ public const int avd_hide_password_1 = 2130837778;
+
+ // aapt resource value: 0x7f020113
+ public const int avd_hide_password_2 = 2130837779;
+
+ // aapt resource value: 0x7f020114
+ public const int avd_hide_password_3 = 2130837780;
+
// aapt resource value: 0x7f020054
public const int avd_show_password = 2130837588;
+ // aapt resource value: 0x7f020115
+ public const int avd_show_password_1 = 2130837781;
+
+ // aapt resource value: 0x7f020116
+ public const int avd_show_password_2 = 2130837782;
+
+ // aapt resource value: 0x7f020117
+ public const int avd_show_password_3 = 2130837783;
+
// aapt resource value: 0x7f020055
public const int design_bottom_navigation_item_background = 2130837589;
diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.TestRunner.Droid/eShopOnContainers.TestRunner.Droid.csproj b/src/Mobile/eShopOnContainers/eShopOnContainers.TestRunner.Droid/eShopOnContainers.TestRunner.Droid.csproj
index fee481b8a..328b2a203 100644
--- a/src/Mobile/eShopOnContainers/eShopOnContainers.TestRunner.Droid/eShopOnContainers.TestRunner.Droid.csproj
+++ b/src/Mobile/eShopOnContainers/eShopOnContainers.TestRunner.Droid/eShopOnContainers.TestRunner.Droid.csproj
@@ -1,7 +1,7 @@
-
-
+
+
Debug
@@ -50,6 +50,9 @@
False
+
+ ..\..\..\..\packages\Xamarin.Forms.3.0.0.482510\lib\MonoAndroid10\FormsViewGroup.dll
+
@@ -109,6 +112,18 @@
..\..\..\..\packages\Xamarin.Android.Support.v7.MediaRouter.25.4.0.2\lib\MonoAndroid70\Xamarin.Android.Support.v7.MediaRouter.dll
+
+ ..\..\..\..\packages\Xamarin.Forms.3.0.0.482510\lib\MonoAndroid10\Xamarin.Forms.Core.dll
+
+
+ ..\..\..\..\packages\Xamarin.Forms.3.0.0.482510\lib\MonoAndroid10\Xamarin.Forms.Platform.dll
+
+
+ ..\..\..\..\packages\Xamarin.Forms.3.0.0.482510\lib\MonoAndroid10\Xamarin.Forms.Platform.Android.dll
+
+
+ ..\..\..\..\packages\Xamarin.Forms.3.0.0.482510\lib\MonoAndroid10\Xamarin.Forms.Xaml.dll
+
..\..\..\..\packages\xunit.runner.devices.2.3.3\lib\monoandroid80\xunit.runner.devices.dll
@@ -196,21 +211,6 @@
..\..\..\..\packages\Xamarin.FFImageLoading.Forms.2.3.4\lib\MonoAndroid10\FFImageLoading.Forms.Droid.dll
-
- ..\..\..\..\packages\Xamarin.Forms.2.5.0.122203\lib\MonoAndroid10\FormsViewGroup.dll
-
-
- ..\..\..\..\packages\Xamarin.Forms.2.5.0.122203\lib\MonoAndroid10\Xamarin.Forms.Core.dll
-
-
- ..\..\..\..\packages\Xamarin.Forms.2.5.0.122203\lib\MonoAndroid10\Xamarin.Forms.Platform.Android.dll
-
-
- ..\..\..\..\packages\Xamarin.Forms.2.5.0.122203\lib\MonoAndroid10\Xamarin.Forms.Platform.dll
-
-
- ..\..\..\..\packages\Xamarin.Forms.2.5.0.122203\lib\MonoAndroid10\Xamarin.Forms.Xaml.dll
-
@@ -262,15 +262,19 @@
-
This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
-
+
+
+
+
+
-
-
-
+
+
+
+
\ No newline at end of file
diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.TestRunner.Droid/packages.config b/src/Mobile/eShopOnContainers/eShopOnContainers.TestRunner.Droid/packages.config
index c487853a8..e78a48cbf 100644
--- a/src/Mobile/eShopOnContainers/eShopOnContainers.TestRunner.Droid/packages.config
+++ b/src/Mobile/eShopOnContainers/eShopOnContainers.TestRunner.Droid/packages.config
@@ -7,7 +7,7 @@
-
+
@@ -81,10 +81,10 @@
-
+
-
+
diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.TestRunner.Windows/eShopOnContainers.TestRunner.Windows.csproj b/src/Mobile/eShopOnContainers/eShopOnContainers.TestRunner.Windows/eShopOnContainers.TestRunner.Windows.csproj
index 058fd2810..dd648b8d5 100644
--- a/src/Mobile/eShopOnContainers/eShopOnContainers.TestRunner.Windows/eShopOnContainers.TestRunner.Windows.csproj
+++ b/src/Mobile/eShopOnContainers/eShopOnContainers.TestRunner.Windows/eShopOnContainers.TestRunner.Windows.csproj
@@ -128,7 +128,7 @@
- 6.0.6
+ 6.1.5
2.3.3
diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.TestRunner.iOS/eShopOnContainers.TestRunner.iOS.csproj b/src/Mobile/eShopOnContainers/eShopOnContainers.TestRunner.iOS/eShopOnContainers.TestRunner.iOS.csproj
index 250d836a7..5bcdeee05 100644
--- a/src/Mobile/eShopOnContainers/eShopOnContainers.TestRunner.iOS/eShopOnContainers.TestRunner.iOS.csproj
+++ b/src/Mobile/eShopOnContainers/eShopOnContainers.TestRunner.iOS/eShopOnContainers.TestRunner.iOS.csproj
@@ -1,232 +1,232 @@
-
-
+
+
+
+ Debug
+ iPhoneSimulator
+ {B68C2B56-7581-46AE-B55D-D25DDFD3BFE3}
+ {FEACFBD2-3405-455C-9665-78FE426C6842};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
+ Exe
+ eShopOnContainers.TestRunner.iOS
+ Resources
+ eShopOnContainersTestRunneriOS
+
+
+ true
+
+
+ true
+ full
+ false
+ bin\iPhoneSimulator\Debug
+ DEBUG
+ prompt
+ 4
+ false
+ x86_64
+ None
+ True
+ False
+ False
+ False
+ False
+ False
+ True
+ Default
+ HttpClientHandler
+ False
+
+
+ false
+ none
+ true
+ bin\iPhoneSimulator\Release
+ prompt
+ 4
+ None
+ x86_64
+ false
+
+
+ true
+ full
+ false
+ bin\iPhone\Debug
+ DEBUG
+ prompt
+ 4
+ false
+ ARMv7, ARM64
+ Entitlements.plist
+ iPhone Developer
+ true
+ None
+
+
+ false
+ none
+ true
+ bin\iPhone\Release
+ prompt
+ 4
+ Entitlements.plist
+ ARMv7, ARM64
+ false
+ iPhone Developer
+
+
+ none
+ True
+ bin\iPhone\Ad-Hoc
+ prompt
+ 4
+ False
+ ARMv7, ARM64
+ Entitlements.plist
+ True
+ Automatic:AdHoc
+ iPhone Distribution
+
+
+ none
+ True
+ bin\iPhone\AppStore
+ prompt
+ 4
+ False
+ ARMv7, ARM64
+ Entitlements.plist
+ Automatic:AppStore
+ iPhone Distribution
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ..\..\..\..\packages\Xamarin.Forms.3.0.0.482510\lib\Xamarin.iOS10\Xamarin.Forms.Core.dll
+
+
+ ..\..\..\..\packages\Xamarin.Forms.3.0.0.482510\lib\Xamarin.iOS10\Xamarin.Forms.Platform.dll
+
+
+ ..\..\..\..\packages\Xamarin.Forms.3.0.0.482510\lib\Xamarin.iOS10\Xamarin.Forms.Platform.iOS.dll
+
+
+ ..\..\..\..\packages\Xamarin.Forms.3.0.0.482510\lib\Xamarin.iOS10\Xamarin.Forms.Xaml.dll
+
+
+
+
+
+ ..\..\..\..\packages\xunit.runner.devices.2.3.3\lib\xamarinios10\xunit.runner.devices.dll
+
+
+ ..\..\..\..\packages\xunit.runner.devices.2.3.3\lib\xamarinios10\xunit.runner.utility.netstandard15.dll
+
+
+ ..\..\..\..\packages\xunit.abstractions.2.0.1\lib\netstandard1.0\xunit.abstractions.dll
+
+
+ ..\..\..\..\packages\xunit.assert.2.3.1\lib\netstandard1.1\xunit.assert.dll
+
+
+ ..\..\..\..\packages\xunit.extensibility.core.2.3.1\lib\netstandard1.1\xunit.core.dll
+
+
+ ..\..\..\..\packages\xunit.extensibility.execution.2.3.1\lib\netstandard1.1\xunit.execution.dotnet.dll
+
+
+ ..\..\..\..\packages\Newtonsoft.Json.10.0.3\lib\netstandard1.3\Newtonsoft.Json.dll
+
+
+ ..\..\..\..\packages\SlideOverKit.2.1.5\lib\Xamarin.iOS10\SlideOverKit.dll
+
+
+ ..\..\..\..\packages\SlideOverKit.2.1.5\lib\Xamarin.iOS10\SlideOverKit.iOS.dll
+
+
+ ..\..\..\..\packages\IdentityModel.3.0.0\lib\netstandard2.0\IdentityModel.dll
+
+
+ ..\..\..\..\packages\Acr.Support.2.1.0\lib\Xamarin.iOS10\Acr.Support.iOS.dll
+
+
+ ..\..\..\..\packages\BTProgressHUD.1.2.0.5\lib\Xamarin.iOS10\BTProgressHUD.dll
+
+
+ ..\..\..\..\packages\Splat.2.0.0\lib\Xamarin.iOS10\Splat.dll
+
+
+ ..\..\..\..\packages\Acr.UserDialogs.6.5.1\lib\Xamarin.iOS10\Acr.UserDialogs.dll
+
+
+ ..\..\..\..\packages\Acr.UserDialogs.6.5.1\lib\Xamarin.iOS10\Acr.UserDialogs.Interface.dll
+
+
+ ..\..\..\..\packages\WebP.Touch.1.0.7\lib\Xamarin.iOS10\WebP.Touch.dll
+
+
+ ..\..\..\..\packages\Xamarin.FFImageLoading.2.3.4\lib\Xamarin.iOS10\FFImageLoading.dll
+
+
+ ..\..\..\..\packages\Xamarin.FFImageLoading.2.3.4\lib\Xamarin.iOS10\FFImageLoading.Platform.dll
+
+
+ ..\..\..\..\packages\Xamarin.FFImageLoading.Forms.2.3.4\lib\Xamarin.iOS10\FFImageLoading.Forms.dll
+
+
+ ..\..\..\..\packages\Xamarin.FFImageLoading.Forms.2.3.4\lib\Xamarin.iOS10\FFImageLoading.Forms.Touch.dll
+
+
+ ..\..\..\..\packages\PInvoke.Windows.Core.0.3.2\lib\portable-net45+win+wpa81+MonoAndroid10+xamarinios10+MonoTouch10\PInvoke.Windows.Core.dll
+
+
+ ..\..\..\..\packages\PInvoke.Kernel32.0.3.2\lib\portable-net45+win+wpa81+MonoAndroid10+xamarinios10+MonoTouch10\PInvoke.Kernel32.dll
+
+
+ ..\..\..\..\packages\PInvoke.BCrypt.0.3.2\lib\portable-net45+win+wpa81+MonoAndroid10+xamarinios10+MonoTouch10\PInvoke.BCrypt.dll
+
+
+ ..\..\..\..\packages\PInvoke.NCrypt.0.3.2\lib\portable-net45+win+wpa81+MonoAndroid10+xamarinios10+MonoTouch10\PInvoke.NCrypt.dll
+
+
+ ..\..\..\..\packages\Validation.2.2.8\lib\dotnet\Validation.dll
+
+
+ ..\..\..\..\packages\PCLCrypto.2.0.147\lib\xamarinios10\PCLCrypto.dll
+
+
+
+
+
+
+
+ {FDD910BC-DF0F-483D-B7D5-C7D831855172}
+ eShopOnContainers.UnitTests
+
+
+
+
+
+
- Debug
- iPhoneSimulator
- {B68C2B56-7581-46AE-B55D-D25DDFD3BFE3}
- {FEACFBD2-3405-455C-9665-78FE426C6842};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
- Exe
- eShopOnContainers.TestRunner.iOS
- Resources
- eShopOnContainersTestRunneriOS
-
-
- true
+ This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
-
- true
- full
- false
- bin\iPhoneSimulator\Debug
- DEBUG
- prompt
- 4
- false
- x86_64
- None
- True
- False
- False
- False
- False
- False
- True
- Default
- HttpClientHandler
- False
-
-
- false
- none
- true
- bin\iPhoneSimulator\Release
- prompt
- 4
- None
- x86_64
- false
-
-
- true
- full
- false
- bin\iPhone\Debug
- DEBUG
- prompt
- 4
- false
- ARMv7, ARM64
- Entitlements.plist
- iPhone Developer
- true
- None
-
-
- false
- none
- true
- bin\iPhone\Release
- prompt
- 4
- Entitlements.plist
- ARMv7, ARM64
- false
- iPhone Developer
-
-
- none
- True
- bin\iPhone\Ad-Hoc
- prompt
- 4
- False
- ARMv7, ARM64
- Entitlements.plist
- True
- Automatic:AdHoc
- iPhone Distribution
-
-
- none
- True
- bin\iPhone\AppStore
- prompt
- 4
- False
- ARMv7, ARM64
- Entitlements.plist
- Automatic:AppStore
- iPhone Distribution
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- ..\..\..\..\packages\Xamarin.Forms.2.5.0.122203\lib\Xamarin.iOS10\Xamarin.Forms.Core.dll
-
-
- ..\..\..\..\packages\Xamarin.Forms.2.5.0.122203\lib\Xamarin.iOS10\Xamarin.Forms.Platform.dll
-
-
- ..\..\..\..\packages\Xamarin.Forms.2.5.0.122203\lib\Xamarin.iOS10\Xamarin.Forms.Platform.iOS.dll
-
-
- ..\..\..\..\packages\Xamarin.Forms.2.5.0.122203\lib\Xamarin.iOS10\Xamarin.Forms.Xaml.dll
-
-
-
-
-
- ..\..\..\..\packages\xunit.runner.devices.2.3.3\lib\xamarinios10\xunit.runner.devices.dll
-
-
- ..\..\..\..\packages\xunit.runner.devices.2.3.3\lib\xamarinios10\xunit.runner.utility.netstandard15.dll
-
-
- ..\..\..\..\packages\xunit.abstractions.2.0.1\lib\netstandard1.0\xunit.abstractions.dll
-
-
- ..\..\..\..\packages\xunit.assert.2.3.1\lib\netstandard1.1\xunit.assert.dll
-
-
- ..\..\..\..\packages\xunit.extensibility.core.2.3.1\lib\netstandard1.1\xunit.core.dll
-
-
- ..\..\..\..\packages\xunit.extensibility.execution.2.3.1\lib\netstandard1.1\xunit.execution.dotnet.dll
-
-
- ..\..\..\..\packages\Newtonsoft.Json.10.0.3\lib\netstandard1.3\Newtonsoft.Json.dll
-
-
- ..\..\..\..\packages\SlideOverKit.2.1.5\lib\Xamarin.iOS10\SlideOverKit.dll
-
-
- ..\..\..\..\packages\SlideOverKit.2.1.5\lib\Xamarin.iOS10\SlideOverKit.iOS.dll
-
-
- ..\..\..\..\packages\IdentityModel.3.0.0\lib\netstandard2.0\IdentityModel.dll
-
-
- ..\..\..\..\packages\Acr.Support.2.1.0\lib\Xamarin.iOS10\Acr.Support.iOS.dll
-
-
- ..\..\..\..\packages\BTProgressHUD.1.2.0.5\lib\Xamarin.iOS10\BTProgressHUD.dll
-
-
- ..\..\..\..\packages\Splat.2.0.0\lib\Xamarin.iOS10\Splat.dll
-
-
- ..\..\..\..\packages\Acr.UserDialogs.6.5.1\lib\Xamarin.iOS10\Acr.UserDialogs.dll
-
-
- ..\..\..\..\packages\Acr.UserDialogs.6.5.1\lib\Xamarin.iOS10\Acr.UserDialogs.Interface.dll
-
-
- ..\..\..\..\packages\WebP.Touch.1.0.7\lib\Xamarin.iOS10\WebP.Touch.dll
-
-
- ..\..\..\..\packages\Xamarin.FFImageLoading.2.3.4\lib\Xamarin.iOS10\FFImageLoading.dll
-
-
- ..\..\..\..\packages\Xamarin.FFImageLoading.2.3.4\lib\Xamarin.iOS10\FFImageLoading.Platform.dll
-
-
- ..\..\..\..\packages\Xamarin.FFImageLoading.Forms.2.3.4\lib\Xamarin.iOS10\FFImageLoading.Forms.dll
-
-
- ..\..\..\..\packages\Xamarin.FFImageLoading.Forms.2.3.4\lib\Xamarin.iOS10\FFImageLoading.Forms.Touch.dll
-
-
- ..\..\..\..\packages\PInvoke.Windows.Core.0.3.2\lib\portable-net45+win+wpa81+MonoAndroid10+xamarinios10+MonoTouch10\PInvoke.Windows.Core.dll
-
-
- ..\..\..\..\packages\PInvoke.Kernel32.0.3.2\lib\portable-net45+win+wpa81+MonoAndroid10+xamarinios10+MonoTouch10\PInvoke.Kernel32.dll
-
-
- ..\..\..\..\packages\PInvoke.BCrypt.0.3.2\lib\portable-net45+win+wpa81+MonoAndroid10+xamarinios10+MonoTouch10\PInvoke.BCrypt.dll
-
-
- ..\..\..\..\packages\PInvoke.NCrypt.0.3.2\lib\portable-net45+win+wpa81+MonoAndroid10+xamarinios10+MonoTouch10\PInvoke.NCrypt.dll
-
-
- ..\..\..\..\packages\Validation.2.2.8\lib\dotnet\Validation.dll
-
-
- ..\..\..\..\packages\PCLCrypto.2.0.147\lib\xamarinios10\PCLCrypto.dll
-
-
-
-
-
-
-
- {FDD910BC-DF0F-483D-B7D5-C7D831855172}
- eShopOnContainers.UnitTests
-
-
-
-
-
-
-
- This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
-
-
-
-
-
-
-
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.TestRunner.iOS/packages.config b/src/Mobile/eShopOnContainers/eShopOnContainers.TestRunner.iOS/packages.config
index 6bbbed083..4a79e3884 100644
--- a/src/Mobile/eShopOnContainers/eShopOnContainers.TestRunner.iOS/packages.config
+++ b/src/Mobile/eShopOnContainers/eShopOnContainers.TestRunner.iOS/packages.config
@@ -7,7 +7,7 @@
-
+
@@ -67,7 +67,7 @@
-
+
diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.UnitTests/eShopOnContainers.UnitTests.csproj b/src/Mobile/eShopOnContainers/eShopOnContainers.UnitTests/eShopOnContainers.UnitTests.csproj
index 74e0d0c29..d5c8bdb3b 100644
--- a/src/Mobile/eShopOnContainers/eShopOnContainers.UnitTests/eShopOnContainers.UnitTests.csproj
+++ b/src/Mobile/eShopOnContainers/eShopOnContainers.UnitTests/eShopOnContainers.UnitTests.csproj
@@ -5,7 +5,7 @@
-
+
diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Windows/eShopOnContainers.Windows.csproj b/src/Mobile/eShopOnContainers/eShopOnContainers.Windows/eShopOnContainers.Windows.csproj
index 9a1a2d108..5dbe11213 100644
--- a/src/Mobile/eShopOnContainers/eShopOnContainers.Windows/eShopOnContainers.Windows.csproj
+++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Windows/eShopOnContainers.Windows.csproj
@@ -180,7 +180,7 @@
- 6.0.6
+ 6.1.5
diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.iOS/eShopOnContainers.iOS.csproj b/src/Mobile/eShopOnContainers/eShopOnContainers.iOS/eShopOnContainers.iOS.csproj
index 3d18f3a5c..c24b98c02 100644
--- a/src/Mobile/eShopOnContainers/eShopOnContainers.iOS/eShopOnContainers.iOS.csproj
+++ b/src/Mobile/eShopOnContainers/eShopOnContainers.iOS/eShopOnContainers.iOS.csproj
@@ -1,428 +1,428 @@
-
+
+
+ Debug
+ iPhoneSimulator
+ 8.0.30703
+ 2.0
+ {6EEB23DC-7063-4444-9AF8-90DF24F549C0}
+ {FEACFBD2-3405-455C-9665-78FE426C6842};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
+ Exe
+ eShopOnContainers.iOS
+ Resources
+ eShopOnContainersiOS
+
+
+ true
+ true
+
+
+ true
+ full
+ false
+ bin\iPhoneSimulator\Debug
+ DEBUG
+ prompt
+ 4
+ false
+ i386, x86_64
+ None
+ True
+ False
+ False
+ False
+ False
+ False
+ True
+ Default
+ HttpClientHandler
+ False
+
+
+ none
+ true
+ bin\iPhoneSimulator\Release
+ prompt
+ 4
+ None
+ i386, x86_64
+ false
+
+
+ true
+ full
+ false
+ bin\iPhone\Debug
+ DEBUG
+ prompt
+ 4
+ false
+ ARMv7, ARM64
+ iPhone Developer
+ true
+ Entitlements.plist
+ None
+
+
+ none
+ true
+ bin\iPhone\Release
+ prompt
+ 4
+ ARMv7, ARM64
+ false
+ iPhone Developer
+ Entitlements.plist
+
+
+ none
+ True
+ bin\iPhone\Ad-Hoc
+ prompt
+ 4
+ False
+ ARMv7, ARM64
+ True
+ Automatic:AdHoc
+ iPhone Distribution
+ Entitlements.plist
+
+
+ none
+ True
+ bin\iPhone\AppStore
+ prompt
+ 4
+ False
+ ARMv7, ARM64
+ Automatic:AppStore
+ iPhone Distribution
+ Entitlements.plist
+
+
+
+
+
+
+ Resources\fonts\Montserrat-Bold.ttf
+
+
+ Resources\fonts\Montserrat-Regular.ttf
+
+
+ Resources\fonts\SourceSansPro-Regular.ttf
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ..\..\..\..\packages\Xamarin.Forms.3.0.0.482510\lib\Xamarin.iOS10\Xamarin.Forms.Core.dll
+
+
+ ..\..\..\..\packages\Xamarin.Forms.3.0.0.482510\lib\Xamarin.iOS10\Xamarin.Forms.Platform.dll
+
+
+ ..\..\..\..\packages\Xamarin.Forms.3.0.0.482510\lib\Xamarin.iOS10\Xamarin.Forms.Platform.iOS.dll
+
+
+ ..\..\..\..\packages\Xamarin.Forms.3.0.0.482510\lib\Xamarin.iOS10\Xamarin.Forms.Xaml.dll
+
+
+
+
+
+ ..\..\..\..\packages\WebP.Touch.1.0.7\lib\Xamarin.iOS10\WebP.Touch.dll
+
+
+ ..\..\..\..\packages\Xamarin.FFImageLoading.2.3.4\lib\Xamarin.iOS10\FFImageLoading.dll
+
+
+ ..\..\..\..\packages\Xamarin.FFImageLoading.2.3.4\lib\Xamarin.iOS10\FFImageLoading.Platform.dll
+
+
+ ..\..\..\..\packages\Xamarin.FFImageLoading.Forms.2.3.4\lib\Xamarin.iOS10\FFImageLoading.Forms.dll
+
+
+ ..\..\..\..\packages\Xamarin.FFImageLoading.Forms.2.3.4\lib\Xamarin.iOS10\FFImageLoading.Forms.Touch.dll
+
+
+ ..\..\..\..\packages\SlideOverKit.2.1.5\lib\Xamarin.iOS10\SlideOverKit.dll
+
+
+ ..\..\..\..\packages\SlideOverKit.2.1.5\lib\Xamarin.iOS10\SlideOverKit.iOS.dll
+
+
+ ..\..\..\..\packages\Xam.Plugins.Settings.3.1.1\lib\Xamarin.iOS10\Plugin.Settings.Abstractions.dll
+
+
+ ..\..\..\..\packages\Xam.Plugins.Settings.3.1.1\lib\Xamarin.iOS10\Plugin.Settings.dll
+
+
+ ..\..\..\..\packages\Newtonsoft.Json.10.0.3\lib\netstandard1.3\Newtonsoft.Json.dll
+
+
+ ..\..\..\..\packages\Acr.Support.2.1.0\lib\Xamarin.iOS10\Acr.Support.iOS.dll
+
+
+ ..\..\..\..\packages\BTProgressHUD.1.2.0.5\lib\Xamarin.iOS10\BTProgressHUD.dll
+
+
+ ..\..\..\..\packages\Splat.2.0.0\lib\Xamarin.iOS10\Splat.dll
+
+
+ ..\..\..\..\packages\Acr.UserDialogs.6.5.1\lib\Xamarin.iOS10\Acr.UserDialogs.dll
+
+
+ ..\..\..\..\packages\Acr.UserDialogs.6.5.1\lib\Xamarin.iOS10\Acr.UserDialogs.Interface.dll
+
+
+ ..\..\..\..\packages\PInvoke.Windows.Core.0.3.2\lib\portable-net45+win+wpa81+MonoAndroid10+xamarinios10+MonoTouch10\PInvoke.Windows.Core.dll
+
+
+ ..\..\..\..\packages\PInvoke.Kernel32.0.3.2\lib\portable-net45+win+wpa81+MonoAndroid10+xamarinios10+MonoTouch10\PInvoke.Kernel32.dll
+
+
+ ..\..\..\..\packages\PInvoke.BCrypt.0.3.2\lib\portable-net45+win+wpa81+MonoAndroid10+xamarinios10+MonoTouch10\PInvoke.BCrypt.dll
+
+
+ ..\..\..\..\packages\PInvoke.NCrypt.0.3.2\lib\portable-net45+win+wpa81+MonoAndroid10+xamarinios10+MonoTouch10\PInvoke.NCrypt.dll
+
+
+ ..\..\..\..\packages\Validation.2.2.8\lib\dotnet\Validation.dll
+
+
+ ..\..\..\..\packages\PCLCrypto.2.0.147\lib\xamarinios10\PCLCrypto.dll
+
+
+ ..\..\..\..\packages\IdentityModel.3.0.0\lib\netstandard2.0\IdentityModel.dll
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ false
+
+
+ false
+
+
+ false
+
+
+ false
+
+
+ false
+
+
+ false
+
+
+ false
+
+
+ false
+
+
+ false
+
+
+ false
+
+
+ false
+
+
+ false
+
+
+ false
+
+
+ false
+
+
+ false
+
+
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {76C5F2A7-6CD5-49EA-9F33-EC44DE6539C7}
+ eShopOnContainers.Core
+
+
+
+
+
- Debug
- iPhoneSimulator
- 8.0.30703
- 2.0
- {6EEB23DC-7063-4444-9AF8-90DF24F549C0}
- {FEACFBD2-3405-455C-9665-78FE426C6842};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
- Exe
- eShopOnContainers.iOS
- Resources
- eShopOnContainersiOS
-
-
- true
- true
+ This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
-
- true
- full
- false
- bin\iPhoneSimulator\Debug
- DEBUG
- prompt
- 4
- false
- i386, x86_64
- None
- True
- False
- False
- False
- False
- False
- True
- Default
- HttpClientHandler
- False
-
-
- none
- true
- bin\iPhoneSimulator\Release
- prompt
- 4
- None
- i386, x86_64
- false
-
-
- true
- full
- false
- bin\iPhone\Debug
- DEBUG
- prompt
- 4
- false
- ARMv7, ARM64
- iPhone Developer
- true
- Entitlements.plist
- None
-
-
- none
- true
- bin\iPhone\Release
- prompt
- 4
- ARMv7, ARM64
- false
- iPhone Developer
- Entitlements.plist
-
-
- none
- True
- bin\iPhone\Ad-Hoc
- prompt
- 4
- False
- ARMv7, ARM64
- True
- Automatic:AdHoc
- iPhone Distribution
- Entitlements.plist
-
-
- none
- True
- bin\iPhone\AppStore
- prompt
- 4
- False
- ARMv7, ARM64
- Automatic:AppStore
- iPhone Distribution
- Entitlements.plist
-
-
-
-
-
-
- Resources\fonts\Montserrat-Bold.ttf
-
-
- Resources\fonts\Montserrat-Regular.ttf
-
-
- Resources\fonts\SourceSansPro-Regular.ttf
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- ..\..\..\..\packages\Xamarin.Forms.2.5.0.122203\lib\Xamarin.iOS10\Xamarin.Forms.Core.dll
-
-
- ..\..\..\..\packages\Xamarin.Forms.2.5.0.122203\lib\Xamarin.iOS10\Xamarin.Forms.Platform.dll
-
-
- ..\..\..\..\packages\Xamarin.Forms.2.5.0.122203\lib\Xamarin.iOS10\Xamarin.Forms.Platform.iOS.dll
-
-
- ..\..\..\..\packages\Xamarin.Forms.2.5.0.122203\lib\Xamarin.iOS10\Xamarin.Forms.Xaml.dll
-
-
- ..\..\..\..\packages\WebP.Touch.1.0.7\lib\Xamarin.iOS10\WebP.Touch.dll
-
-
- ..\..\..\..\packages\Xamarin.FFImageLoading.2.3.4\lib\Xamarin.iOS10\FFImageLoading.dll
-
-
- ..\..\..\..\packages\Xamarin.FFImageLoading.2.3.4\lib\Xamarin.iOS10\FFImageLoading.Platform.dll
-
-
- ..\..\..\..\packages\Xamarin.FFImageLoading.Forms.2.3.4\lib\Xamarin.iOS10\FFImageLoading.Forms.dll
-
-
- ..\..\..\..\packages\Xamarin.FFImageLoading.Forms.2.3.4\lib\Xamarin.iOS10\FFImageLoading.Forms.Touch.dll
-
-
- ..\..\..\..\packages\SlideOverKit.2.1.5\lib\Xamarin.iOS10\SlideOverKit.dll
-
-
- ..\..\..\..\packages\SlideOverKit.2.1.5\lib\Xamarin.iOS10\SlideOverKit.iOS.dll
-
-
- ..\..\..\..\packages\Xam.Plugins.Settings.3.1.1\lib\Xamarin.iOS10\Plugin.Settings.Abstractions.dll
-
-
- ..\..\..\..\packages\Xam.Plugins.Settings.3.1.1\lib\Xamarin.iOS10\Plugin.Settings.dll
-
-
- ..\..\..\..\packages\Newtonsoft.Json.10.0.3\lib\netstandard1.3\Newtonsoft.Json.dll
-
-
- ..\..\..\..\packages\Acr.Support.2.1.0\lib\Xamarin.iOS10\Acr.Support.iOS.dll
-
-
- ..\..\..\..\packages\BTProgressHUD.1.2.0.5\lib\Xamarin.iOS10\BTProgressHUD.dll
-
-
- ..\..\..\..\packages\Splat.2.0.0\lib\Xamarin.iOS10\Splat.dll
-
-
- ..\..\..\..\packages\Acr.UserDialogs.6.5.1\lib\Xamarin.iOS10\Acr.UserDialogs.dll
-
-
- ..\..\..\..\packages\Acr.UserDialogs.6.5.1\lib\Xamarin.iOS10\Acr.UserDialogs.Interface.dll
-
-
- ..\..\..\..\packages\PInvoke.Windows.Core.0.3.2\lib\portable-net45+win+wpa81+MonoAndroid10+xamarinios10+MonoTouch10\PInvoke.Windows.Core.dll
-
-
- ..\..\..\..\packages\PInvoke.Kernel32.0.3.2\lib\portable-net45+win+wpa81+MonoAndroid10+xamarinios10+MonoTouch10\PInvoke.Kernel32.dll
-
-
- ..\..\..\..\packages\PInvoke.BCrypt.0.3.2\lib\portable-net45+win+wpa81+MonoAndroid10+xamarinios10+MonoTouch10\PInvoke.BCrypt.dll
-
-
- ..\..\..\..\packages\PInvoke.NCrypt.0.3.2\lib\portable-net45+win+wpa81+MonoAndroid10+xamarinios10+MonoTouch10\PInvoke.NCrypt.dll
-
-
- ..\..\..\..\packages\Validation.2.2.8\lib\dotnet\Validation.dll
-
-
- ..\..\..\..\packages\PCLCrypto.2.0.147\lib\xamarinios10\PCLCrypto.dll
-
-
- ..\..\..\..\packages\IdentityModel.3.0.0\lib\netstandard2.0\IdentityModel.dll
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- false
-
-
- false
-
-
- false
-
-
- false
-
-
- false
-
-
- false
-
-
- false
-
-
- false
-
-
- false
-
-
- false
-
-
- false
-
-
- false
-
-
- false
-
-
- false
-
-
- false
-
-
- false
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {76C5F2A7-6CD5-49EA-9F33-EC44DE6539C7}
- eShopOnContainers.Core
-
-
-
-
-
-
-
-
-
-
- This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
-
-
-
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.iOS/packages.config b/src/Mobile/eShopOnContainers/eShopOnContainers.iOS/packages.config
index 86db43622..c7802a448 100644
--- a/src/Mobile/eShopOnContainers/eShopOnContainers.iOS/packages.config
+++ b/src/Mobile/eShopOnContainers/eShopOnContainers.iOS/packages.config
@@ -7,7 +7,7 @@
-
+
@@ -67,5 +67,5 @@
-
+
\ No newline at end of file
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.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
{
- 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;
-
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();
+
+ 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();
- RegisterAppInsights(services);
+ 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());
-
- }
-
- public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
- {
- //Configure logs
-
- 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);
+ return services;
}
- private void RegisterAppInsights(IServiceCollection services)
+ public static IServiceCollection AddEventBus(this IServiceCollection services, IConfiguration configuration)
{
- services.AddApplicationInsightsTelemetry(Configuration);
- var orchestratorType = Configuration.GetValue("OrchestratorType");
+ var subscriptionClientName = configuration["SubscriptionClientName"];
- 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,8 +48,110 @@
public IServiceProvider ConfigureServices(IServiceCollection services)
{
- RegisterAppInsights(services);
+ services.AddApplicationInsights(Configuration)
+ .AddCustomMvc()
+ .AddHealthChecks(Configuration)
+ .AddCustomDbContext(Configuration)
+ .AddCustomSwagger(Configuration)
+ .AddCustomIntegrations(Configuration)
+ .AddCustomConfiguration(Configuration)
+ .AddEventBus(Configuration)
+ .AddCustomAuthentication(Configuration);
+ //configure autofac
+
+ var container = new ContainerBuilder();
+ container.Populate(services);
+
+ container.RegisterModule(new MediatorModule());
+ container.RegisterModule(new ApplicationModule(Configuration["ConnectionString"]));
+
+ return new AutofacServiceProvider(container.Build());
+ }
+
+
+ public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory)
+ {
+ 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");
+
+ ConfigureAuth(app);
+
+ app.UseMvcWithDefaultRoute();
+
+ app.UseSwagger()
+ .UseSwaggerUI(c =>
+ {
+ c.SwaggerEndpoint($"{ (!string.IsNullOrEmpty(pathBase) ? pathBase : string.Empty) }/swagger/v1/swagger.json", "Ordering.API V1");
+ c.OAuthClientId("orderingswaggerui");
+ c.OAuthAppName("Ordering Swagger UI");
+ });
+
+ ConfigureEventBus(app);
+ }
+
+
+ private void ConfigureEventBus(IApplicationBuilder app)
+ {
+ var eventBus = app.ApplicationServices.GetRequiredService();
+
+ eventBus.Subscribe>();
+ eventBus.Subscribe>();
+ eventBus.Subscribe>();
+ eventBus.Subscribe>();
+ eventBus.Subscribe>();
+ eventBus.Subscribe>();
+ }
+
+
+ protected virtual void ConfigureAuth(IApplicationBuilder app)
+ {
+ if (Configuration.GetValue("UseLoadTest"))
+ {
+ app.UseMiddleware();
+ }
+
+ app.UseAuthentication();
+ }
+ }
+
+ static class CustomExtensionsMethods
+ {
+ public static IServiceCollection AddApplicationInsights(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)
+ {
// Add framework services.
services.AddMvc(options =>
{
@@ -56,34 +159,51 @@
}).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.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))
+ if (int.TryParse(configuration["HealthCheck:Timeout"], out var minutesParsed))
{
minutes = minutesParsed;
}
- checks.AddSqlCheck("OrderingDb", Configuration["ConnectionString"], TimeSpan.FromMinutes(minutes));
+ 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)
- );
+ .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"],
+ options.UseSqlServer(configuration["ConnectionString"],
sqlServerOptionsAction: sqlOptions =>
{
sqlOptions.MigrationsAssembly(typeof(Startup).GetTypeInfo().Assembly.GetName().Name);
@@ -91,10 +211,12 @@
sqlOptions.EnableRetryOnFailure(maxRetryCount: 10, maxRetryDelay: TimeSpan.FromSeconds(30), errorNumbersToAdd: null);
});
});
-
- services.Configure(Configuration);
+ return services;
+ }
+ public static IServiceCollection AddCustomSwagger(this IServiceCollection services, IConfiguration configuration)
+ {
services.AddSwaggerGen(options =>
{
options.DescribeAllEnumsAsStrings();
@@ -110,8 +232,8 @@
{
Type = "oauth2",
Flow = "implicit",
- AuthorizationUrl = $"{Configuration.GetValue("IdentityUrlExternal")}/connect/authorize",
- TokenUrl = $"{Configuration.GetValue("IdentityUrlExternal")}/connect/token",
+ AuthorizationUrl = $"{configuration.GetValue("IdentityUrlExternal")}/connect/authorize",
+ TokenUrl = $"{configuration.GetValue("IdentityUrlExternal")}/connect/token",
Scopes = new Dictionary()
{
{ "orders", "Ordering API" }
@@ -121,16 +243,11 @@
options.OperationFilter();
});
- services.AddCors(options =>
- {
- options.AddPolicy("CorsPolicy",
- builder => builder.AllowAnyOrigin()
- .AllowAnyMethod()
- .AllowAnyHeader()
- .AllowCredentials());
- });
+ return services;
+ }
- // Add application services.
+ public static IServiceCollection AddCustomIntegrations(this IServiceCollection services, IConfiguration configuration)
+ {
services.AddSingleton();
services.AddTransient();
services.AddTransient>(
@@ -138,13 +255,13 @@
services.AddTransient();
- if (Configuration.GetValue("AzureServiceBusEnabled"))
+ if (configuration.GetValue("AzureServiceBusEnabled"))
{
services.AddSingleton(sp =>
{
var logger = sp.GetRequiredService>();
- var serviceBusConnectionString = Configuration["EventBusConnection"];
+ var serviceBusConnectionString = configuration["EventBusConnection"];
var serviceBusConnection = new ServiceBusConnectionStringBuilder(serviceBusConnectionString);
return new DefaultServiceBusPersisterConnection(serviceBusConnection, logger);
@@ -159,152 +276,69 @@
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);
- ConfigureAuthService(services);
- services.AddOptions();
-
- //configure autofac
-
- var container = new ContainerBuilder();
- container.Populate(services);
-
- container.RegisterModule(new MediatorModule());
- container.RegisterModule(new ApplicationModule(Configuration["ConnectionString"]));
-
- return new AutofacServiceProvider(container.Build());
- }
-
-
- public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory)
- {
- 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");
-
- ConfigureAuth(app);
-
- app.UseMvcWithDefaultRoute();
-
- app.UseSwagger()
- .UseSwaggerUI(c =>
- {
- c.SwaggerEndpoint($"{ (!string.IsNullOrEmpty(pathBase) ? pathBase : string.Empty) }/swagger/v1/swagger.json", "Ordering.API V1");
- c.OAuthClientId("orderingswaggerui");
- c.OAuthAppName("Ordering Swagger UI");
- });
-
- 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());
- }
+ return services;
}
- private void ConfigureEventBus(IApplicationBuilder app)
+ public static IServiceCollection AddCustomConfiguration(this IServiceCollection services, IConfiguration configuration)
{
- var eventBus = app.ApplicationServices.GetRequiredService();
-
- eventBus.Subscribe>();
- eventBus.Subscribe>();
- eventBus.Subscribe>();
- eventBus.Subscribe>();
- eventBus.Subscribe>();
- 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 =>
+ services.AddOptions();
+ services.Configure(configuration);
+ services.Configure(options =>
{
- options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
- options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
+ 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."
+ };
- }).AddJwtBearer(options =>
- {
- options.Authority = identityUrl;
- options.RequireHttpsMetadata = false;
- options.Audience = "orders";
+ return new BadRequestObjectResult(problemDetails)
+ {
+ ContentTypes = { "application/problem+json", "application/problem+xml" }
+ };
+ };
});
- }
-
- protected virtual void ConfigureAuth(IApplicationBuilder app)
- {
- if (Configuration.GetValue("UseLoadTest"))
- {
- app.UseMiddleware();
- }
- app.UseAuthentication();
+ return services;
}
- private void RegisterEventBus(IServiceCollection services)
+ public static IServiceCollection AddEventBus(this IServiceCollection services, IConfiguration configuration)
{
- var subscriptionClientName = Configuration["SubscriptionClientName"];
+ var subscriptionClientName = configuration["SubscriptionClientName"];
- if (Configuration.GetValue("AzureServiceBusEnabled"))
+ 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 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();
@@ -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 responseString = await _httpClient.GetStringAsync(uri);
- var dataString = await _apiClient.GetStringAsync(allMyOrdersUri, token);
- var response = JsonConvert.DeserializeObject>(dataString);
+ 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