# Conflicts:
#	eShopOnContainers-ServicesAndWebApps.sln
#	k8s/deployments.yaml
#	k8s/gen-k8s-env-aks.ps1
#	k8s/internalurls.yaml
#	k8s/ocelot/configuration-web-shopping.json
#	src/ApiGateways/ApiGw-Base/Program.cs
#	src/ApiGateways/Mobile.Bff.Shopping/apigw/configuration.json
#	src/ApiGateways/Web.Bff.Shopping/apigw/configuration.json
#	src/Services/Identity/Identity.API/Configuration/Config.cs
#	src/Services/Identity/Identity.API/Data/ConfigurationDbContextSeed.cs
#	src/Services/Ordering/Ordering.Domain/AggregatesModel/OrderAggregate/Order.cs
#	src/Web/WebMVC/AppSettings.cs
#	src/Web/WebMVC/Startup.cs
#	src/Web/WebSPA/AppSettings.cs
#	src/Web/WebSPA/Client/modules/shared/models/configuration.model.ts
#	src/Web/WebSPA/Client/modules/shared/services/configuration.service.ts
#	src/Web/WebSPA/Client/modules/shared/services/security.service.ts
This commit is contained in:
ddrsql 2018-05-24 18:02:28 +08:00
commit 91103a4a01
129 changed files with 10161 additions and 624 deletions

View File

@ -28,5 +28,7 @@ cli-linux
**/node_modules/ **/node_modules/
**/bower_components/ **/bower_components/
**/wwwroot/lib/ **/wwwroot/lib/
!**/wwwroot/lib/signalr/*
!**/wwwroot/lib/toastr/*
global.json global.json
src/Web/WebSPA/wwwroot/ src/Web/WebSPA/wwwroot/

2
.gitignore vendored
View File

@ -27,6 +27,8 @@ bld/
.vs/ .vs/
# Uncomment if you have tasks that create the project's static files in wwwroot # Uncomment if you have tasks that create the project's static files in wwwroot
**/wwwroot/lib/ **/wwwroot/lib/
!/wwwroot/lib/signalr
!/wwwroot/lib/toastr
# MSTest test Results # MSTest test Results
[Tt]est[Rr]esult*/ [Tt]est[Rr]esult*/

View File

@ -2,10 +2,7 @@
Sample .NET Core reference application, powered by Microsoft, based on a simplified microservices architecture and Docker containers. Sample .NET Core reference application, powered by Microsoft, based on a simplified microservices architecture and Docker containers.
## IMPORTANT NOTES! ## IMPORTANT NOTES!
**Since April 5 2018, Visual Studio 2017 15.7 Preview 2.0 or later is needed to run the solution from the *[DEV branch](https://github.com/dotnet-architecture/eShopOnContainers/tree/dev)* (current evolving code) which now includes API Gateways features**. Due to the configuration used in `docker-compose.yml` file, VS 15.7 (currently in Preview 2) is needed to run the solution at [DEV branch](https://github.com/dotnet-architecture/eShopOnContainers/tree/dev) or you can also run eShopOnContainers with Docker CLI with **"docker-compose up"** or deploying to **Kubernetes/AKS**. **The current supported Visual Studio version for eShopOnContainers is Visual Studio 2017 15.7** ([GA/RTM since May 8th 2018](https://docs.microsoft.com/en-us/visualstudio/releasenotes/vs2017-relnotes)) or later version.
Trying to run the solution from [DEV branch](https://github.com/dotnet-architecture/eShopOnContainers/tree/dev) in VS 15.6 (current RTM of Visual Studio 2017) will generate errors (complaining about invalid values in docker-compose file).
If you want/need to run eShopOnContainers in **Visual Studio 2017 15.6 RTM** or previous, you'll need to use the code at the **[MASTER branch](https://github.com/dotnet-architecture/eShopOnContainers/tree/master)** which is the previous stable version of eShopOnContainers.
**Note for Pull Requests (PRs)**: We accept pull request from the community. When doing it, please do it onto the **DEV branch** which is the consolidated work-in-progress branch. Do not request it onto Master branch, if possible. **Note for Pull Requests (PRs)**: We accept pull request from the community. When doing it, please do it onto the **DEV branch** which is the consolidated work-in-progress branch. Do not request it onto Master branch, if possible.
@ -28,8 +25,9 @@ For a list on the new .NET Core 2.0 related implemented features, see this [blog
However, this sample application should not be considered as an "eCommerce reference model", at all. The implemented business domain might not be ideal from an eCommerce business point of view. It is neither trying to solve all the problems in a large, scalable and mission-critical distributed system. It is just a bootstrap for developers to easily get started in the world of Docker containers and microservices with .NET Core. However, this sample application should not be considered as an "eCommerce reference model", at all. The implemented business domain might not be ideal from an eCommerce business point of view. It is neither trying to solve all the problems in a large, scalable and mission-critical distributed system. It is just a bootstrap for developers to easily get started in the world of Docker containers and microservices with .NET Core.
> <p>For example, the next step after running the solution in the local dev PC and understanding Docker containers and microservices development with .NET Core, is to select a microservice cluster/orchestrator like Kubernetes in Azure (AKS) or Azure Service Fabric, both environments tested and supported by this solution. > <p>For example, the next step after running the solution in the local dev PC and understanding Docker containers and microservices development with .NET Core, is to select a microservice cluster/orchestrator like Kubernetes in Azure (AKS) or Azure Service Fabric, both environments tested and supported by this solution.
> Additional steps would be to move your databases to HA cloud services (like Azure SQL Database), or switch your EventBus to use Azure Service Bus (instead of bare-bone RabbitMQ) or any other production ready Service Bus in the market. > Additional steps would be to move your databases to HA cloud services (like Azure SQL Database), or switch your EventBus to use Azure Service Bus (instead of bare-bone RabbitMQ) or any other production ready Service Bus in the market.
> <p>
> <img src="img/exploring-to-production-ready.png"> ![image](https://user-images.githubusercontent.com/1712635/40397331-059a7ec6-5de7-11e8-8542-a597eca16fef.png)
> Read the planned <a href='https://github.com/dotnet/eShopOnContainers/wiki/01.-Roadmap-and-Milestones-for-future-releases'>Roadmap and Milestones for future releases of eShopOnContainers</a> within the Wiki for further info about possible new implementations and provide feedback at the <a href='https://github.com/dotnet/eShopOnContainers/issues'>ISSUES section</a> if you'd like to see any specific scenario implemented or improved. Also, feel free to discuss on any current issue. > Read the planned <a href='https://github.com/dotnet/eShopOnContainers/wiki/01.-Roadmap-and-Milestones-for-future-releases'>Roadmap and Milestones for future releases of eShopOnContainers</a> within the Wiki for further info about possible new implementations and provide feedback at the <a href='https://github.com/dotnet/eShopOnContainers/issues'>ISSUES section</a> if you'd like to see any specific scenario implemented or improved. Also, feel free to discuss on any current issue.
### Architecture overview ### Architecture overview

View File

@ -0,0 +1,37 @@
Param(
[parameter(Mandatory=$false)][string]$acrName,
[parameter(Mandatory=$false)][string]$gitUser,
[parameter(Mandatory=$false)][string]$repoName="eShopOnContainers",
[parameter(Mandatory=$false)][string]$gitBranch="dev",
[parameter(Mandatory=$true)][string]$patToken
)
$gitContext = "https://github.com/$gitUser/$repoName"
$services = @(
@{ Name="eshopbasket"; Image="eshop/basket.api"; File="src/Services/Basket/Basket.API/Dockerfile" },
@{ Name="eshopcatalog"; Image="eshop/catalog.api"; File="src/Services/Catalog/Catalog.API/Dockerfile" },
@{ Name="eshopidentity"; Image="eshop/identity.api"; File="src/Services/Identity/Identity.API/Dockerfile" },
@{ Name="eshopordering"; Image="eshop/ordering.api"; File="src/Services/Ordering/Ordering.API/Dockerfile" },
@{ Name="eshoporderingbg"; Image="eshop/ordering.backgroundtasks"; File="src/Services/Ordering/Ordering.BackgroundTasks/Dockerfile" },
@{ Name="eshopmarketing"; Image="eshop/marketing.api"; File="src/Services/Marketing/Marketing.API/Dockerfile" },
@{ Name="eshopwebspa"; Image="eshop/webspa"; File="src/Web/WebSPA/Dockerfile" },
@{ Name="eshopwebmvc"; Image="eshop/webmvc"; File="src/Web/WebMVC/Dockerfile" },
@{ Name="eshopwebstatus"; Image="eshop/webstatus"; File="src/Web/WebStatus/Dockerfile" },
@{ Name="eshoppayment"; Image="eshop/payment.api"; File="src/Services/Payment/Payment.API/Dockerfile" },
@{ Name="eshoplocations"; Image="eshop/locations.api"; File="src/Services/Location/Locations.API/Dockerfile" },
@{ Name="eshopocelotapigw"; Image="eshop/ocelotapigw"; File="src/ApiGateways/ApiGw-Base/Dockerfile" },
@{ Name="eshopmobileshoppingagg"; Image="eshop/mobileshoppingagg"; File="src/ApiGateways/Mobile.Bff.Shopping/aggregator/Dockerfile" },
@{ Name="eshopwebshoppingagg"; Image="eshop/webshoppingagg"; File="src/ApiGateways/Web.Bff.Shopping/aggregator/Dockerfile" },
@{ Name="eshoporderingsignalrhub"; Image="eshop/ordering.signalrhub"; File="src/Services/Ordering/Ordering.SignalrHub/Dockerfile" }
)
$services |% {
$bname = $_.Name
$bimg = $_.Image
$bfile = $_.File
Write-Host "Setting ACR build $bname ($bimg)"
az acr build-task create --registry $acrName --name $bname --image ${bimg}:$gitBranch --context $gitContext --branch $gitBranch --git-access-token $patToken --file $bfile
}
# Basket.API

View File

@ -46,6 +46,16 @@ services:
- sql.data - sql.data
- rabbitmq - rabbitmq
ordering.signalrhub:
image: eshop/ordering.signalrhub:${TAG:-latest}
build:
context: .
dockerfile: src/Services/Ordering/Ordering.SignalrHub/Dockerfile
depends_on:
- sql.data
- identity.api
- rabbitmq
marketing.api: marketing.api:
image: eshop/marketing.api-win:${TAG:-latest} image: eshop/marketing.api-win:${TAG:-latest}
build: build:

View File

@ -1,19 +0,0 @@
version: '3.4'
services:
ci-build:
image: microsoft/aspnetcore-build:2.0.2 #Depending on the bug below, you can also try this other SDK image: microsoft/aspnetcore-build:1.0-2.0-2017-10 or microsoft/aspnetcore-build:1.0-2.0
volumes:
- .:/src
- ./cli-linux:/cli-linux
working_dir: /src
# Next line is using the .sln file to compile all the projects.
# Sometime there is an issue in msbuild exits the process before finishing building the bits: (https://github.com/Microsoft/msbuild/issues/2153)
# Random error: error MSB4017: The build stopped unexpectedly be cause of an unexpected logger failure.
command: /bin/bash -c "pushd ./src/Web/WebSPA && npm rebuild node-sass && popd && dotnet publish ./eShopOnContainers-ServicesAndWebApps.sln -c Release -o ./obj/Docker/publish"
# NOTE: Using build-bits-linux.sh from Linux build container exits before ending.
#command: /bin/bash -c "pushd ./src/Web/WebSPA && npm rebuild node-sass && popd && pushd /cli-linux && ./build-bits-linux.sh /src"

View File

@ -10,7 +10,6 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<None Include=".dockerignore" /> <None Include=".dockerignore" />
<None Include="docker-compose.ci.build.yml" />
<None Include="docker-compose.override.yml"> <None Include="docker-compose.override.yml">
<DependentUpon>docker-compose.yml</DependentUpon> <DependentUpon>docker-compose.yml</DependentUpon>
</None> </None>

View File

@ -54,5 +54,10 @@ services:
locations.api: locations.api:
environment: environment:
- EventBusUserName=admin
- EventBusPassword=password
ordering.signalrhub:
environment:
- EventBusUserName=admin - EventBusUserName=admin
- EventBusPassword=password - EventBusPassword=password

View File

@ -88,6 +88,25 @@ services:
- "5102:80" # Important: In a production environment your should remove the external port (5102) kept here for microservice debugging purposes. - "5102:80" # Important: In a production environment your should remove the external port (5102) kept here for microservice debugging purposes.
# The API Gateway redirects and access through the internal port (80). # The API Gateway redirects and access through the internal port (80).
ordering.backgroundtasks:
environment:
- ASPNETCORE_ENVIRONMENT=Development
- ASPNETCORE_URLS=http://0.0.0.0:80
- ConnectionString=${ESHOP_AZURE_ORDERING_DB:-Server=sql.data;Database=Microsoft.eShopOnContainers.Services.OrderingDb;User Id=sa;Password=Pass@word}
- EventBusConnection=${ESHOP_AZURE_SERVICE_BUS:-rabbitmq}
- EventBusUserName=${ESHOP_SERVICE_BUS_USERNAME}
- EventBusPassword=${ESHOP_SERVICE_BUS_PASSWORD}
- UseCustomizationData=True
- AzureServiceBusEnabled=False
- CheckUpdateTime=30000
- GracePeriodTime=1
- ApplicationInsights__InstrumentationKey=${INSTRUMENTATION_KEY}
- OrchestratorType=${ORCHESTRATOR_TYPE}
- UseLoadTest=${USE_LOADTEST:-False}
ports:
- "5111:80"
marketing.api: marketing.api:
environment: environment:
- ASPNETCORE_ENVIRONMENT=Development - ASPNETCORE_ENVIRONMENT=Development
@ -119,7 +138,7 @@ services:
- ASPNETCORE_URLS=http://0.0.0.0:80 - ASPNETCORE_URLS=http://0.0.0.0:80
- IdentityUrl=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5105 #Local: You need to open your local dev-machine firewall at range 5100-5105. at range 5100-5105. - IdentityUrl=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5105 #Local: You need to open your local dev-machine firewall at range 5100-5105. at range 5100-5105.
- PurchaseUrl=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5202 - PurchaseUrl=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5202
- MarketingUrl=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5203 - MarketingUrl=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5203
- CatalogUrlHC=http://catalog.api/hc - CatalogUrlHC=http://catalog.api/hc
- OrderingUrlHC=http://ordering.api/hc - OrderingUrlHC=http://ordering.api/hc
- IdentityUrlHC=http://identity.api/hc #Local: Use ${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}, if using external IP or DNS name from browser. - IdentityUrlHC=http://identity.api/hc #Local: Use ${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}, if using external IP or DNS name from browser.
@ -129,6 +148,7 @@ services:
- UseCustomizationData=True - UseCustomizationData=True
- ApplicationInsights__InstrumentationKey=${INSTRUMENTATION_KEY} - ApplicationInsights__InstrumentationKey=${INSTRUMENTATION_KEY}
- OrchestratorType=${ORCHESTRATOR_TYPE} - OrchestratorType=${ORCHESTRATOR_TYPE}
- SignalrHubUrl=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5202
ports: ports:
- "5104:80" - "5104:80"
@ -145,6 +165,7 @@ services:
- BasketUrlHC=http://basket.api/hc - BasketUrlHC=http://basket.api/hc
- MarketingUrlHC=http://marketing.api/hc - MarketingUrlHC=http://marketing.api/hc
- PaymentUrlHC=http://payment.api/hc - PaymentUrlHC=http://payment.api/hc
- SignalrHubUrl=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5202
- UseCustomizationData=True - UseCustomizationData=True
- ApplicationInsights__InstrumentationKey=${INSTRUMENTATION_KEY} - ApplicationInsights__InstrumentationKey=${INSTRUMENTATION_KEY}
- OrchestratorType=${ORCHESTRATOR_TYPE} - OrchestratorType=${ORCHESTRATOR_TYPE}
@ -158,6 +179,7 @@ services:
- ASPNETCORE_URLS=http://0.0.0.0:80 - ASPNETCORE_URLS=http://0.0.0.0:80
- CatalogUrl=http://catalog.api/hc - CatalogUrl=http://catalog.api/hc
- OrderingUrl=http://ordering.api/hc - OrderingUrl=http://ordering.api/hc
- OrderingBackgroundTasksUrl=http://ordering.backgroundtasks/hc
- BasketUrl=http://basket.api/hc - BasketUrl=http://basket.api/hc
- IdentityUrl=http://identity.api/hc - IdentityUrl=http://identity.api/hc
- LocationsUrl=http://locations.api/hc - LocationsUrl=http://locations.api/hc
@ -202,6 +224,7 @@ services:
ports: ports:
- "5109:80" # Important: In a production environment your should remove the external port (5109) kept here for microservice debugging purposes. - "5109:80" # Important: In a production environment your should remove the external port (5109) kept here for microservice debugging purposes.
# The API Gateway redirects and access through the internal port (80). # The API Gateway redirects and access through the internal port (80).
sql.data: sql.data:
environment: environment:
@ -279,4 +302,18 @@ services:
- urls__identity=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5110. - urls__identity=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5110.
ports: ports:
- "5121:80" # Important: In a production environment your should remove the external port (5121) kept here for microservice debugging purposes. - "5121:80" # Important: In a production environment your should remove the external port (5121) kept here for microservice debugging purposes.
# The API Gateway redirects and access through the internal port (80). # The API Gateway redirects and access through the internal port (80).
ordering.signalrhub:
environment:
- ASPNETCORE_ENVIRONMENT=Development
- ASPNETCORE_URLS=http://0.0.0.0:80
- EventBusConnection=${ESHOP_AZURE_SERVICE_BUS:-rabbitmq}
- EventBusUserName=${ESHOP_SERVICE_BUS_USERNAME}
- EventBusPassword=${ESHOP_SERVICE_BUS_PASSWORD}
- AzureServiceBusEnabled=False
- ApplicationInsights__InstrumentationKey=${INSTRUMENTATION_KEY}
- OrchestratorType=${ORCHESTRATOR_TYPE}
- identityUrl=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5110.
ports:
- "5112:80"

View File

@ -92,6 +92,25 @@ services:
ports: ports:
- "80" # The API Gateway redirects and access through the internal port (80). - "80" # The API Gateway redirects and access through the internal port (80).
ordering.backgroundtasks:
environment:
- ASPNETCORE_ENVIRONMENT=Development
- ASPNETCORE_URLS=http://0.0.0.0:80
- ConnectionString=${ESHOP_AZURE_ORDERING_DB:-Server=sql.data;Database=Microsoft.eShopOnContainers.Services.OrderingDb;User Id=sa;Password=Pass@word}
- EventBusConnection=${ESHOP_AZURE_SERVICE_BUS:-rabbitmq}
- EventBusUserName=${ESHOP_SERVICE_BUS_USERNAME}
- EventBusPassword=${ESHOP_SERVICE_BUS_PASSWORD}
- UseCustomizationData=True
- AzureServiceBusEnabled=False
- CheckUpdateTime=30000
- GracePeriodTime=1
- ApplicationInsights__InstrumentationKey=${INSTRUMENTATION_KEY}
- OrchestratorType=${ORCHESTRATOR_TYPE}
- UseLoadTest=${USE_LOADTEST:-False}
ports:
- "5111:80"
marketing.api: marketing.api:
environment: environment:
- ASPNETCORE_ENVIRONMENT=Development - ASPNETCORE_ENVIRONMENT=Development
@ -161,6 +180,7 @@ services:
- ASPNETCORE_URLS=http://0.0.0.0:80 - ASPNETCORE_URLS=http://0.0.0.0:80
- CatalogUrl=http://catalog.api/hc - CatalogUrl=http://catalog.api/hc
- OrderingUrl=http://ordering.api/hc - OrderingUrl=http://ordering.api/hc
- OrderingBackgroundTasksUrl=http://ordering.backgroundtasks/hc
- BasketUrl=http://basket.api/hc - BasketUrl=http://basket.api/hc
- IdentityUrl=http://identity.api/hc - IdentityUrl=http://identity.api/hc
- LocationsUrl=http://locations.api/hc - LocationsUrl=http://locations.api/hc

View File

@ -38,6 +38,15 @@ services:
- sql.data - sql.data
- rabbitmq - rabbitmq
ordering.backgroundtasks:
image: eshop/ordering.backgroundtasks:${TAG:-latest}
build:
context: .
dockerfile: src/Services/Ordering/Ordering.BackgroundTasks/Dockerfile
depends_on:
- sql.data
- rabbitmq
marketing.api: marketing.api:
image: eshop/marketing.api:${TAG:-latest} image: eshop/marketing.api:${TAG:-latest}
build: build:
@ -144,3 +153,9 @@ services:
context: . context: .
dockerfile: src/ApiGateways/Web.Bff.Shopping/aggregator/Dockerfile dockerfile: src/ApiGateways/Web.Bff.Shopping/aggregator/Dockerfile
ordering.signalrhub:
image: eshop/ordering.signalrhub:${TAG:-latest}
build:
context: .
dockerfile: src/Services/Ordering/Ordering.SignalrHub/Dockerfile

View File

@ -1,7 +1,7 @@
 
Microsoft Visual Studio Solution File, Format Version 12.00 Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15 # Visual Studio 15
VisualStudioVersion = 15.0.27130.2024 VisualStudioVersion = 15.0.27130.2027
MinimumVisualStudioVersion = 10.0.40219.1 MinimumVisualStudioVersion = 10.0.40219.1
Project("{E53339B2-1760-4266-BCC7-CA923CBCF16C}") = "docker-compose", "docker-compose.dcproj", "{FEA0C318-FFED-4D39-8781-265718CA43DD}" Project("{E53339B2-1760-4266-BCC7-CA923CBCF16C}") = "docker-compose", "docker-compose.dcproj", "{FEA0C318-FFED-4D39-8781-265718CA43DD}"
EndProject EndProject
@ -98,7 +98,39 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "WebHost", "WebHost", "{1815
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WebHost.Customization", "src\BuildingBlocks\WebHostCustomization\WebHost.Customization\WebHost.Customization.csproj", "{15F4B3AA-89B6-4A0D-9051-414305974781}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WebHost.Customization", "src\BuildingBlocks\WebHostCustomization\WebHost.Customization\WebHost.Customization.csproj", "{15F4B3AA-89B6-4A0D-9051-414305974781}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ordering.BackgroundTasks", "src\Services\Ordering\Ordering.BackgroundTasks\Ordering.BackgroundTasks.csproj", "{2FF56999-0266-48B2-ACC1-FEBC482A5105}" Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ApiGateways", "ApiGateways", "{77849D35-37D4-4802-81DC-9477B2775A40}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ApiGw-Base", "ApiGw-Base", "{EC91ADE9-3D66-4AB2-9FB4-2B585E1F3531}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Mobile.Bff.Marketing", "Mobile.Bff.Marketing", "{DB813A36-11BA-41FE-B258-CA9A7152247B}"
ProjectSection(SolutionItems) = preProject
src\ApiGateways\Mobile.Bff.Marketing\apigw\configuration.json = src\ApiGateways\Mobile.Bff.Marketing\apigw\configuration.json
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Mobile.Bff.Shopping", "Mobile.Bff.Shopping", "{0189E4FB-6E2B-4F2E-9B1D-5473D23FC6DB}"
ProjectSection(SolutionItems) = preProject
src\ApiGateways\Mobile.Bff.Shopping\apigw\configuration.json = src\ApiGateways\Mobile.Bff.Shopping\apigw\configuration.json
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Web.Bff.Marketing", "Web.Bff.Marketing", "{F8F0921C-EE5D-4AED-A4D6-5BF5FAE02CB5}"
ProjectSection(SolutionItems) = preProject
src\ApiGateways\Web.Bff.Marketing\apigw\configuration.json = src\ApiGateways\Web.Bff.Marketing\apigw\configuration.json
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Web.Bff.Shopping", "Web.Bff.Shopping", "{28C0F5C8-4849-4035-80AB-45639424E73F}"
ProjectSection(SolutionItems) = preProject
src\ApiGateways\Web.Bff.Shopping\apigw\configuration.json = src\ApiGateways\Web.Bff.Shopping\apigw\configuration.json
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OcelotApiGw", "src\ApiGateways\ApiGw-Base\OcelotApiGw.csproj", "{3F79558C-485D-49E1-BD3E-E12538D3D308}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Mobile.Shopping.HttpAggregator", "src\ApiGateways\Mobile.Bff.Shopping\aggregator\Mobile.Shopping.HttpAggregator.csproj", "{BEA37D6D-4CF2-4AE8-9575-72388E54FBD0}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Web.Shopping.HttpAggregator", "src\ApiGateways\Web.Bff.Shopping\aggregator\Web.Shopping.HttpAggregator.csproj", "{AF0828DB-8BDD-411A-AEEF-B780FBB8D8C1}"
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}"
EndProject EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
@ -1314,54 +1346,246 @@ Global
{15F4B3AA-89B6-4A0D-9051-414305974781}.Release|x64.Build.0 = Release|Any CPU {15F4B3AA-89B6-4A0D-9051-414305974781}.Release|x64.Build.0 = Release|Any CPU
{15F4B3AA-89B6-4A0D-9051-414305974781}.Release|x86.ActiveCfg = Release|Any CPU {15F4B3AA-89B6-4A0D-9051-414305974781}.Release|x86.ActiveCfg = Release|Any CPU
{15F4B3AA-89B6-4A0D-9051-414305974781}.Release|x86.Build.0 = Release|Any CPU {15F4B3AA-89B6-4A0D-9051-414305974781}.Release|x86.Build.0 = Release|Any CPU
{2FF56999-0266-48B2-ACC1-FEBC482A5105}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU {3F79558C-485D-49E1-BD3E-E12538D3D308}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
{2FF56999-0266-48B2-ACC1-FEBC482A5105}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU {3F79558C-485D-49E1-BD3E-E12538D3D308}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
{2FF56999-0266-48B2-ACC1-FEBC482A5105}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU {3F79558C-485D-49E1-BD3E-E12538D3D308}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU
{2FF56999-0266-48B2-ACC1-FEBC482A5105}.Ad-Hoc|ARM.Build.0 = Debug|Any CPU {3F79558C-485D-49E1-BD3E-E12538D3D308}.Ad-Hoc|ARM.Build.0 = Debug|Any CPU
{2FF56999-0266-48B2-ACC1-FEBC482A5105}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU {3F79558C-485D-49E1-BD3E-E12538D3D308}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
{2FF56999-0266-48B2-ACC1-FEBC482A5105}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU {3F79558C-485D-49E1-BD3E-E12538D3D308}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
{2FF56999-0266-48B2-ACC1-FEBC482A5105}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU {3F79558C-485D-49E1-BD3E-E12538D3D308}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{2FF56999-0266-48B2-ACC1-FEBC482A5105}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU {3F79558C-485D-49E1-BD3E-E12538D3D308}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
{2FF56999-0266-48B2-ACC1-FEBC482A5105}.Ad-Hoc|x64.ActiveCfg = Debug|Any CPU {3F79558C-485D-49E1-BD3E-E12538D3D308}.Ad-Hoc|x64.ActiveCfg = Debug|Any CPU
{2FF56999-0266-48B2-ACC1-FEBC482A5105}.Ad-Hoc|x64.Build.0 = Debug|Any CPU {3F79558C-485D-49E1-BD3E-E12538D3D308}.Ad-Hoc|x64.Build.0 = Debug|Any CPU
{2FF56999-0266-48B2-ACC1-FEBC482A5105}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU {3F79558C-485D-49E1-BD3E-E12538D3D308}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU
{2FF56999-0266-48B2-ACC1-FEBC482A5105}.Ad-Hoc|x86.Build.0 = Debug|Any CPU {3F79558C-485D-49E1-BD3E-E12538D3D308}.Ad-Hoc|x86.Build.0 = Debug|Any CPU
{2FF56999-0266-48B2-ACC1-FEBC482A5105}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU {3F79558C-485D-49E1-BD3E-E12538D3D308}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
{2FF56999-0266-48B2-ACC1-FEBC482A5105}.AppStore|Any CPU.Build.0 = Debug|Any CPU {3F79558C-485D-49E1-BD3E-E12538D3D308}.AppStore|Any CPU.Build.0 = Debug|Any CPU
{2FF56999-0266-48B2-ACC1-FEBC482A5105}.AppStore|ARM.ActiveCfg = Debug|Any CPU {3F79558C-485D-49E1-BD3E-E12538D3D308}.AppStore|ARM.ActiveCfg = Debug|Any CPU
{2FF56999-0266-48B2-ACC1-FEBC482A5105}.AppStore|ARM.Build.0 = Debug|Any CPU {3F79558C-485D-49E1-BD3E-E12538D3D308}.AppStore|ARM.Build.0 = Debug|Any CPU
{2FF56999-0266-48B2-ACC1-FEBC482A5105}.AppStore|iPhone.ActiveCfg = Debug|Any CPU {3F79558C-485D-49E1-BD3E-E12538D3D308}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
{2FF56999-0266-48B2-ACC1-FEBC482A5105}.AppStore|iPhone.Build.0 = Debug|Any CPU {3F79558C-485D-49E1-BD3E-E12538D3D308}.AppStore|iPhone.Build.0 = Debug|Any CPU
{2FF56999-0266-48B2-ACC1-FEBC482A5105}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU {3F79558C-485D-49E1-BD3E-E12538D3D308}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{2FF56999-0266-48B2-ACC1-FEBC482A5105}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU {3F79558C-485D-49E1-BD3E-E12538D3D308}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
{2FF56999-0266-48B2-ACC1-FEBC482A5105}.AppStore|x64.ActiveCfg = Debug|Any CPU {3F79558C-485D-49E1-BD3E-E12538D3D308}.AppStore|x64.ActiveCfg = Debug|Any CPU
{2FF56999-0266-48B2-ACC1-FEBC482A5105}.AppStore|x64.Build.0 = Debug|Any CPU {3F79558C-485D-49E1-BD3E-E12538D3D308}.AppStore|x64.Build.0 = Debug|Any CPU
{2FF56999-0266-48B2-ACC1-FEBC482A5105}.AppStore|x86.ActiveCfg = Debug|Any CPU {3F79558C-485D-49E1-BD3E-E12538D3D308}.AppStore|x86.ActiveCfg = Debug|Any CPU
{2FF56999-0266-48B2-ACC1-FEBC482A5105}.AppStore|x86.Build.0 = Debug|Any CPU {3F79558C-485D-49E1-BD3E-E12538D3D308}.AppStore|x86.Build.0 = Debug|Any CPU
{2FF56999-0266-48B2-ACC1-FEBC482A5105}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {3F79558C-485D-49E1-BD3E-E12538D3D308}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2FF56999-0266-48B2-ACC1-FEBC482A5105}.Debug|Any CPU.Build.0 = Debug|Any CPU {3F79558C-485D-49E1-BD3E-E12538D3D308}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2FF56999-0266-48B2-ACC1-FEBC482A5105}.Debug|ARM.ActiveCfg = Debug|Any CPU {3F79558C-485D-49E1-BD3E-E12538D3D308}.Debug|ARM.ActiveCfg = Debug|Any CPU
{2FF56999-0266-48B2-ACC1-FEBC482A5105}.Debug|ARM.Build.0 = Debug|Any CPU {3F79558C-485D-49E1-BD3E-E12538D3D308}.Debug|ARM.Build.0 = Debug|Any CPU
{2FF56999-0266-48B2-ACC1-FEBC482A5105}.Debug|iPhone.ActiveCfg = Debug|Any CPU {3F79558C-485D-49E1-BD3E-E12538D3D308}.Debug|iPhone.ActiveCfg = Debug|Any CPU
{2FF56999-0266-48B2-ACC1-FEBC482A5105}.Debug|iPhone.Build.0 = Debug|Any CPU {3F79558C-485D-49E1-BD3E-E12538D3D308}.Debug|iPhone.Build.0 = Debug|Any CPU
{2FF56999-0266-48B2-ACC1-FEBC482A5105}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU {3F79558C-485D-49E1-BD3E-E12538D3D308}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{2FF56999-0266-48B2-ACC1-FEBC482A5105}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU {3F79558C-485D-49E1-BD3E-E12538D3D308}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
{2FF56999-0266-48B2-ACC1-FEBC482A5105}.Debug|x64.ActiveCfg = Debug|Any CPU {3F79558C-485D-49E1-BD3E-E12538D3D308}.Debug|x64.ActiveCfg = Debug|Any CPU
{2FF56999-0266-48B2-ACC1-FEBC482A5105}.Debug|x64.Build.0 = Debug|Any CPU {3F79558C-485D-49E1-BD3E-E12538D3D308}.Debug|x64.Build.0 = Debug|Any CPU
{2FF56999-0266-48B2-ACC1-FEBC482A5105}.Debug|x86.ActiveCfg = Debug|Any CPU {3F79558C-485D-49E1-BD3E-E12538D3D308}.Debug|x86.ActiveCfg = Debug|Any CPU
{2FF56999-0266-48B2-ACC1-FEBC482A5105}.Debug|x86.Build.0 = Debug|Any CPU {3F79558C-485D-49E1-BD3E-E12538D3D308}.Debug|x86.Build.0 = Debug|Any CPU
{2FF56999-0266-48B2-ACC1-FEBC482A5105}.Release|Any CPU.ActiveCfg = Release|Any CPU {3F79558C-485D-49E1-BD3E-E12538D3D308}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2FF56999-0266-48B2-ACC1-FEBC482A5105}.Release|Any CPU.Build.0 = Release|Any CPU {3F79558C-485D-49E1-BD3E-E12538D3D308}.Release|Any CPU.Build.0 = Release|Any CPU
{2FF56999-0266-48B2-ACC1-FEBC482A5105}.Release|ARM.ActiveCfg = Release|Any CPU {3F79558C-485D-49E1-BD3E-E12538D3D308}.Release|ARM.ActiveCfg = Release|Any CPU
{2FF56999-0266-48B2-ACC1-FEBC482A5105}.Release|ARM.Build.0 = Release|Any CPU {3F79558C-485D-49E1-BD3E-E12538D3D308}.Release|ARM.Build.0 = Release|Any CPU
{2FF56999-0266-48B2-ACC1-FEBC482A5105}.Release|iPhone.ActiveCfg = Release|Any CPU {3F79558C-485D-49E1-BD3E-E12538D3D308}.Release|iPhone.ActiveCfg = Release|Any CPU
{2FF56999-0266-48B2-ACC1-FEBC482A5105}.Release|iPhone.Build.0 = Release|Any CPU {3F79558C-485D-49E1-BD3E-E12538D3D308}.Release|iPhone.Build.0 = Release|Any CPU
{2FF56999-0266-48B2-ACC1-FEBC482A5105}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU {3F79558C-485D-49E1-BD3E-E12538D3D308}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{2FF56999-0266-48B2-ACC1-FEBC482A5105}.Release|iPhoneSimulator.Build.0 = Release|Any CPU {3F79558C-485D-49E1-BD3E-E12538D3D308}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{2FF56999-0266-48B2-ACC1-FEBC482A5105}.Release|x64.ActiveCfg = Release|Any CPU {3F79558C-485D-49E1-BD3E-E12538D3D308}.Release|x64.ActiveCfg = Release|Any CPU
{2FF56999-0266-48B2-ACC1-FEBC482A5105}.Release|x64.Build.0 = Release|Any CPU {3F79558C-485D-49E1-BD3E-E12538D3D308}.Release|x64.Build.0 = Release|Any CPU
{2FF56999-0266-48B2-ACC1-FEBC482A5105}.Release|x86.ActiveCfg = Release|Any CPU {3F79558C-485D-49E1-BD3E-E12538D3D308}.Release|x86.ActiveCfg = Release|Any CPU
{2FF56999-0266-48B2-ACC1-FEBC482A5105}.Release|x86.Build.0 = Release|Any CPU {3F79558C-485D-49E1-BD3E-E12538D3D308}.Release|x86.Build.0 = Release|Any CPU
{BEA37D6D-4CF2-4AE8-9575-72388E54FBD0}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
{BEA37D6D-4CF2-4AE8-9575-72388E54FBD0}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
{BEA37D6D-4CF2-4AE8-9575-72388E54FBD0}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU
{BEA37D6D-4CF2-4AE8-9575-72388E54FBD0}.Ad-Hoc|ARM.Build.0 = Debug|Any CPU
{BEA37D6D-4CF2-4AE8-9575-72388E54FBD0}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
{BEA37D6D-4CF2-4AE8-9575-72388E54FBD0}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
{BEA37D6D-4CF2-4AE8-9575-72388E54FBD0}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{BEA37D6D-4CF2-4AE8-9575-72388E54FBD0}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
{BEA37D6D-4CF2-4AE8-9575-72388E54FBD0}.Ad-Hoc|x64.ActiveCfg = Debug|Any CPU
{BEA37D6D-4CF2-4AE8-9575-72388E54FBD0}.Ad-Hoc|x64.Build.0 = Debug|Any CPU
{BEA37D6D-4CF2-4AE8-9575-72388E54FBD0}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU
{BEA37D6D-4CF2-4AE8-9575-72388E54FBD0}.Ad-Hoc|x86.Build.0 = Debug|Any CPU
{BEA37D6D-4CF2-4AE8-9575-72388E54FBD0}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
{BEA37D6D-4CF2-4AE8-9575-72388E54FBD0}.AppStore|Any CPU.Build.0 = Debug|Any CPU
{BEA37D6D-4CF2-4AE8-9575-72388E54FBD0}.AppStore|ARM.ActiveCfg = Debug|Any CPU
{BEA37D6D-4CF2-4AE8-9575-72388E54FBD0}.AppStore|ARM.Build.0 = Debug|Any CPU
{BEA37D6D-4CF2-4AE8-9575-72388E54FBD0}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
{BEA37D6D-4CF2-4AE8-9575-72388E54FBD0}.AppStore|iPhone.Build.0 = Debug|Any CPU
{BEA37D6D-4CF2-4AE8-9575-72388E54FBD0}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{BEA37D6D-4CF2-4AE8-9575-72388E54FBD0}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
{BEA37D6D-4CF2-4AE8-9575-72388E54FBD0}.AppStore|x64.ActiveCfg = Debug|Any CPU
{BEA37D6D-4CF2-4AE8-9575-72388E54FBD0}.AppStore|x64.Build.0 = Debug|Any CPU
{BEA37D6D-4CF2-4AE8-9575-72388E54FBD0}.AppStore|x86.ActiveCfg = Debug|Any CPU
{BEA37D6D-4CF2-4AE8-9575-72388E54FBD0}.AppStore|x86.Build.0 = Debug|Any CPU
{BEA37D6D-4CF2-4AE8-9575-72388E54FBD0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BEA37D6D-4CF2-4AE8-9575-72388E54FBD0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BEA37D6D-4CF2-4AE8-9575-72388E54FBD0}.Debug|ARM.ActiveCfg = Debug|Any CPU
{BEA37D6D-4CF2-4AE8-9575-72388E54FBD0}.Debug|ARM.Build.0 = Debug|Any CPU
{BEA37D6D-4CF2-4AE8-9575-72388E54FBD0}.Debug|iPhone.ActiveCfg = Debug|Any CPU
{BEA37D6D-4CF2-4AE8-9575-72388E54FBD0}.Debug|iPhone.Build.0 = Debug|Any CPU
{BEA37D6D-4CF2-4AE8-9575-72388E54FBD0}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{BEA37D6D-4CF2-4AE8-9575-72388E54FBD0}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
{BEA37D6D-4CF2-4AE8-9575-72388E54FBD0}.Debug|x64.ActiveCfg = Debug|Any CPU
{BEA37D6D-4CF2-4AE8-9575-72388E54FBD0}.Debug|x64.Build.0 = Debug|Any CPU
{BEA37D6D-4CF2-4AE8-9575-72388E54FBD0}.Debug|x86.ActiveCfg = Debug|Any CPU
{BEA37D6D-4CF2-4AE8-9575-72388E54FBD0}.Debug|x86.Build.0 = Debug|Any CPU
{BEA37D6D-4CF2-4AE8-9575-72388E54FBD0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BEA37D6D-4CF2-4AE8-9575-72388E54FBD0}.Release|Any CPU.Build.0 = Release|Any CPU
{BEA37D6D-4CF2-4AE8-9575-72388E54FBD0}.Release|ARM.ActiveCfg = Release|Any CPU
{BEA37D6D-4CF2-4AE8-9575-72388E54FBD0}.Release|ARM.Build.0 = Release|Any CPU
{BEA37D6D-4CF2-4AE8-9575-72388E54FBD0}.Release|iPhone.ActiveCfg = Release|Any CPU
{BEA37D6D-4CF2-4AE8-9575-72388E54FBD0}.Release|iPhone.Build.0 = Release|Any CPU
{BEA37D6D-4CF2-4AE8-9575-72388E54FBD0}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{BEA37D6D-4CF2-4AE8-9575-72388E54FBD0}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{BEA37D6D-4CF2-4AE8-9575-72388E54FBD0}.Release|x64.ActiveCfg = Release|Any CPU
{BEA37D6D-4CF2-4AE8-9575-72388E54FBD0}.Release|x64.Build.0 = Release|Any CPU
{BEA37D6D-4CF2-4AE8-9575-72388E54FBD0}.Release|x86.ActiveCfg = Release|Any CPU
{BEA37D6D-4CF2-4AE8-9575-72388E54FBD0}.Release|x86.Build.0 = Release|Any CPU
{AF0828DB-8BDD-411A-AEEF-B780FBB8D8C1}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
{AF0828DB-8BDD-411A-AEEF-B780FBB8D8C1}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
{AF0828DB-8BDD-411A-AEEF-B780FBB8D8C1}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU
{AF0828DB-8BDD-411A-AEEF-B780FBB8D8C1}.Ad-Hoc|ARM.Build.0 = Debug|Any CPU
{AF0828DB-8BDD-411A-AEEF-B780FBB8D8C1}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
{AF0828DB-8BDD-411A-AEEF-B780FBB8D8C1}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
{AF0828DB-8BDD-411A-AEEF-B780FBB8D8C1}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{AF0828DB-8BDD-411A-AEEF-B780FBB8D8C1}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
{AF0828DB-8BDD-411A-AEEF-B780FBB8D8C1}.Ad-Hoc|x64.ActiveCfg = Debug|Any CPU
{AF0828DB-8BDD-411A-AEEF-B780FBB8D8C1}.Ad-Hoc|x64.Build.0 = Debug|Any CPU
{AF0828DB-8BDD-411A-AEEF-B780FBB8D8C1}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU
{AF0828DB-8BDD-411A-AEEF-B780FBB8D8C1}.Ad-Hoc|x86.Build.0 = Debug|Any CPU
{AF0828DB-8BDD-411A-AEEF-B780FBB8D8C1}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
{AF0828DB-8BDD-411A-AEEF-B780FBB8D8C1}.AppStore|Any CPU.Build.0 = Debug|Any CPU
{AF0828DB-8BDD-411A-AEEF-B780FBB8D8C1}.AppStore|ARM.ActiveCfg = Debug|Any CPU
{AF0828DB-8BDD-411A-AEEF-B780FBB8D8C1}.AppStore|ARM.Build.0 = Debug|Any CPU
{AF0828DB-8BDD-411A-AEEF-B780FBB8D8C1}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
{AF0828DB-8BDD-411A-AEEF-B780FBB8D8C1}.AppStore|iPhone.Build.0 = Debug|Any CPU
{AF0828DB-8BDD-411A-AEEF-B780FBB8D8C1}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{AF0828DB-8BDD-411A-AEEF-B780FBB8D8C1}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
{AF0828DB-8BDD-411A-AEEF-B780FBB8D8C1}.AppStore|x64.ActiveCfg = Debug|Any CPU
{AF0828DB-8BDD-411A-AEEF-B780FBB8D8C1}.AppStore|x64.Build.0 = Debug|Any CPU
{AF0828DB-8BDD-411A-AEEF-B780FBB8D8C1}.AppStore|x86.ActiveCfg = Debug|Any CPU
{AF0828DB-8BDD-411A-AEEF-B780FBB8D8C1}.AppStore|x86.Build.0 = Debug|Any CPU
{AF0828DB-8BDD-411A-AEEF-B780FBB8D8C1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AF0828DB-8BDD-411A-AEEF-B780FBB8D8C1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AF0828DB-8BDD-411A-AEEF-B780FBB8D8C1}.Debug|ARM.ActiveCfg = Debug|Any CPU
{AF0828DB-8BDD-411A-AEEF-B780FBB8D8C1}.Debug|ARM.Build.0 = Debug|Any CPU
{AF0828DB-8BDD-411A-AEEF-B780FBB8D8C1}.Debug|iPhone.ActiveCfg = Debug|Any CPU
{AF0828DB-8BDD-411A-AEEF-B780FBB8D8C1}.Debug|iPhone.Build.0 = Debug|Any CPU
{AF0828DB-8BDD-411A-AEEF-B780FBB8D8C1}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{AF0828DB-8BDD-411A-AEEF-B780FBB8D8C1}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
{AF0828DB-8BDD-411A-AEEF-B780FBB8D8C1}.Debug|x64.ActiveCfg = Debug|Any CPU
{AF0828DB-8BDD-411A-AEEF-B780FBB8D8C1}.Debug|x64.Build.0 = Debug|Any CPU
{AF0828DB-8BDD-411A-AEEF-B780FBB8D8C1}.Debug|x86.ActiveCfg = Debug|Any CPU
{AF0828DB-8BDD-411A-AEEF-B780FBB8D8C1}.Debug|x86.Build.0 = Debug|Any CPU
{AF0828DB-8BDD-411A-AEEF-B780FBB8D8C1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AF0828DB-8BDD-411A-AEEF-B780FBB8D8C1}.Release|Any CPU.Build.0 = Release|Any CPU
{AF0828DB-8BDD-411A-AEEF-B780FBB8D8C1}.Release|ARM.ActiveCfg = Release|Any CPU
{AF0828DB-8BDD-411A-AEEF-B780FBB8D8C1}.Release|ARM.Build.0 = Release|Any CPU
{AF0828DB-8BDD-411A-AEEF-B780FBB8D8C1}.Release|iPhone.ActiveCfg = Release|Any CPU
{AF0828DB-8BDD-411A-AEEF-B780FBB8D8C1}.Release|iPhone.Build.0 = Release|Any CPU
{AF0828DB-8BDD-411A-AEEF-B780FBB8D8C1}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{AF0828DB-8BDD-411A-AEEF-B780FBB8D8C1}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{AF0828DB-8BDD-411A-AEEF-B780FBB8D8C1}.Release|x64.ActiveCfg = Release|Any CPU
{AF0828DB-8BDD-411A-AEEF-B780FBB8D8C1}.Release|x64.Build.0 = Release|Any CPU
{AF0828DB-8BDD-411A-AEEF-B780FBB8D8C1}.Release|x86.ActiveCfg = Release|Any CPU
{AF0828DB-8BDD-411A-AEEF-B780FBB8D8C1}.Release|x86.Build.0 = Release|Any CPU
{7D63ED4A-3EDA-4BBA-8BBA-F46BD6430931}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
{7D63ED4A-3EDA-4BBA-8BBA-F46BD6430931}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
{7D63ED4A-3EDA-4BBA-8BBA-F46BD6430931}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU
{7D63ED4A-3EDA-4BBA-8BBA-F46BD6430931}.Ad-Hoc|ARM.Build.0 = Debug|Any CPU
{7D63ED4A-3EDA-4BBA-8BBA-F46BD6430931}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
{7D63ED4A-3EDA-4BBA-8BBA-F46BD6430931}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
{7D63ED4A-3EDA-4BBA-8BBA-F46BD6430931}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{7D63ED4A-3EDA-4BBA-8BBA-F46BD6430931}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
{7D63ED4A-3EDA-4BBA-8BBA-F46BD6430931}.Ad-Hoc|x64.ActiveCfg = Debug|Any CPU
{7D63ED4A-3EDA-4BBA-8BBA-F46BD6430931}.Ad-Hoc|x64.Build.0 = Debug|Any CPU
{7D63ED4A-3EDA-4BBA-8BBA-F46BD6430931}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU
{7D63ED4A-3EDA-4BBA-8BBA-F46BD6430931}.Ad-Hoc|x86.Build.0 = Debug|Any CPU
{7D63ED4A-3EDA-4BBA-8BBA-F46BD6430931}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
{7D63ED4A-3EDA-4BBA-8BBA-F46BD6430931}.AppStore|Any CPU.Build.0 = Debug|Any CPU
{7D63ED4A-3EDA-4BBA-8BBA-F46BD6430931}.AppStore|ARM.ActiveCfg = Debug|Any CPU
{7D63ED4A-3EDA-4BBA-8BBA-F46BD6430931}.AppStore|ARM.Build.0 = Debug|Any CPU
{7D63ED4A-3EDA-4BBA-8BBA-F46BD6430931}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
{7D63ED4A-3EDA-4BBA-8BBA-F46BD6430931}.AppStore|iPhone.Build.0 = Debug|Any CPU
{7D63ED4A-3EDA-4BBA-8BBA-F46BD6430931}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{7D63ED4A-3EDA-4BBA-8BBA-F46BD6430931}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
{7D63ED4A-3EDA-4BBA-8BBA-F46BD6430931}.AppStore|x64.ActiveCfg = Debug|Any CPU
{7D63ED4A-3EDA-4BBA-8BBA-F46BD6430931}.AppStore|x64.Build.0 = Debug|Any CPU
{7D63ED4A-3EDA-4BBA-8BBA-F46BD6430931}.AppStore|x86.ActiveCfg = Debug|Any CPU
{7D63ED4A-3EDA-4BBA-8BBA-F46BD6430931}.AppStore|x86.Build.0 = Debug|Any CPU
{7D63ED4A-3EDA-4BBA-8BBA-F46BD6430931}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7D63ED4A-3EDA-4BBA-8BBA-F46BD6430931}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7D63ED4A-3EDA-4BBA-8BBA-F46BD6430931}.Debug|ARM.ActiveCfg = Debug|Any CPU
{7D63ED4A-3EDA-4BBA-8BBA-F46BD6430931}.Debug|ARM.Build.0 = Debug|Any CPU
{7D63ED4A-3EDA-4BBA-8BBA-F46BD6430931}.Debug|iPhone.ActiveCfg = Debug|Any CPU
{7D63ED4A-3EDA-4BBA-8BBA-F46BD6430931}.Debug|iPhone.Build.0 = Debug|Any CPU
{7D63ED4A-3EDA-4BBA-8BBA-F46BD6430931}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{7D63ED4A-3EDA-4BBA-8BBA-F46BD6430931}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
{7D63ED4A-3EDA-4BBA-8BBA-F46BD6430931}.Debug|x64.ActiveCfg = Debug|Any CPU
{7D63ED4A-3EDA-4BBA-8BBA-F46BD6430931}.Debug|x64.Build.0 = Debug|Any CPU
{7D63ED4A-3EDA-4BBA-8BBA-F46BD6430931}.Debug|x86.ActiveCfg = Debug|Any CPU
{7D63ED4A-3EDA-4BBA-8BBA-F46BD6430931}.Debug|x86.Build.0 = Debug|Any CPU
{7D63ED4A-3EDA-4BBA-8BBA-F46BD6430931}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7D63ED4A-3EDA-4BBA-8BBA-F46BD6430931}.Release|Any CPU.Build.0 = Release|Any CPU
{7D63ED4A-3EDA-4BBA-8BBA-F46BD6430931}.Release|ARM.ActiveCfg = Release|Any CPU
{7D63ED4A-3EDA-4BBA-8BBA-F46BD6430931}.Release|ARM.Build.0 = Release|Any CPU
{7D63ED4A-3EDA-4BBA-8BBA-F46BD6430931}.Release|iPhone.ActiveCfg = Release|Any CPU
{7D63ED4A-3EDA-4BBA-8BBA-F46BD6430931}.Release|iPhone.Build.0 = Release|Any CPU
{7D63ED4A-3EDA-4BBA-8BBA-F46BD6430931}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{7D63ED4A-3EDA-4BBA-8BBA-F46BD6430931}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{7D63ED4A-3EDA-4BBA-8BBA-F46BD6430931}.Release|x64.ActiveCfg = Release|Any CPU
{7D63ED4A-3EDA-4BBA-8BBA-F46BD6430931}.Release|x64.Build.0 = Release|Any CPU
{7D63ED4A-3EDA-4BBA-8BBA-F46BD6430931}.Release|x86.ActiveCfg = Release|Any CPU
{7D63ED4A-3EDA-4BBA-8BBA-F46BD6430931}.Release|x86.Build.0 = Release|Any CPU
{E1D2B260-4E7F-4A88-BC13-9910F7C44623}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
{E1D2B260-4E7F-4A88-BC13-9910F7C44623}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
{E1D2B260-4E7F-4A88-BC13-9910F7C44623}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU
{E1D2B260-4E7F-4A88-BC13-9910F7C44623}.Ad-Hoc|ARM.Build.0 = Debug|Any CPU
{E1D2B260-4E7F-4A88-BC13-9910F7C44623}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
{E1D2B260-4E7F-4A88-BC13-9910F7C44623}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
{E1D2B260-4E7F-4A88-BC13-9910F7C44623}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{E1D2B260-4E7F-4A88-BC13-9910F7C44623}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
{E1D2B260-4E7F-4A88-BC13-9910F7C44623}.Ad-Hoc|x64.ActiveCfg = Debug|Any CPU
{E1D2B260-4E7F-4A88-BC13-9910F7C44623}.Ad-Hoc|x64.Build.0 = Debug|Any CPU
{E1D2B260-4E7F-4A88-BC13-9910F7C44623}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU
{E1D2B260-4E7F-4A88-BC13-9910F7C44623}.Ad-Hoc|x86.Build.0 = Debug|Any CPU
{E1D2B260-4E7F-4A88-BC13-9910F7C44623}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
{E1D2B260-4E7F-4A88-BC13-9910F7C44623}.AppStore|Any CPU.Build.0 = Debug|Any CPU
{E1D2B260-4E7F-4A88-BC13-9910F7C44623}.AppStore|ARM.ActiveCfg = Debug|Any CPU
{E1D2B260-4E7F-4A88-BC13-9910F7C44623}.AppStore|ARM.Build.0 = Debug|Any CPU
{E1D2B260-4E7F-4A88-BC13-9910F7C44623}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
{E1D2B260-4E7F-4A88-BC13-9910F7C44623}.AppStore|iPhone.Build.0 = Debug|Any CPU
{E1D2B260-4E7F-4A88-BC13-9910F7C44623}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{E1D2B260-4E7F-4A88-BC13-9910F7C44623}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
{E1D2B260-4E7F-4A88-BC13-9910F7C44623}.AppStore|x64.ActiveCfg = Debug|Any CPU
{E1D2B260-4E7F-4A88-BC13-9910F7C44623}.AppStore|x64.Build.0 = Debug|Any CPU
{E1D2B260-4E7F-4A88-BC13-9910F7C44623}.AppStore|x86.ActiveCfg = Debug|Any CPU
{E1D2B260-4E7F-4A88-BC13-9910F7C44623}.AppStore|x86.Build.0 = Debug|Any CPU
{E1D2B260-4E7F-4A88-BC13-9910F7C44623}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E1D2B260-4E7F-4A88-BC13-9910F7C44623}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E1D2B260-4E7F-4A88-BC13-9910F7C44623}.Debug|ARM.ActiveCfg = Debug|Any CPU
{E1D2B260-4E7F-4A88-BC13-9910F7C44623}.Debug|ARM.Build.0 = Debug|Any CPU
{E1D2B260-4E7F-4A88-BC13-9910F7C44623}.Debug|iPhone.ActiveCfg = Debug|Any CPU
{E1D2B260-4E7F-4A88-BC13-9910F7C44623}.Debug|iPhone.Build.0 = Debug|Any CPU
{E1D2B260-4E7F-4A88-BC13-9910F7C44623}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{E1D2B260-4E7F-4A88-BC13-9910F7C44623}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
{E1D2B260-4E7F-4A88-BC13-9910F7C44623}.Debug|x64.ActiveCfg = Debug|Any CPU
{E1D2B260-4E7F-4A88-BC13-9910F7C44623}.Debug|x64.Build.0 = Debug|Any CPU
{E1D2B260-4E7F-4A88-BC13-9910F7C44623}.Debug|x86.ActiveCfg = Debug|Any CPU
{E1D2B260-4E7F-4A88-BC13-9910F7C44623}.Debug|x86.Build.0 = Debug|Any CPU
{E1D2B260-4E7F-4A88-BC13-9910F7C44623}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E1D2B260-4E7F-4A88-BC13-9910F7C44623}.Release|Any CPU.Build.0 = Release|Any CPU
{E1D2B260-4E7F-4A88-BC13-9910F7C44623}.Release|ARM.ActiveCfg = Release|Any CPU
{E1D2B260-4E7F-4A88-BC13-9910F7C44623}.Release|ARM.Build.0 = Release|Any CPU
{E1D2B260-4E7F-4A88-BC13-9910F7C44623}.Release|iPhone.ActiveCfg = Release|Any CPU
{E1D2B260-4E7F-4A88-BC13-9910F7C44623}.Release|iPhone.Build.0 = Release|Any CPU
{E1D2B260-4E7F-4A88-BC13-9910F7C44623}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{E1D2B260-4E7F-4A88-BC13-9910F7C44623}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{E1D2B260-4E7F-4A88-BC13-9910F7C44623}.Release|x64.ActiveCfg = Release|Any CPU
{E1D2B260-4E7F-4A88-BC13-9910F7C44623}.Release|x64.Build.0 = Release|Any CPU
{E1D2B260-4E7F-4A88-BC13-9910F7C44623}.Release|x86.ActiveCfg = Release|Any CPU
{E1D2B260-4E7F-4A88-BC13-9910F7C44623}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
@ -1408,7 +1632,17 @@ Global
{969E793C-C413-490E-9C9D-B2B46DA5AF32} = {EF0337F2-ED00-4643-89FD-EE10863F1870} {969E793C-C413-490E-9C9D-B2B46DA5AF32} = {EF0337F2-ED00-4643-89FD-EE10863F1870}
{1815B651-941C-466B-AE33-D1D7EEB8F77F} = {DB0EFB20-B024-4E5E-A75C-52143C131D25} {1815B651-941C-466B-AE33-D1D7EEB8F77F} = {DB0EFB20-B024-4E5E-A75C-52143C131D25}
{15F4B3AA-89B6-4A0D-9051-414305974781} = {1815B651-941C-466B-AE33-D1D7EEB8F77F} {15F4B3AA-89B6-4A0D-9051-414305974781} = {1815B651-941C-466B-AE33-D1D7EEB8F77F}
{2FF56999-0266-48B2-ACC1-FEBC482A5105} = {0BD0DB92-2D98-44D9-9AC0-C59186D59B0B} {77849D35-37D4-4802-81DC-9477B2775A40} = {932D8224-11F6-4D07-B109-DA28AD288A63}
{EC91ADE9-3D66-4AB2-9FB4-2B585E1F3531} = {77849D35-37D4-4802-81DC-9477B2775A40}
{DB813A36-11BA-41FE-B258-CA9A7152247B} = {77849D35-37D4-4802-81DC-9477B2775A40}
{0189E4FB-6E2B-4F2E-9B1D-5473D23FC6DB} = {77849D35-37D4-4802-81DC-9477B2775A40}
{F8F0921C-EE5D-4AED-A4D6-5BF5FAE02CB5} = {77849D35-37D4-4802-81DC-9477B2775A40}
{28C0F5C8-4849-4035-80AB-45639424E73F} = {77849D35-37D4-4802-81DC-9477B2775A40}
{3F79558C-485D-49E1-BD3E-E12538D3D308} = {EC91ADE9-3D66-4AB2-9FB4-2B585E1F3531}
{BEA37D6D-4CF2-4AE8-9575-72388E54FBD0} = {0189E4FB-6E2B-4F2E-9B1D-5473D23FC6DB}
{AF0828DB-8BDD-411A-AEEF-B780FBB8D8C1} = {28C0F5C8-4849-4035-80AB-45639424E73F}
{7D63ED4A-3EDA-4BBA-8BBA-F46BD6430931} = {0BD0DB92-2D98-44D9-9AC0-C59186D59B0B}
{E1D2B260-4E7F-4A88-BC13-9910F7C44623} = {0BD0DB92-2D98-44D9-9AC0-C59186D59B0B}
EndGlobalSection EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {25728519-5F0F-4973-8A64-0A81EB4EA8D9} SolutionGuid = {25728519-5F0F-4973-8A64-0A81EB4EA8D9}

View File

@ -1,5 +1,5 @@
{ {
"sdk": { "sdk": {
"version":"2.1.2" "version": "2.1.4"
} }
} }

View File

@ -4,17 +4,24 @@ The k8s directory contains Kubernetes configuration for the eShopOnContainers ap
## Prerequisites ## Prerequisites
* A Kubernetes cluster. Follow Azure Container Service's [walkthrough](https://docs.microsoft.com/en-us/azure/container-service/container-service-kubernetes-walkthrough) to create one. * A Kubernetes cluster. Follow Azure Container Service's [walkthrough](https://docs.microsoft.com/en-us/azure/container-service/container-service-kubernetes-walkthrough) to create one.
* A private Docker registry. Follow Azure Container Registry's [guide](https://docs.microsoft.com/en-us/azure/container-registry/container-registry-get-started-portal) to create one. * A private Docker registry. Follow Azure Container Registry's [guide](https://docs.microsoft.com/en-us/azure/container-registry/container-registry-get-started-portal) to create one.
* Optionally, previous steps can be skipped if you run gen-k8s-env.ps1 (or gen-k8s-env-aks.ps1 if you would like to use AKS instead of ACS) script to automatically create the azure environment needed for kubernetes deployment. Azure cli 2.0 must be previously installed [installation guide](https://docs.microsoft.com/en-us/cli/azure/install-azure-cli). For example: * Optionally, previous steps can be skipped if you run the **gen-k8s-env-aks.ps1** script to create an AKS cluster environment or gen-k8s-env.ps1 script to create an ACS for Kuberentes cluster environment including the creation of additional Azure environment needed like an Azure Resource Manager and ACR registry.
Azure cli 2.0 must be previously installed [installation guide](https://docs.microsoft.com/en-us/cli/azure/install-azure-cli). For example:
**Important**: Note the parameter "-createAcr true". If you are creating the K8s cluster but you want to re-use and existing ACR, say "-createAcr false". **Important**: Note the parameter "-createAcr true". If you are creating the K8s cluster but you want to re-use and existing ACR, say "-createAcr false".
For AKS:
>```
>./gen-k8s-env-aks -resourceGroupName YoureShopAksResgroup -location centralus -serviceName YoureShopAksCluster -dnsNamePrefix youreshopaks -registryName YoureShopAcrRegistry -createAcr true -nodeCount 3 -nodeVMSize Standard_D2_v2
>```
For ACS:
>``` >```
>./gen-k8s-env -resourceGroupName k8sGroup -location westeurope -registryName k8sregistry -createAcr true -orchestratorName k8s-cluster -dnsName k8s-dns >./gen-k8s-env -resourceGroupName k8sGroup -location westeurope -registryName k8sregistry -createAcr true -orchestratorName k8s-cluster -dnsName k8s-dns
>``` >```
or using AKS instead of ACS
>```
>./gen-k8s-env-aks -resourceGroupName k8sGroup -location westeurope -registryName k8sregistry -dnsName k8s-dns -serviceName k8s-cluster -createAcr true -nodeCount 3 -nodeVMSize Standard_D2_v2
>```
* A Docker development environment with `docker` and `docker-compose`. * A Docker development environment with `docker` and `docker-compose`.
* Visit [docker.com](https://docker.com) to download the tools and set up the environment. Docker's [installation guide](https://docs.docker.com/engine/getstarted/step_one/#step-3-verify-your-installation) covers verifying your Docker installation. * Visit [docker.com](https://docker.com) to download the tools and set up the environment. Docker's [installation guide](https://docs.docker.com/engine/getstarted/step_one/#step-3-verify-your-installation) covers verifying your Docker installation.

72
k8s/build-push-images.ps1 Normal file
View File

@ -0,0 +1,72 @@
Param(
[parameter(Mandatory=$false)][string]$registry,
[parameter(Mandatory=$false)][string]$dockerUser,
[parameter(Mandatory=$false)][string]$dockerPassword,
[parameter(Mandatory=$false)][string]$imageTag,
[parameter(Mandatory=$false)][bool]$buildImages=$true,
[parameter(Mandatory=$false)][bool]$pushImages=$true,
[parameter(Mandatory=$false)][string]$dockerOrg="eshop"
)
# Initialization
$useDockerHub = [string]::IsNullOrEmpty($registry)
# Check required commands (only if not in CI environment)
$requiredCommands = ("docker", "docker-compose")
foreach ($command in $requiredCommands) {
if ((Get-Command $command -ErrorAction SilentlyContinue) -eq $null) {
Write-Host "$command must be on path" -ForegroundColor Red
exit
}
}
# Get tag to use from current branch if no tag is passed
if ([string]::IsNullOrEmpty($imageTag)) {
$imageTag = $(git rev-parse --abbrev-ref HEAD)
}
Write-Host "Docker image Tag: $imageTag" -ForegroundColor Yellow
# Build docker images if needed
if ($buildImages) {
Write-Host "Building Docker images tagged with '$imageTag'" -ForegroundColor Yellow
$env:TAG=$imageTag
docker-compose -p .. -f ../docker-compose.yml build
}
# Login to Docker registry
if (-not [string]::IsNullOrEmpty($dockerUser)) {
$registryFDQN = if (-not $useDockerHub) {$registry} else {"index.docker.io/v1/"}
Write-Host "Logging in to $registryFDQN as user $dockerUser" -ForegroundColor Yellow
if ($useDockerHub) {
docker login -u $dockerUser -p $dockerPassword
}
else {
docker login -u $dockerUser -p $dockerPassword $registryFDQN
}
if (-not $LastExitCode -eq 0) {
Write-Host "Login failed" -ForegroundColor Red
exit
}
}
# Push images to Docker registry
if ($pushImages) {
Write-Host "Pushing images to $registry/$dockerOrg..." -ForegroundColor Yellow
$services = ("basket.api", "catalog.api", "identity.api", "ordering.api", "ordering.backgroundtasks", "marketing.api","payment.api","locations.api", "webmvc", "webspa", "webstatus", "ocelotapigw", "mobileshoppingagg", "webshoppingagg", "ordering.signalrhub")
foreach ($service in $services) {
$imageFqdn = if ($useDockerHub) {"$dockerOrg/${service}"} else {"$registry/$dockerOrg/${service}"}
docker tag eshop/${service}:$imageTag ${imageFqdn}:$imageTag
docker push ${imageFqdn}:$imageTag
}
}

View File

@ -8,6 +8,7 @@ Param(
[parameter(Mandatory=$false)][string]$imageTag, [parameter(Mandatory=$false)][string]$imageTag,
[parameter(Mandatory=$false)][bool]$deployCI=$false, [parameter(Mandatory=$false)][bool]$deployCI=$false,
[parameter(Mandatory=$false)][bool]$buildImages=$true, [parameter(Mandatory=$false)][bool]$buildImages=$true,
[parameter(Mandatory=$false)][bool]$pushImages=$true,
[parameter(Mandatory=$false)][bool]$deployInfrastructure=$true, [parameter(Mandatory=$false)][bool]$deployInfrastructure=$true,
[parameter(Mandatory=$false)][string]$dockerOrg="eshop" [parameter(Mandatory=$false)][string]$dockerOrg="eshop"
) )
@ -63,9 +64,11 @@ if ($buildImages) {
Write-Host "Building Docker images tagged with '$imageTag'" -ForegroundColor Yellow Write-Host "Building Docker images tagged with '$imageTag'" -ForegroundColor Yellow
$env:TAG=$imageTag $env:TAG=$imageTag
docker-compose -p .. -f ../docker-compose.yml build docker-compose -p .. -f ../docker-compose.yml build
}
if ($pushImages) {
Write-Host "Pushing images to $registry/$dockerOrg..." -ForegroundColor Yellow Write-Host "Pushing images to $registry/$dockerOrg..." -ForegroundColor Yellow
$services = ("basket.api", "catalog.api", "identity.api", "ordering.api", "marketing.api","payment.api","locations.api", "webmvc", "webspa", "webstatus", "ocelotapigw", "mobileshoppingagg", "webshoppingagg") $services = ("basket.api", "catalog.api", "identity.api", "ordering.api", "ordering.backgroundtasks", "marketing.api","payment.api","locations.api", "webmvc", "webspa", "webstatus", "ocelotapigw", "mobileshoppingagg", "webshoppingagg", "ordering.signalrhub")
foreach ($service in $services) { foreach ($service in $services) {
$imageFqdn = if ($useDockerHub) {"$dockerOrg/${service}"} else {"$registry/$dockerOrg/${service}"} $imageFqdn = if ($useDockerHub) {"$dockerOrg/${service}"} else {"$registry/$dockerOrg/${service}"}
@ -91,7 +94,10 @@ if (-not [string]::IsNullOrEmpty($dockerUser)) {
exit exit
} }
# create registry key secret # Try to delete the Docker registry key secret
ExecKube -cmd 'delete secret docker-registry registry-key'
# Create the Docker registry key secret
ExecKube -cmd 'create secret docker-registry registry-key ` ExecKube -cmd 'create secret docker-registry registry-key `
--docker-server=$registryFDQN ` --docker-server=$registryFDQN `
--docker-username=$dockerUser ` --docker-username=$dockerUser `
@ -161,12 +167,14 @@ ExecKube -cmd 'set image deployments/basket basket=${registryPath}${dockerOrg}/b
ExecKube -cmd 'set image deployments/catalog catalog=${registryPath}${dockerOrg}/catalog.api:$imageTag' ExecKube -cmd 'set image deployments/catalog catalog=${registryPath}${dockerOrg}/catalog.api:$imageTag'
ExecKube -cmd 'set image deployments/identity identity=${registryPath}${dockerOrg}/identity.api:$imageTag' ExecKube -cmd 'set image deployments/identity identity=${registryPath}${dockerOrg}/identity.api:$imageTag'
ExecKube -cmd 'set image deployments/ordering ordering=${registryPath}${dockerOrg}/ordering.api:$imageTag' ExecKube -cmd 'set image deployments/ordering ordering=${registryPath}${dockerOrg}/ordering.api:$imageTag'
ExecKube -cmd 'set image deployments/ordering-backgroundtasks ordering-backgroundtasks=${registryPath}${dockerOrg}/ordering.backgroundtasks:$imageTag'
ExecKube -cmd 'set image deployments/marketing marketing=${registryPath}${dockerOrg}/marketing.api:$imageTag' ExecKube -cmd 'set image deployments/marketing marketing=${registryPath}${dockerOrg}/marketing.api:$imageTag'
ExecKube -cmd 'set image deployments/locations locations=${registryPath}${dockerOrg}/locations.api:$imageTag' ExecKube -cmd 'set image deployments/locations locations=${registryPath}${dockerOrg}/locations.api:$imageTag'
ExecKube -cmd 'set image deployments/payment payment=${registryPath}${dockerOrg}/payment.api:$imageTag' ExecKube -cmd 'set image deployments/payment payment=${registryPath}${dockerOrg}/payment.api:$imageTag'
ExecKube -cmd 'set image deployments/webmvc webmvc=${registryPath}${dockerOrg}/webmvc:$imageTag' ExecKube -cmd 'set image deployments/webmvc webmvc=${registryPath}${dockerOrg}/webmvc:$imageTag'
ExecKube -cmd 'set image deployments/webstatus webstatus=${registryPath}${dockerOrg}/webstatus:$imageTag' ExecKube -cmd 'set image deployments/webstatus webstatus=${registryPath}${dockerOrg}/webstatus:$imageTag'
ExecKube -cmd 'set image deployments/webspa webspa=${registryPath}${dockerOrg}/webspa:$imageTag' ExecKube -cmd 'set image deployments/webspa webspa=${registryPath}${dockerOrg}/webspa:$imageTag'
ExecKube -cmd 'set image deployments/ordering-signalrhub ordering-signalrhub=${registryPath}${dockerOrg}/ordering.signalrhub:$imageTag'
ExecKube -cmd 'set image deployments/mobileshoppingagg mobileshoppingagg=${registryPath}${dockerOrg}/mobileshoppingagg:$imageTag' ExecKube -cmd 'set image deployments/mobileshoppingagg mobileshoppingagg=${registryPath}${dockerOrg}/mobileshoppingagg:$imageTag'
ExecKube -cmd 'set image deployments/webshoppingagg webshoppingagg=${registryPath}${dockerOrg}/webshoppingagg:$imageTag' ExecKube -cmd 'set image deployments/webshoppingagg webshoppingagg=${registryPath}${dockerOrg}/webshoppingagg:$imageTag'
@ -181,6 +189,7 @@ ExecKube -cmd 'rollout resume deployments/basket'
ExecKube -cmd 'rollout resume deployments/catalog' ExecKube -cmd 'rollout resume deployments/catalog'
ExecKube -cmd 'rollout resume deployments/identity' ExecKube -cmd 'rollout resume deployments/identity'
ExecKube -cmd 'rollout resume deployments/ordering' ExecKube -cmd 'rollout resume deployments/ordering'
ExecKube -cmd 'rollout resume deployments/ordering-backgroundtasks'
ExecKube -cmd 'rollout resume deployments/marketing' ExecKube -cmd 'rollout resume deployments/marketing'
ExecKube -cmd 'rollout resume deployments/locations' ExecKube -cmd 'rollout resume deployments/locations'
ExecKube -cmd 'rollout resume deployments/payment' ExecKube -cmd 'rollout resume deployments/payment'
@ -193,6 +202,7 @@ ExecKube -cmd 'rollout resume deployments/apigwmm'
ExecKube -cmd 'rollout resume deployments/apigwms' ExecKube -cmd 'rollout resume deployments/apigwms'
ExecKube -cmd 'rollout resume deployments/apigwwm' ExecKube -cmd 'rollout resume deployments/apigwwm'
ExecKube -cmd 'rollout resume deployments/apigwws' ExecKube -cmd 'rollout resume deployments/apigwws'
ExecKube -cmd 'rollout resume deployments/ordering-signalrhub'
Write-Host "WebSPA is exposed at http://$externalDns, WebMVC at http://$externalDns/webmvc, WebStatus at http://$externalDns/webstatus" -ForegroundColor Yellow Write-Host "WebSPA is exposed at http://$externalDns, WebMVC at http://$externalDns/webmvc, WebStatus at http://$externalDns/webstatus" -ForegroundColor Yellow

View File

@ -21,50 +21,37 @@ spec:
valueFrom: valueFrom:
configMapKeyRef: configMapKeyRef:
name: externalcfg name: externalcfg
key: BasketRedisConStr key: basket__ConnectionString
- name: EventBusConnection - name: EventBusConnection
valueFrom: valueFrom:
configMapKeyRef: configMapKeyRef:
name: externalcfg name: externalcfg
key: BasketBus key: all__EventBusConnection
- name: AzureServiceBusEnabled - name: AzureServiceBusEnabled
valueFrom: valueFrom:
configMapKeyRef: configMapKeyRef:
name: externalcfg name: externalcfg
key: UseAzureServiceBus key: all__UseAzureServiceBus
- name: ApplicationInsights__InstrumentationKey - name: ApplicationInsights__InstrumentationKey
valueFrom: valueFrom:
configMapKeyRef: configMapKeyRef:
name: externalcfg name: externalcfg
key: Instrumentation_Key key: all__InstrumentationKey
- name: IdentityUrl - name: IdentityUrl
valueFrom: valueFrom:
configMapKeyRef: configMapKeyRef:
name: urls name: urls
key: IdentityUrl key: identity_e
- name: UseLoadTest - name: UseLoadTest
valueFrom: valueFrom:
configMapKeyRef: configMapKeyRef:
name: externalcfg name: externalcfg
key: EnableLoadTest key: all__EnableLoadTest
- name: OrchestratorType - name: OrchestratorType
value: 'K8S' value: 'K8S'
ports: ports:
- containerPort: 80 - containerPort: 80
readinessProbe:
httpGet:
path: /hc
port: 80
scheme: HTTP
initialDelaySeconds: 60
periodSeconds: 60
livenessProbe:
httpGet:
path: /liveness
port: 80
scheme: HTTP
initialDelaySeconds: 120
periodSeconds: 60
imagePullSecrets: imagePullSecrets:
- name: registry-key - name: registry-key
--- ---
@ -91,7 +78,7 @@ spec:
valueFrom: valueFrom:
configMapKeyRef: configMapKeyRef:
name: externalcfg name: externalcfg
key: CatalogSqlDb key: catalog__ConnectionString
- name: PicBaseUrl - name: PicBaseUrl
valueFrom: valueFrom:
configMapKeyRef: configMapKeyRef:
@ -101,35 +88,22 @@ spec:
valueFrom: valueFrom:
configMapKeyRef: configMapKeyRef:
name: externalcfg name: externalcfg
key: CatalogAzureStorageEnabled key: catalog__AzureStorageEnabled
- name: EventBusConnection - name: EventBusConnection
valueFrom: valueFrom:
configMapKeyRef: configMapKeyRef:
name: externalcfg name: externalcfg
key: CatalogBus key: all__EventBusConnection
- name: ApplicationInsights__InstrumentationKey - name: ApplicationInsights__InstrumentationKey
valueFrom: valueFrom:
configMapKeyRef: configMapKeyRef:
name: externalcfg name: externalcfg
key: Instrumentation_Key key: all__InstrumentationKey
- name: OrchestratorType - name: OrchestratorType
value: 'K8S' value: 'K8S'
ports: ports:
- containerPort: 80 - containerPort: 80
readinessProbe:
httpGet:
path: /hc
port: 80
scheme: HTTP
initialDelaySeconds: 60
periodSeconds: 60
livenessProbe:
httpGet:
path: /liveness
port: 80
scheme: HTTP
initialDelaySeconds: 120
periodSeconds: 60
imagePullSecrets: imagePullSecrets:
- name: registry-key - name: registry-key
--- ---
@ -156,7 +130,7 @@ spec:
valueFrom: valueFrom:
configMapKeyRef: configMapKeyRef:
name: externalcfg name: externalcfg
key: IdentitySqlDb key: identity__ConnectionString
- name: DPConnectionString - name: DPConnectionString
valueFrom: valueFrom:
configMapKeyRef: configMapKeyRef:
@ -168,55 +142,57 @@ spec:
valueFrom: valueFrom:
configMapKeyRef: configMapKeyRef:
name: urls name: urls
key: MvcClientExternalUrl key: mvc_e
- name: SpaClient - name: SpaClient
valueFrom: valueFrom:
configMapKeyRef: configMapKeyRef:
name: urls name: urls
key: SpaClientExternalUrl key: spa_e
- name: LocationApiClient - name: LocationApiClient
valueFrom: valueFrom:
configMapKeyRef: configMapKeyRef:
name: urls name: urls
key: LocationApiClient key: locations_e
- name: MarketingApiClient - name: MarketingApiClient
valueFrom: valueFrom:
configMapKeyRef: configMapKeyRef:
name: urls name: urls
key: MarketingApiClient key: marketing_e
- name: BasketApiClient - name: BasketApiClient
valueFrom: valueFrom:
configMapKeyRef: configMapKeyRef:
name: urls name: urls
key: BasketApiClient key: basket_e
- name: OrderingApiClient - name: OrderingApiClient
valueFrom: valueFrom:
configMapKeyRef: configMapKeyRef:
name: urls name: urls
key: OrderingApiClient key: ordering_e
- name: MobileShoppingAggClient
valueFrom:
configMapKeyRef:
name: urls
key: mobileshoppingagg_e
- name: WebShoppingAggClient
valueFrom:
configMapKeyRef:
name: urls
key: webshoppingagg_e
- name: XamarinCallback
valueFrom:
configMapKeyRef:
name: urls
key: xamarin_callback_e
- name: ApplicationInsights__InstrumentationKey - name: ApplicationInsights__InstrumentationKey
valueFrom: valueFrom:
configMapKeyRef: configMapKeyRef:
name: externalcfg name: externalcfg
key: Instrumentation_Key key: all__InstrumentationKey
- name: OrchestratorType - name: OrchestratorType
value: 'K8S' value: 'K8S'
ports: ports:
- containerPort: 80 - containerPort: 80
readinessProbe:
httpGet:
path: /hc
port: 80
scheme: HTTP
initialDelaySeconds: 60
periodSeconds: 60
livenessProbe:
httpGet:
path: /liveness
port: 80
scheme: HTTP
initialDelaySeconds: 120
periodSeconds: 60
imagePullSecrets: imagePullSecrets:
- name: registry-key - name: registry-key
--- ---
@ -243,125 +219,157 @@ spec:
valueFrom: valueFrom:
configMapKeyRef: configMapKeyRef:
name: externalcfg name: externalcfg
key: OrderingSqlDb key: ordering__ConnectionString
- name: EventBusConnection - name: EventBusConnection
valueFrom: valueFrom:
configMapKeyRef: configMapKeyRef:
name: externalcfg name: externalcfg
key: OrderingBus key: all__EventBusConnection
- name: AzureServiceBusEnabled - name: AzureServiceBusEnabled
valueFrom: valueFrom:
configMapKeyRef: configMapKeyRef:
name: externalcfg name: externalcfg
key: UseAzureServiceBus key: all__UseAzureServiceBus
- name: IdentityUrl - name: IdentityUrl
valueFrom: valueFrom:
configMapKeyRef: configMapKeyRef:
name: urls name: urls
key: IdentityUrl key: identity_e
- name: CheckUpdateTime
valueFrom:
configMapKeyRef:
name: externalcfg
key: GracePeriodManager__CheckUpdateTime
- name: GracePeriodTime
valueFrom:
configMapKeyRef:
name: externalcfg
key: GracePeriodManager__GracePeriodTime
- name: ApplicationInsights__InstrumentationKey - name: ApplicationInsights__InstrumentationKey
valueFrom: valueFrom:
configMapKeyRef: configMapKeyRef:
name: externalcfg name: externalcfg
key: Instrumentation_Key key: all__InstrumentationKey
- name: UseLoadTest - name: UseLoadTest
valueFrom: valueFrom:
configMapKeyRef: configMapKeyRef:
name: externalcfg name: externalcfg
key: EnableLoadTest key: all__EnableLoadTest
- name: OrchestratorType - name: OrchestratorType
value: 'K8S' value: 'K8S'
ports: ports:
- containerPort: 80 - containerPort: 80
readinessProbe:
httpGet:
path: /hc
port: 80
scheme: HTTP
initialDelaySeconds: 60
periodSeconds: 60
livenessProbe:
httpGet:
path: /liveness
port: 80
scheme: HTTP
initialDelaySeconds: 120
periodSeconds: 60
imagePullSecrets: imagePullSecrets:
- name: registry-key - name: registry-key
--- ---
apiVersion: extensions/v1beta1 apiVersion: extensions/v1beta1
kind: Deployment kind: Deployment
metadata: metadata:
name: orderingbackground name: ordering-backgroundtasks
spec: spec:
paused: true paused: true
template: template:
metadata: metadata:
labels: labels:
app: eshop app: eshop
component: orderingbackground component: ordering-backgroundtasks
spec: spec:
containers: containers:
- name: orderingbackground - name: ordering-backgroundtasks
image: eshop/ordering.backgroundtasks image: eshop/ordering.backgroundtasks
imagePullPolicy: Always imagePullPolicy: Always
env: env:
- name: PATH_BASE
value: /ordering-backgroundtasks
- name: ConnectionString - name: ConnectionString
valueFrom: valueFrom:
configMapKeyRef: configMapKeyRef:
name: externalcfg name: externalcfg
key: OrderingSqlDb key: ordering__ConnectionString
- name: EventBusConnection - name: EventBusConnection
valueFrom: valueFrom:
configMapKeyRef: configMapKeyRef:
name: externalcfg name: externalcfg
key: OrderingBus key: all__EventBusConnection
- name: AzureServiceBusEnabled - name: AzureServiceBusEnabled
valueFrom: valueFrom:
configMapKeyRef: configMapKeyRef:
name: externalcfg name: externalcfg
key: UseAzureServiceBus key: all__UseAzureServiceBus
- name: CheckUpdateTime - name: CheckUpdateTime
valueFrom: valueFrom:
configMapKeyRef: configMapKeyRef:
name: externalcfg name: externalcfg
key: GracePeriodManager_CheckUpdateTime key: GracePeriodManager__CheckUpdateTime
- name: GracePeriodTime - name: GracePeriodTime
valueFrom: valueFrom:
configMapKeyRef: configMapKeyRef:
name: externalcfg name: externalcfg
key: GracePeriodManager_GracePeriodTime key: GracePeriodManager__GracePeriodTime
- name: ApplicationInsights__InstrumentationKey - name: ApplicationInsights__InstrumentationKey
valueFrom: valueFrom:
configMapKeyRef: configMapKeyRef:
name: externalcfg name: externalcfg
key: Instrumentation_Key key: all__InstrumentationKey
- name: UseLoadTest - name: UseLoadTest
valueFrom: valueFrom:
configMapKeyRef: configMapKeyRef:
name: externalcfg name: externalcfg
key: EnableLoadTest key: all__EnableLoadTest
- name: OrchestratorType - name: OrchestratorType
value: 'K8S' value: 'K8S'
ports:
- containerPort: 80
imagePullSecrets:
- name: registry-key
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: ordering-signalrhub
spec:
paused: true
template:
metadata:
labels:
app: eshop
component: ordering-signalrhub
spec:
containers:
- name: ordering-signalrhub
image: eshop/ordering.signalrhub
imagePullPolicy: Always
env:
- name: EventBusConnection
valueFrom:
configMapKeyRef:
name: externalcfg
key: all__EventBusConnection
- name: IdentityUrl
valueFrom:
configMapKeyRef:
name: urls
key: identity_e
- name: AzureServiceBusEnabled
valueFrom:
configMapKeyRef:
name: externalcfg
key: all__UseAzureServiceBus
- name: ApplicationInsights__InstrumentationKey
valueFrom:
configMapKeyRef:
name: externalcfg
key: all__InstrumentationKey
- name: OrchestratorType
value: 'K8S'
- name: IsClusterEnv
value: 'True'
- name: SignalrStoreConnectionString
valueFrom:
configMapKeyRef:
name: externalcfg
key: keystore
ports: ports:
- containerPort: 80 - containerPort: 80
readinessProbe:
httpGet:
path: /hc
port: 80
scheme: HTTP
initialDelaySeconds: 60
periodSeconds: 60
livenessProbe:
httpGet:
path: /liveness
port: 80
scheme: HTTP
initialDelaySeconds: 120
periodSeconds: 60
imagePullSecrets: imagePullSecrets:
- name: registry-key - name: registry-key
--- ---
@ -388,60 +396,47 @@ spec:
valueFrom: valueFrom:
configMapKeyRef: configMapKeyRef:
name: externalcfg name: externalcfg
key: LocationsNoSqlDb key: locations__ConnectionString
- name: Database - name: Database
valueFrom: valueFrom:
configMapKeyRef: configMapKeyRef:
name: externalcfg name: externalcfg
key: LocationsNoSqlDbName key: locations__Database
- name: AzureServiceBusEnabled - name: AzureServiceBusEnabled
valueFrom: valueFrom:
configMapKeyRef: configMapKeyRef:
name: externalcfg name: externalcfg
key: UseAzureServiceBus key: all__UseAzureServiceBus
- name: EventBusConnection - name: EventBusConnection
valueFrom: valueFrom:
configMapKeyRef: configMapKeyRef:
name: externalcfg name: externalcfg
key: LocationsBus key: all__EventBusConnection
- name: IdentityUrl - name: IdentityUrl
valueFrom: valueFrom:
configMapKeyRef: configMapKeyRef:
name: urls name: internalurls
key: IdentityUrl key: identity
- name: IdentityUrlExternal - name: IdentityUrlExternal
valueFrom: valueFrom:
configMapKeyRef: configMapKeyRef:
name: urls name: urls
key: IdentityUrl key: identity_e
- name: ApplicationInsights__InstrumentationKey - name: ApplicationInsights__InstrumentationKey
valueFrom: valueFrom:
configMapKeyRef: configMapKeyRef:
name: externalcfg name: externalcfg
key: Instrumentation_Key key: all__InstrumentationKey
- name: UseLoadTest - name: UseLoadTest
valueFrom: valueFrom:
configMapKeyRef: configMapKeyRef:
name: externalcfg name: externalcfg
key: EnableLoadTest key: all__EnableLoadTest
- name: OrchestratorType - name: OrchestratorType
value: 'K8S' value: 'K8S'
ports: ports:
- containerPort: 80 - containerPort: 80
readinessProbe:
httpGet:
path: /hc
port: 80
scheme: HTTP
initialDelaySeconds: 50
periodSeconds: 60
livenessProbe:
httpGet:
path: /liveness
port: 80
scheme: HTTP
initialDelaySeconds: 120
periodSeconds: 60
imagePullSecrets: imagePullSecrets:
- name: registry-key - name: registry-key
--- ---
@ -468,37 +463,37 @@ spec:
valueFrom: valueFrom:
configMapKeyRef: configMapKeyRef:
name: externalcfg name: externalcfg
key: MarketingSqlDb key: marketing__ConnectionString
- name: MongoConnectionString - name: MongoConnectionString
valueFrom: valueFrom:
configMapKeyRef: configMapKeyRef:
name: externalcfg name: externalcfg
key: MarketingNoSqlDb key: marketing__MongoConnectionString
- name: MongoDatabase - name: MongoDatabase
valueFrom: valueFrom:
configMapKeyRef: configMapKeyRef:
name: externalcfg name: externalcfg
key: MarketingNoSqlDbName key: marketing__MongoDatabase
- name: AzureServiceBusEnabled - name: AzureServiceBusEnabled
valueFrom: valueFrom:
configMapKeyRef: configMapKeyRef:
name: externalcfg name: externalcfg
key: UseAzureServiceBus key: all__UseAzureServiceBus
- name: EventBusConnection - name: EventBusConnection
valueFrom: valueFrom:
configMapKeyRef: configMapKeyRef:
name: externalcfg name: externalcfg
key: MarketingBus key: all__EventBusConnection
- name: IdentityUrl - name: IdentityUrl
valueFrom: valueFrom:
configMapKeyRef: configMapKeyRef:
name: urls name: internalurls
key: IdentityUrl key: identity
- name: IdentityUrlExternal - name: IdentityUrlExternal
valueFrom: valueFrom:
configMapKeyRef: configMapKeyRef:
name: urls name: urls
key: IdentityUrl key: identity_e
- name: PicBaseUrl - name: PicBaseUrl
valueFrom: valueFrom:
configMapKeyRef: configMapKeyRef:
@ -508,30 +503,17 @@ spec:
valueFrom: valueFrom:
configMapKeyRef: configMapKeyRef:
name: externalcfg name: externalcfg
key: Instrumentation_Key key: all__InstrumentationKey
- name: UseLoadTest - name: UseLoadTest
valueFrom: valueFrom:
configMapKeyRef: configMapKeyRef:
name: externalcfg name: externalcfg
key: EnableLoadTest key: all__EnableLoadTest
- name: OrchestratorType - name: OrchestratorType
value: 'K8S' value: 'K8S'
ports: ports:
- containerPort: 80 - containerPort: 80
readinessProbe:
httpGet:
path: /hc
port: 80
scheme: HTTP
initialDelaySeconds: 60
periodSeconds: 60
livenessProbe:
httpGet:
path: /liveness
port: 80
scheme: HTTP
initialDelaySeconds: 120
periodSeconds: 60
imagePullSecrets: imagePullSecrets:
- name: registry-key - name: registry-key
--- ---
@ -558,35 +540,22 @@ spec:
valueFrom: valueFrom:
configMapKeyRef: configMapKeyRef:
name: externalcfg name: externalcfg
key: UseAzureServiceBus key: all__UseAzureServiceBus
- name: EventBusConnection - name: EventBusConnection
valueFrom: valueFrom:
configMapKeyRef: configMapKeyRef:
name: externalcfg name: externalcfg
key: PaymentBus key: all__EventBusConnection
- name: ApplicationInsights__InstrumentationKey - name: ApplicationInsights__InstrumentationKey
valueFrom: valueFrom:
configMapKeyRef: configMapKeyRef:
name: externalcfg name: externalcfg
key: Instrumentation_Key key: all__InstrumentationKey
- name: OrchestratorType - name: OrchestratorType
value: 'K8S' value: 'K8S'
ports: ports:
- containerPort: 80 - containerPort: 80
readinessProbe:
httpGet:
path: /hc
port: 80
scheme: HTTP
initialDelaySeconds: 60
periodSeconds: 60
livenessProbe:
httpGet:
path: /liveness
port: 80
scheme: HTTP
initialDelaySeconds: 120
periodSeconds: 60
imagePullSecrets: imagePullSecrets:
- name: registry-key - name: registry-key
--- ---
@ -616,99 +585,81 @@ spec:
key: keystore key: keystore
- name: IsClusterEnv - name: IsClusterEnv
value: 'True' value: 'True'
- name: BasketUrl - name: PurchaseUrl
valueFrom:
configMapKeyRef:
name: internalurls
key: apigwws
- name: ExternalPurchaseUrl
valueFrom: valueFrom:
configMapKeyRef: configMapKeyRef:
name: urls name: urls
key: MvcClientBasketUrl key: webshoppingapigw_e
- name: CallBackUrl - name: CallBackUrl
valueFrom: valueFrom:
configMapKeyRef: configMapKeyRef:
name: urls name: urls
key: MvcClientExternalUrl key: mvc_e
- name: LocationsUrl
valueFrom:
configMapKeyRef:
name: urls
key: MvcClientLocationsUrl
- name: CatalogUrl
valueFrom:
configMapKeyRef:
name: urls
key: MvcClientCatalogUrl
- name: IdentityUrl - name: IdentityUrl
valueFrom: valueFrom:
configMapKeyRef: configMapKeyRef:
name: urls name: urls
key: IdentityUrl key: identity_e
- name: OrderingUrl
valueFrom:
configMapKeyRef:
name: urls
key: MvcClientOrderingUrl
- name: MarketingUrl - name: MarketingUrl
valueFrom: valueFrom:
configMapKeyRef: configMapKeyRef:
name: urls name: internalurls
key: MvcClientMarketingUrl key: apigwwm
- name: BasketUrlHC - name: BasketUrlHC
valueFrom: valueFrom:
configMapKeyRef: configMapKeyRef:
name: urls name: internalurls
key: BasketHealthCheckUrl key: basket__hc
- name: CatalogUrlHC - name: CatalogUrlHC
valueFrom: valueFrom:
configMapKeyRef: configMapKeyRef:
name: urls name: internalurls
key: CatalogHealthCheckUrl key: catalog__hc
- name: IdentityUrlHC - name: IdentityUrlHC
valueFrom: valueFrom:
configMapKeyRef: configMapKeyRef:
name: urls name: internalurls
key: IdentityHealthCheckUrl key: identity__hc
- name: OrderingUrlHC - name: OrderingUrlHC
valueFrom: valueFrom:
configMapKeyRef: configMapKeyRef:
name: urls name: internalurls
key: OrderingHealthCheckUrl key: ordering__hc
- name: MarketingUrlHC - name: MarketingUrlHC
valueFrom: valueFrom:
configMapKeyRef: configMapKeyRef:
name: urls name: internalurls
key: MarketingHealthCheckUrl key: marketing__hc
- name: PaymentUrlHC - name: PaymentUrlHC
valueFrom: valueFrom:
configMapKeyRef: configMapKeyRef:
name: urls name: internalurls
key: PaymentHealthCheckUrl key: payment__hc
- name: ApplicationInsights__InstrumentationKey - name: ApplicationInsights__InstrumentationKey
valueFrom: valueFrom:
configMapKeyRef: configMapKeyRef:
name: externalcfg name: externalcfg
key: Instrumentation_Key key: all__InstrumentationKey
- name: UseLoadTest - name: UseLoadTest
valueFrom: valueFrom:
configMapKeyRef: configMapKeyRef:
name: externalcfg name: externalcfg
key: EnableLoadTest key: all__EnableLoadTest
- name: OrchestratorType - name: OrchestratorType
value: 'K8S' value: 'K8S'
- name: SignalrHubUrl
valueFrom:
configMapKeyRef:
name: urls
key: webshoppingapigw_e
ports: ports:
- containerPort: 80 - containerPort: 80
readinessProbe:
httpGet:
path: /hc
port: 80
scheme: HTTP
initialDelaySeconds: 60
periodSeconds: 60
livenessProbe:
httpGet:
path: /liveness
port: 80
scheme: HTTP
initialDelaySeconds: 120
periodSeconds: 60
imagePullSecrets: imagePullSecrets:
- name: registry-key - name: registry-key
--- ---
@ -734,53 +685,58 @@ spec:
- name: BasketUrl - name: BasketUrl
valueFrom: valueFrom:
configMapKeyRef: configMapKeyRef:
name: urls name: internalurls
key: BasketHealthCheckUrl key: basket__hc
- name: CatalogUrl - name: CatalogUrl
valueFrom: valueFrom:
configMapKeyRef: configMapKeyRef:
name: urls name: internalurls
key: CatalogHealthCheckUrl key: catalog__hc
- name: IdentityUrl - name: IdentityUrl
valueFrom: valueFrom:
configMapKeyRef: configMapKeyRef:
name: urls name: internalurls
key: IdentityHealthCheckUrl key: identity__hc
- name: OrderingUrl - name: OrderingUrl
valueFrom: valueFrom:
configMapKeyRef: configMapKeyRef:
name: urls name: internalurls
key: OrderingHealthCheckUrl key: ordering__hc
- name: OrderingBackgroundTasksUrl
valueFrom:
configMapKeyRef:
name: internalurls
key: ordering-background__hc
- name: LocationsUrl - name: LocationsUrl
valueFrom: valueFrom:
configMapKeyRef: configMapKeyRef:
name: urls name: internalurls
key: LocationsHealthCheckUrl key: locations__hc
- name: MarketingUrl - name: MarketingUrl
valueFrom: valueFrom:
configMapKeyRef: configMapKeyRef:
name: urls name: internalurls
key: MarketingHealthCheckUrl key: marketing__hc
- name: mvc - name: mvc
valueFrom: valueFrom:
configMapKeyRef: configMapKeyRef:
name: urls name: internalurls
key: WebMvcHealthCheckUrl key: mvc__hc
- name: spa - name: spa
valueFrom: valueFrom:
configMapKeyRef: configMapKeyRef:
name: urls name: internalurls
key: WebSpaHealthCheckUrl key: spa__hc
- name: PaymentUrl - name: PaymentUrl
valueFrom: valueFrom:
configMapKeyRef: configMapKeyRef:
name: urls name: internalurls
key: PaymentHealthCheckUrl key: payment__hc
- name: ApplicationInsights__InstrumentationKey - name: ApplicationInsights__InstrumentationKey
valueFrom: valueFrom:
configMapKeyRef: configMapKeyRef:
name: externalcfg name: externalcfg
key: Instrumentation_Key key: all__InstrumentationKey
- name: OrchestratorType - name: OrchestratorType
value: 'K8S' value: 'K8S'
ports: ports:
@ -814,93 +770,159 @@ spec:
key: keystore key: keystore
- name: IsClusterEnv - name: IsClusterEnv
value: 'True' value: 'True'
- name: BasketUrl - name: PurchaseUrl
valueFrom: valueFrom:
configMapKeyRef: configMapKeyRef:
name: urls name: urls
key: SpaClientBasketExternalUrl key: webshoppingapigw_e
- name: CallBackUrl - name: CallBackUrl
valueFrom: valueFrom:
configMapKeyRef: configMapKeyRef:
name: urls name: urls
key: SpaClientExternalUrl key: spa_e
- name: CatalogUrl
valueFrom:
configMapKeyRef:
name: urls
key: SpaClientCatalogExternalUrl
- name: IdentityUrl - name: IdentityUrl
valueFrom: valueFrom:
configMapKeyRef: configMapKeyRef:
name: urls name: urls
key: SpaClientIdentityExternalUrl key: identity_e
- name: OrderingUrl
valueFrom:
configMapKeyRef:
name: urls
key: SpaClientOrderingExternalUrl
- name: MarketingUrl - name: MarketingUrl
valueFrom: valueFrom:
configMapKeyRef: configMapKeyRef:
name: urls name: urls
key: SpaClientMarketingExternalUrl key: marketingapigw_e
- name: LocationsUrl
valueFrom:
configMapKeyRef:
name: urls
key: SpaClientLocationsUrl
- name: BasketUrlHC - name: BasketUrlHC
valueFrom: valueFrom:
configMapKeyRef: configMapKeyRef:
name: urls name: internalurls
key: BasketHealthCheckUrl key: basket__hc
- name: CatalogUrlHC - name: CatalogUrlHC
valueFrom: valueFrom:
configMapKeyRef: configMapKeyRef:
name: urls name: internalurls
key: CatalogHealthCheckUrl key: catalog__hc
- name: IdentityUrlHC - name: IdentityUrlHC
valueFrom: valueFrom:
configMapKeyRef: configMapKeyRef:
name: urls name: internalurls
key: IdentityHealthCheckUrl key: identity__hc
- name: OrderingUrlHC - name: OrderingUrlHC
valueFrom: valueFrom:
configMapKeyRef: configMapKeyRef:
name: urls name: internalurls
key: OrderingHealthCheckUrl key: ordering__hc
- name: MarketingUrlHC - name: MarketingUrlHC
valueFrom: valueFrom:
configMapKeyRef: configMapKeyRef:
name: urls name: internalurls
key: MarketingHealthCheckUrl key: marketing__hc
- name: PaymentUrlHC - name: PaymentUrlHC
valueFrom: valueFrom:
configMapKeyRef: configMapKeyRef:
name: urls name: internalurls
key: PaymentHealthCheckUrl key: payment__hc
- name: ApplicationInsights__InstrumentationKey - name: ApplicationInsights__InstrumentationKey
valueFrom: valueFrom:
configMapKeyRef: configMapKeyRef:
name: externalcfg name: externalcfg
key: Instrumentation_Key key: all__InstrumentationKey
- name: OrchestratorType - name: OrchestratorType
value: 'K8S' value: 'K8S'
- name: SignalrHubUrl
valueFrom:
configMapKeyRef:
name: urls
key: webshoppingapigw_e
ports: ports:
- containerPort: 80 - containerPort: 80
readinessProbe:
httpGet:
path: /hc
port: 80
scheme: HTTP
initialDelaySeconds: 60
periodSeconds: 60
livenessProbe:
httpGet:
path: /liveness
port: 80
scheme: HTTP
initialDelaySeconds: 120
periodSeconds: 60
imagePullSecrets: imagePullSecrets:
- name: registry-key - name: registry-key
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: webshoppingagg
spec:
paused: true
template:
metadata:
labels:
app: eshop
component: webshoppingagg
spec:
containers:
- name: webshoppingagg
image: eshop/webshoppingagg
imagePullPolicy: Always
env:
- name: ASPNETCORE_URLS
value: http://0.0.0.0:80
- name: urls__basket
valueFrom:
configMapKeyRef:
name: internalurls
key: basket
- name: urls__catalog
valueFrom:
configMapKeyRef:
name: internalurls
key: catalog
- name: urls__orders
valueFrom:
configMapKeyRef:
name: internalurls
key: ordering
- name: urls__identity
valueFrom:
configMapKeyRef:
name: internalurls
key: identity
ports:
- containerPort: 80
imagePullSecrets:
- name: registry-key
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: mobileshoppingagg
spec:
paused: true
template:
metadata:
labels:
app: eshop
component: mobileshoppingagg
spec:
containers:
- name: mobileshoppingagg
image: eshop/mobileshoppingagg
imagePullPolicy: Always
env:
- name: ASPNETCORE_URLS
value: http://0.0.0.0:80
- name: urls__basket
valueFrom:
configMapKeyRef:
name: internalurls
key: basket
- name: urls__catalog
valueFrom:
configMapKeyRef:
name: internalurls
key: catalog
- name: urls__orders
valueFrom:
configMapKeyRef:
name: internalurls
key: ordering
- name: urls__identity
valueFrom:
configMapKeyRef:
name: internalurls
key: identity
ports:
- containerPort: 80
imagePullSecrets:
- name: registry-key
---

View File

@ -1,17 +1,16 @@
Param( Param(
[parameter(Mandatory=$true)][string]$resourceGroupName, [parameter(Mandatory=$true)][string]$resourceGroupName,
[parameter(Mandatory=$true)][string]$location, [parameter(Mandatory=$true)][string]$location,
[parameter(Mandatory=$false)][string]$registryName,
[parameter(Mandatory=$true)][string]$serviceName, [parameter(Mandatory=$true)][string]$serviceName,
[parameter(Mandatory=$true)][string]$dnsName, [parameter(Mandatory=$true)][string]$dnsNamePrefix,
[parameter(Mandatory=$false)][string]$registryName,
[parameter(Mandatory=$true)][string]$createAcr=$true, [parameter(Mandatory=$true)][string]$createAcr=$true,
[parameter(Mandatory=$false)][int]$nodeCount=2, [parameter(Mandatory=$false)][int]$nodeCount=3,
[parameter(Mandatory=$false)][string]$nodeVMSize="Standard_D2_v2", [parameter(Mandatory=$false)][string]$nodeVMSize="Standard_D2_v2"
[parameter(Mandatory=$false)][string]$kubernetesVersion="1.7.7"
) )
# Create resource group # Create resource group
Write-Host "Creating resource group..." -ForegroundColor Yellow Write-Host "Creating Azure Resource Group..." -ForegroundColor Yellow
az group create --name=$resourceGroupName --location=$location az group create --name=$resourceGroupName --location=$location
if ($createAcr -eq $true) { if ($createAcr -eq $true) {
@ -20,14 +19,16 @@ if ($createAcr -eq $true) {
az acr create -n $registryName -g $resourceGroupName -l $location --admin-enabled true --sku Basic az acr create -n $registryName -g $resourceGroupName -l $location --admin-enabled true --sku Basic
} }
# Create kubernetes orchestrator # Create kubernetes cluster in AKS
Write-Host "Creating kubernetes orchestrator..." -ForegroundColor Yellow Write-Host "Creating Kubernetes cluster in AKS..." -ForegroundColor Yellow
az aks create --resource-group=$resourceGroupName --name=$serviceName --dns-name-prefix=$dnsName --generate-ssh-keys --node-count=$nodeCount --node-vm-size=$nodeVMSize --kubernetes-version $kubernetesVersion az aks create --resource-group=$resourceGroupName --name=$serviceName --dns-name-prefix=$dnsNamePrefix --generate-ssh-keys --node-count=$nodeCount --node-vm-size=$nodeVMSize
# Retrieve kubernetes cluster configuration and save it under ~/.kube/config # Retrieve kubernetes cluster configuration and save it under ~/.kube/config
Write-Host "Getting Kubernetes config..." -ForegroundColor Yellow
az aks get-credentials --resource-group=$resourceGroupName --name=$serviceName az aks get-credentials --resource-group=$resourceGroupName --name=$serviceName
if ($createAcr -eq $true) { if ($createAcr -eq $true) {
# Show ACR credentials # Show ACR credentials
Write-Host "ACR credentials" -ForegroundColor Yellow
az acr credential show -n $registryName az acr credential show -n $registryName
} }

33
k8s/internalurls.yaml Normal file
View File

@ -0,0 +1,33 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: internalurls
labels:
app: eshop
data:
# Internal Services & healthchecks
basket: http://basket
basket__hc: http://basket/hc
catalog: http://catalog
catalog__hc: http://catalog/hc
identity: http://identity
identity__hc: http://identity/hc
ordering: http://ordering
ordering__hc: http://ordering/hc
ordering-background: http://ordering-background
ordering-background__hc: http://ordering-background/hc
marketing: http://marketing
marketing__hc: http://marketing/hc
locations: http://locations
locations__hc: http://locations/hc
payment__hc: http://payment/hc
mvc__hc: http://webmvc/hc
spa__hc: http://webspa/hc
# Aggreggators
mobileshoppingagg: http://mobileshoppingagg
webshoppingagg: http://webshoppingagg
# API GWs
apigwmm: http://ocelotapigw-mm
apigwms: http://ocelotapigw-ms
apigwwm: http://ocelotapigw-wm
apigwws: http://ocelotapigw-ws

View File

@ -0,0 +1,154 @@
{
"ReRoutes": [
{
"DownstreamPathTemplate": "/api/{version}/{everything}",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "catalog",
"Port": 80
}
],
"UpstreamPathTemplate": "/api/{version}/c/{everything}",
"UpstreamHttpMethod": [ "GET" ]
},
{
"DownstreamPathTemplate": "/api/{version}/{everything}",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "basket",
"Port": 80
}
],
"UpstreamPathTemplate": "/api/{version}/b/{everything}",
"UpstreamHttpMethod": [],
"AuthenticationOptions": {
"AuthenticationProviderKey": "IdentityApiKey",
"AllowedScopes": []
}
},
{
"DownstreamPathTemplate": "/api/{version}/{everything}",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "ordering",
"Port": 80
}
],
"UpstreamPathTemplate": "/api/{version}/o/{everything}",
"UpstreamHttpMethod": [],
"AuthenticationOptions": {
"AuthenticationProviderKey": "IdentityApiKey",
"AllowedScopes": []
}
},
{
"DownstreamPathTemplate": "/{everything}",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "webshoppingagg",
"Port": 80
}
],
"UpstreamPathTemplate": "/{everything}",
"UpstreamHttpMethod": [ "POST", "PUT", "GET" ],
"AuthenticationOptions": {
"AuthenticationProviderKey": "IdentityApiKey",
"AllowedScopes": []
}
},
{
"DownstreamPathTemplate": "/{everything}",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "ordering",
"Port": 80
}
],
"UpstreamPathTemplate": "/orders-api/{everything}",
"UpstreamHttpMethod": []
},
{
"DownstreamPathTemplate": "/{everything}",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "ordering-signalrhub",
"Port": 80
}
],
"UpstreamPathTemplate": "/hub/{everything}",
"UpstreamHttpMethod": []
},
{
"DownstreamPathTemplate": "/{everything}",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "basket",
"Port": 80
}
],
"UpstreamPathTemplate": "/basket-api/{everything}",
"UpstreamHttpMethod": []
},
{
"DownstreamPathTemplate": "/{everything}",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "catalog",
"Port": 80
}
],
"UpstreamPathTemplate": "/catalog-api/{everything}",
"UpstreamHttpMethod": []
},
{
"DownstreamPathTemplate": "/{everything}",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "marketing",
"Port": 80
}
],
"UpstreamPathTemplate": "/marketing-api/{everything}",
"UpstreamHttpMethod": []
},
{
"DownstreamPathTemplate": "/{everything}",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "payment",
"Port": 80
}
],
"UpstreamPathTemplate": "/payment-api/{everything}",
"UpstreamHttpMethod": []
},
{
"DownstreamPathTemplate": "/{everything}",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "locations.api",
"Port": 80
}
],
"UpstreamPathTemplate": "/location-api/{everything}",
"UpstreamHttpMethod": []
}
],
"GlobalConfiguration": {
"RequestIdKey": "OcRequestId",
"AdministrationPath": "/administration"
}
}

View File

@ -59,14 +59,28 @@ kind: Service
metadata: metadata:
labels: labels:
app: eshop app: eshop
component: orderingbackground component: ordering-backgroundtasks
name: orderingbackground name: ordering-background
spec: spec:
ports: ports:
- port: 80 - port: 80
selector: selector:
app: eshop app: eshop
component: orderingbackground component: ordering-backgroundtasks
---
apiVersion: v1
kind: Service
metadata:
labels:
app: eshop
component: ordering-signalrhub
name: ordering-signalrhub
spec:
ports:
- port: 80
selector:
app: eshop
component: ordering-signalrhub
--- ---
apiVersion: v1 apiVersion: v1
kind: Service kind: Service

11
package-lock.json generated Normal file
View File

@ -0,0 +1,11 @@
{
"requires": true,
"lockfileVersion": 1,
"dependencies": {
"@aspnet/signalr": {
"version": "1.0.0-preview1-update1",
"resolved": "https://registry.npmjs.org/@aspnet/signalr/-/signalr-1.0.0-preview1-update1.tgz",
"integrity": "sha512-TGFCoLa2svN37Ew5ue0kGFxbkmQzq2I9N5TMLFBWRrpTYF4txlE3yPX0EaPt/NToKBaK1A+VK8Q+1MGSYtnqUw=="
}
}
}

View File

@ -0,0 +1,31 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.DependencyInjection;
namespace OcelotApiGw
{
public class Program
{
public static void Main(string[] args)
{
BuildWebHost(args).Run();
}
public static IWebHost BuildWebHost(string[] args)
{
IWebHostBuilder builder = WebHost.CreateDefaultBuilder(args);
builder.ConfigureServices(s => s.AddSingleton(builder))
.ConfigureAppConfiguration(ic => ic.AddJsonFile(Path.Combine("configuration", "configuration.json")))
.UseStartup<Startup>();
IWebHost host = builder.Build();
return host;
}
}
}

View File

@ -0,0 +1,118 @@
{
"ReRoutes": [
{
"DownstreamPathTemplate": "/api/{version}/{everything}",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "catalog.api",
"Port": 80
}
],
"UpstreamPathTemplate": "/api/{version}/c/{everything}",
"UpstreamHttpMethod": [ "GET" ]
},
{
"DownstreamPathTemplate": "/api/{version}/{everything}",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "basket.api",
"Port": 80
}
],
"UpstreamPathTemplate": "/api/{version}/b/{everything}",
"UpstreamHttpMethod": [],
"AuthenticationOptions": {
"AuthenticationProviderKey": "IdentityApiKey",
"AllowedScopes": []
}
},
{
"DownstreamPathTemplate": "/api/{version}/{everything}",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "ordering.api",
"Port": 80
}
],
"UpstreamPathTemplate": "/api/{version}/o/{everything}",
"UpstreamHttpMethod": [],
"AuthenticationOptions": {
"AuthenticationProviderKey": "IdentityApiKey",
"AllowedScopes": []
}
},
{
"DownstreamPathTemplate": "/{everything}",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "mobileshoppingagg",
"Port": 80
}
],
"UpstreamPathTemplate": "/{everything}",
"UpstreamHttpMethod": [ "POST", "PUT", "GET" ],
"AuthenticationOptions": {
"AuthenticationProviderKey": "IdentityApiKey",
"AllowedScopes": []
}
},
{
"DownstreamPathTemplate": "/{everything}",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "ordering.api",
"Port": 80
}
],
"UpstreamPathTemplate": "/orders-api/{everything}",
"UpstreamHttpMethod": []
},
{
"DownstreamPathTemplate": "/{everything}",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "basket.api",
"Port": 80
}
],
"UpstreamPathTemplate": "/basket-api/{everything}",
"UpstreamHttpMethod": []
},
{
"DownstreamPathTemplate": "/{everything}",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "catalog.api",
"Port": 80
}
],
"UpstreamPathTemplate": "/catalog-api/{everything}",
"UpstreamHttpMethod": []
},
{
"DownstreamPathTemplate": "/{everything}",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "payment.api",
"Port": 80
}
],
"UpstreamPathTemplate": "/payment-api/{everything}",
"UpstreamHttpMethod": []
}
],
"GlobalConfiguration": {
"RequestIdKey": "OcRequestId",
"AdministrationPath": "/administration"
}
}

View File

@ -0,0 +1,130 @@
{
"ReRoutes": [
{
"DownstreamPathTemplate": "/api/{version}/{everything}",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "catalog.api",
"Port": 80
}
],
"UpstreamPathTemplate": "/api/{version}/c/{everything}",
"UpstreamHttpMethod": [ "GET" ]
},
{
"DownstreamPathTemplate": "/api/{version}/{everything}",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "basket.api",
"Port": 80
}
],
"UpstreamPathTemplate": "/api/{version}/b/{everything}",
"UpstreamHttpMethod": [],
"AuthenticationOptions": {
"AuthenticationProviderKey": "IdentityApiKey",
"AllowedScopes": []
}
},
{
"DownstreamPathTemplate": "/api/{version}/{everything}",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "ordering.api",
"Port": 80
}
],
"UpstreamPathTemplate": "/api/{version}/o/{everything}",
"UpstreamHttpMethod": [],
"AuthenticationOptions": {
"AuthenticationProviderKey": "IdentityApiKey",
"AllowedScopes": []
}
},
{
"DownstreamPathTemplate": "/{everything}",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "webshoppingagg",
"Port": 80
}
],
"UpstreamPathTemplate": "/{everything}",
"UpstreamHttpMethod": [ "POST", "PUT", "GET" ],
"AuthenticationOptions": {
"AuthenticationProviderKey": "IdentityApiKey",
"AllowedScopes": []
}
},
{
"DownstreamPathTemplate": "/{everything}",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "ordering.api",
"Port": 80
}
],
"UpstreamPathTemplate": "/orders-api/{everything}",
"UpstreamHttpMethod": []
},
{
"DownstreamPathTemplate": "/{everything}",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "ordering.signalrhub",
"Port": 80
}
],
"UpstreamPathTemplate": "/hub/{everything}",
"UpstreamHttpMethod": []
},
{
"DownstreamPathTemplate": "/{everything}",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "basket.api",
"Port": 80
}
],
"UpstreamPathTemplate": "/basket-api/{everything}",
"UpstreamHttpMethod": []
},
{
"DownstreamPathTemplate": "/{everything}",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "catalog.api",
"Port": 80
}
],
"UpstreamPathTemplate": "/catalog-api/{everything}",
"UpstreamHttpMethod": []
},
{
"DownstreamPathTemplate": "/{everything}",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "payment.api",
"Port": 80
}
],
"UpstreamPathTemplate": "/payment-api/{everything}",
"UpstreamHttpMethod": []
}
],
"GlobalConfiguration": {
"RequestIdKey": "OcRequestId",
"AdministrationPath": "/administration"
}
}

View File

@ -15,7 +15,7 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.2.1" /> <PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.2.1" />
<PackageReference Include="Microsoft.ApplicationInsights.DependencyCollector" Version="2.5.1" /> <PackageReference Include="Microsoft.ApplicationInsights.DependencyCollector" Version="2.5.1" />
<PackageReference Include="Microsoft.ApplicationInsights.Kubernetes" Version="1.0.0-beta5" /> <PackageReference Include="Microsoft.ApplicationInsights.Kubernetes" Version="1.0.0-beta6" />
<PackageReference Include="Microsoft.ApplicationInsights.ServiceFabric" Version="2.0.1-beta1" /> <PackageReference Include="Microsoft.ApplicationInsights.ServiceFabric" Version="2.0.1-beta1" />
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.5" /> <PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.5" />
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="4.2.1" /> <PackageReference Include="Autofac.Extensions.DependencyInjection" Version="4.2.1" />

View File

@ -55,6 +55,8 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API.Controllers
public async Task<IActionResult> Checkout([FromBody]BasketCheckout basketCheckout, [FromHeader(Name = "x-requestid")] string requestId) public async Task<IActionResult> Checkout([FromBody]BasketCheckout basketCheckout, [FromHeader(Name = "x-requestid")] string requestId)
{ {
var userId = _identitySvc.GetUserIdentity(); var userId = _identitySvc.GetUserIdentity();
var userName = User.FindFirst(x => x.Type == "unique_name").Value;
basketCheckout.RequestId = (Guid.TryParse(requestId, out Guid guid) && guid != Guid.Empty) ? basketCheckout.RequestId = (Guid.TryParse(requestId, out Guid guid) && guid != Guid.Empty) ?
guid : basketCheckout.RequestId; guid : basketCheckout.RequestId;
@ -65,7 +67,7 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API.Controllers
return BadRequest(); return BadRequest();
} }
var eventMessage = new UserCheckoutAcceptedIntegrationEvent(userId, basketCheckout.City, basketCheckout.Street, var eventMessage = new UserCheckoutAcceptedIntegrationEvent(userId, userName, basketCheckout.City, basketCheckout.Street,
basketCheckout.State, basketCheckout.Country, basketCheckout.ZipCode, basketCheckout.CardNumber, basketCheckout.CardHolderName, basketCheckout.State, basketCheckout.Country, basketCheckout.ZipCode, basketCheckout.CardNumber, basketCheckout.CardHolderName,
basketCheckout.CardExpiration, basketCheckout.CardSecurityNumber, basketCheckout.CardTypeId, basketCheckout.Buyer, basketCheckout.RequestId, basket); basketCheckout.CardExpiration, basketCheckout.CardSecurityNumber, basketCheckout.CardTypeId, basketCheckout.Buyer, basketCheckout.RequestId, basket);

View File

@ -8,6 +8,8 @@ namespace Basket.API.IntegrationEvents.Events
{ {
public string UserId { get; } public string UserId { get; }
public string UserName { get; }
public int OrderNumber { get; set; } public int OrderNumber { get; set; }
public string City { get; set; } public string City { get; set; }
@ -36,12 +38,13 @@ namespace Basket.API.IntegrationEvents.Events
public CustomerBasket Basket { get; } public CustomerBasket Basket { get; }
public UserCheckoutAcceptedIntegrationEvent(string userId, string city, string street, public UserCheckoutAcceptedIntegrationEvent(string userId, string userName, string city, string street,
string state, string country, string zipCode, string cardNumber, string cardHolderName, string state, string country, string zipCode, string cardNumber, string cardHolderName,
DateTime cardExpiration, string cardSecurityNumber, int cardTypeId, string buyer, Guid requestId, DateTime cardExpiration, string cardSecurityNumber, int cardTypeId, string buyer, Guid requestId,
CustomerBasket basket) CustomerBasket basket)
{ {
UserId = userId; UserId = userId;
UserName = userName;
City = city; City = city;
Street = street; Street = street;
State = state; State = state;

View File

@ -37,7 +37,7 @@
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="4.2.1" /> <PackageReference Include="Autofac.Extensions.DependencyInjection" Version="4.2.1" />
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.2.1" /> <PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.2.1" />
<PackageReference Include="Microsoft.ApplicationInsights.DependencyCollector" Version="2.5.1" /> <PackageReference Include="Microsoft.ApplicationInsights.DependencyCollector" Version="2.5.1" />
<PackageReference Include="Microsoft.ApplicationInsights.Kubernetes" Version="1.0.0-beta5" /> <PackageReference Include="Microsoft.ApplicationInsights.Kubernetes" Version="1.0.0-beta6" />
<PackageReference Include="Microsoft.ApplicationInsights.ServiceFabric" Version="2.0.1-beta1" /> <PackageReference Include="Microsoft.ApplicationInsights.ServiceFabric" Version="2.0.1-beta1" />
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.5" /> <PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.5" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="2.2.0" /> <PackageReference Include="Swashbuckle.AspNetCore" Version="2.2.0" />

View File

@ -14,7 +14,10 @@ namespace Microsoft.eShopOnContainers.Services.Identity.API.Configuration
new ApiResource("orders", "Orders Service"), new ApiResource("orders", "Orders Service"),
new ApiResource("basket", "Basket Service"), new ApiResource("basket", "Basket Service"),
new ApiResource("marketing", "Marketing Service"), new ApiResource("marketing", "Marketing Service"),
new ApiResource("locations", "Locations Service") new ApiResource("locations", "Locations Service"),
new ApiResource("mobileshoppingagg", "Mobile Shopping Aggregator"),
new ApiResource("webshoppingagg", "Web Shopping Aggregator"),
new ApiResource("orders.signalrhub", "Ordering Signalr Hub")
}; };
} }
@ -52,7 +55,9 @@ namespace Microsoft.eShopOnContainers.Services.Identity.API.Configuration
"orders", "orders",
"basket", "basket",
"locations", "locations",
"marketing" "marketing",
"webshoppingagg",
"orders.signalrhub"
} }
}, },
new Client new Client
@ -78,7 +83,8 @@ namespace Microsoft.eShopOnContainers.Services.Identity.API.Configuration
"orders", "orders",
"basket", "basket",
"locations", "locations",
"marketing" "marketing",
"mobileshoppingagg"
}, },
//Allow requesting refresh tokens for long lived API access //Allow requesting refresh tokens for long lived API access
AllowOfflineAccess = true, AllowOfflineAccess = true,
@ -114,7 +120,9 @@ namespace Microsoft.eShopOnContainers.Services.Identity.API.Configuration
"orders", "orders",
"basket", "basket",
"locations", "locations",
"marketing" "marketing",
"webshoppingagg",
"orders.signalrhub"
}, },
}, },
new Client new Client
@ -146,7 +154,8 @@ namespace Microsoft.eShopOnContainers.Services.Identity.API.Configuration
"orders", "orders",
"basket", "basket",
"locations", "locations",
"marketing" "marketing",
"webshoppingagg"
}, },
}, },
new Client new Client
@ -156,7 +165,7 @@ namespace Microsoft.eShopOnContainers.Services.Identity.API.Configuration
AllowedGrantTypes = GrantTypes.Implicit, AllowedGrantTypes = GrantTypes.Implicit,
AllowAccessTokensViaBrowser = true, AllowAccessTokensViaBrowser = true,
RedirectUris = { $"{clientsUrl["LocationsApi"]}/swagger/o2c.html" }, RedirectUris = { $"{clientsUrl["LocationsApi"]}/swagger/oauth2-redirect.html" },
PostLogoutRedirectUris = { $"{clientsUrl["LocationsApi"]}/swagger/" }, PostLogoutRedirectUris = { $"{clientsUrl["LocationsApi"]}/swagger/" },
AllowedScopes = AllowedScopes =
@ -171,7 +180,7 @@ namespace Microsoft.eShopOnContainers.Services.Identity.API.Configuration
AllowedGrantTypes = GrantTypes.Implicit, AllowedGrantTypes = GrantTypes.Implicit,
AllowAccessTokensViaBrowser = true, AllowAccessTokensViaBrowser = true,
RedirectUris = { $"{clientsUrl["MarketingApi"]}/swagger/o2c.html" }, RedirectUris = { $"{clientsUrl["MarketingApi"]}/swagger/oauth2-redirect.html" },
PostLogoutRedirectUris = { $"{clientsUrl["MarketingApi"]}/swagger/" }, PostLogoutRedirectUris = { $"{clientsUrl["MarketingApi"]}/swagger/" },
AllowedScopes = AllowedScopes =
@ -186,7 +195,7 @@ namespace Microsoft.eShopOnContainers.Services.Identity.API.Configuration
AllowedGrantTypes = GrantTypes.Implicit, AllowedGrantTypes = GrantTypes.Implicit,
AllowAccessTokensViaBrowser = true, AllowAccessTokensViaBrowser = true,
RedirectUris = { $"{clientsUrl["BasketApi"]}/swagger/o2c.html" }, RedirectUris = { $"{clientsUrl["BasketApi"]}/swagger/oauth2-redirect.html" },
PostLogoutRedirectUris = { $"{clientsUrl["BasketApi"]}/swagger/" }, PostLogoutRedirectUris = { $"{clientsUrl["BasketApi"]}/swagger/" },
AllowedScopes = AllowedScopes =
@ -201,14 +210,45 @@ namespace Microsoft.eShopOnContainers.Services.Identity.API.Configuration
AllowedGrantTypes = GrantTypes.Implicit, AllowedGrantTypes = GrantTypes.Implicit,
AllowAccessTokensViaBrowser = true, AllowAccessTokensViaBrowser = true,
RedirectUris = { $"{clientsUrl["OrderingApi"]}/swagger/o2c.html" }, RedirectUris = { $"{clientsUrl["OrderingApi"]}/swagger/oauth2-redirect.html" },
PostLogoutRedirectUris = { $"{clientsUrl["OrderingApi"]}/swagger/" }, PostLogoutRedirectUris = { $"{clientsUrl["OrderingApi"]}/swagger/" },
AllowedScopes = AllowedScopes =
{ {
"orders" "orders"
} }
},
new Client
{
ClientId = "mobileshoppingaggswaggerui",
ClientName = "Mobile Shopping Aggregattor Swagger UI",
AllowedGrantTypes = GrantTypes.Implicit,
AllowAccessTokensViaBrowser = true,
RedirectUris = { $"{clientsUrl["MobileShoppingAgg"]}/swagger/oauth2-redirect.html" },
PostLogoutRedirectUris = { $"{clientsUrl["MobileShoppingAgg"]}/swagger/" },
AllowedScopes =
{
"mobileshoppingagg"
}
},
new Client
{
ClientId = "webshoppingaggswaggerui",
ClientName = "Web Shopping Aggregattor Swagger UI",
AllowedGrantTypes = GrantTypes.Implicit,
AllowAccessTokensViaBrowser = true,
RedirectUris = { $"{clientsUrl["WebShoppingAgg"]}/swagger/oauth2-redirect.html" },
PostLogoutRedirectUris = { $"{clientsUrl["WebShoppingAgg"]}/swagger/" },
AllowedScopes =
{
"webshoppingagg"
}
} }
}; };
} }
} }

View File

@ -1,8 +1,10 @@
using IdentityServer4.EntityFramework.DbContexts; using IdentityServer4.EntityFramework.DbContexts;
using IdentityServer4.EntityFramework.Entities;
using IdentityServer4.EntityFramework.Mappers; using IdentityServer4.EntityFramework.Mappers;
using Microsoft.eShopOnContainers.Services.Identity.API.Configuration;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.eShopOnContainers.Services.Identity.API.Configuration;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -11,36 +13,70 @@ namespace Microsoft.eShopOnContainers.Services.Identity.API.Data
{ {
public class ConfigurationDbContextSeed public class ConfigurationDbContextSeed
{ {
public async Task SeedAsync(ConfigurationDbContext context, IConfiguration configuration) public async Task SeedAsync(ConfigurationDbContext context,IConfiguration configuration)
{ {
//callbacks urls from config: //callbacks urls from config:
var clientUrls = new Dictionary<string, string> var clientUrls = new Dictionary<string, string>();
{
{"Mvc", configuration.GetValue<string>("MvcClient")},
{"Spa", configuration.GetValue<string>("SpaClient")},
{"Xamarin", configuration.GetValue<string>("XamarinCallback")},
{"LocationsApi", configuration.GetValue<string>("LocationApiClient")},
{"MarketingApi", configuration.GetValue<string>("MarketingApiClient")},
{"BasketApi", configuration.GetValue<string>("BasketApiClient")},
{"OrderingApi", configuration.GetValue<string>("OrderingApiClient")}
};
if (!await context.Clients.AnyAsync()) clientUrls.Add("Mvc", configuration.GetValue<string>("MvcClient"));
clientUrls.Add("Spa", configuration.GetValue<string>("SpaClient"));
clientUrls.Add("Xamarin", configuration.GetValue<string>("XamarinCallback"));
clientUrls.Add("LocationsApi", configuration.GetValue<string>("LocationApiClient"));
clientUrls.Add("MarketingApi", configuration.GetValue<string>("MarketingApiClient"));
clientUrls.Add("BasketApi", configuration.GetValue<string>("BasketApiClient"));
clientUrls.Add("OrderingApi", configuration.GetValue<string>("OrderingApiClient"));
clientUrls.Add("MobileShoppingAgg", configuration.GetValue<string>("MobileShoppingAggClient"));
clientUrls.Add("WebShoppingAgg", configuration.GetValue<string>("WebShoppingAggClient"));
if (!context.Clients.Any())
{ {
context.Clients.AddRange(Config.GetClients(clientUrls).Select(client => client.ToEntity())); foreach (var client in Config.GetClients(clientUrls))
{
context.Clients.Add(client.ToEntity());
}
await context.SaveChangesAsync();
}
// Checking always for old redirects to fix existing deployments
// to use new swagger-ui redirect uri as of v3.0.0
// There should be no problem for new ones
// ref: https://github.com/dotnet-architecture/eShopOnContainers/issues/586
else
{
List<ClientRedirectUri> oldRedirects = (await context.Clients.Include(c => c.RedirectUris).ToListAsync())
.SelectMany(c => c.RedirectUris)
.Where(ru => ru.RedirectUri.EndsWith("/o2c.html"))
.ToList();
if (oldRedirects.Any())
{
foreach (var ru in oldRedirects)
{
ru.RedirectUri = ru.RedirectUri.Replace("/o2c.html", "/oauth2-redirect.html");
context.Update(ru.Client);
}
await context.SaveChangesAsync();
}
} }
if (!await context.IdentityResources.AnyAsync()) if (!context.IdentityResources.Any())
{ {
context.IdentityResources.AddRange(Config.GetResources().Select(resource => resource.ToEntity())); foreach (var resource in Config.GetResources())
{
context.IdentityResources.Add(resource.ToEntity());
}
await context.SaveChangesAsync();
} }
if (!await context.ApiResources.AnyAsync()) if (!context.ApiResources.Any())
{ {
context.ApiResources.AddRange(Config.GetApis().Select(api => api.ToEntity())); foreach (var api in Config.GetApis())
} {
context.ApiResources.Add(api.ToEntity());
}
await context.SaveChangesAsync(); await context.SaveChangesAsync();
}
} }
} }
} }

View File

@ -17,7 +17,7 @@
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="4.2.1" /> <PackageReference Include="Autofac.Extensions.DependencyInjection" Version="4.2.1" />
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.2.1" /> <PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.2.1" />
<PackageReference Include="Microsoft.ApplicationInsights.DependencyCollector" Version="2.5.1" /> <PackageReference Include="Microsoft.ApplicationInsights.DependencyCollector" Version="2.5.1" />
<PackageReference Include="Microsoft.ApplicationInsights.Kubernetes" Version="1.0.0-beta5" /> <PackageReference Include="Microsoft.ApplicationInsights.Kubernetes" Version="1.0.0-beta6" />
<PackageReference Include="Microsoft.ApplicationInsights.ServiceFabric" Version="2.0.1-beta1" /> <PackageReference Include="Microsoft.ApplicationInsights.ServiceFabric" Version="2.0.1-beta1" />
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.5" /> <PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.5" />
<PackageReference Include="IdentityServer4.AspNetIdentity" Version="2.1.0" /> <PackageReference Include="IdentityServer4.AspNetIdentity" Version="2.1.0" />

View File

@ -5,6 +5,7 @@ using Microsoft.AspNetCore.Identity;
using Microsoft.eShopOnContainers.Services.Identity.API.Models; using Microsoft.eShopOnContainers.Services.Identity.API.Models;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Linq; using System.Linq;
using System.Security.Claims; using System.Security.Claims;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -68,7 +69,8 @@ namespace Microsoft.eShopOnContainers.Services.Identity.API.Services
var claims = new List<Claim> var claims = new List<Claim>
{ {
new Claim(JwtClaimTypes.Subject, user.Id), new Claim(JwtClaimTypes.Subject, user.Id),
new Claim(JwtClaimTypes.PreferredUserName, user.UserName) new Claim(JwtClaimTypes.PreferredUserName, user.UserName),
new Claim(JwtRegisteredClaimNames.UniqueName, user.UserName)
}; };
if (!string.IsNullOrWhiteSpace(user.Name)) if (!string.IsNullOrWhiteSpace(user.Name))

View File

@ -9,7 +9,7 @@
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="4.2.1" /> <PackageReference Include="Autofac.Extensions.DependencyInjection" Version="4.2.1" />
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.2.1" /> <PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.2.1" />
<PackageReference Include="Microsoft.ApplicationInsights.DependencyCollector" Version="2.5.1" /> <PackageReference Include="Microsoft.ApplicationInsights.DependencyCollector" Version="2.5.1" />
<PackageReference Include="Microsoft.ApplicationInsights.Kubernetes" Version="1.0.0-beta5" /> <PackageReference Include="Microsoft.ApplicationInsights.Kubernetes" Version="1.0.0-beta6" />
<PackageReference Include="Microsoft.ApplicationInsights.ServiceFabric" Version="2.0.1-beta1" /> <PackageReference Include="Microsoft.ApplicationInsights.ServiceFabric" Version="2.0.1-beta1" />
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.5" /> <PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.5" />
<PackageReference Include="mongocsharpdriver" Version="2.5.0" /> <PackageReference Include="mongocsharpdriver" Version="2.5.0" />

View File

@ -23,7 +23,7 @@
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="4.2.1" /> <PackageReference Include="Autofac.Extensions.DependencyInjection" Version="4.2.1" />
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.2.1" /> <PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.2.1" />
<PackageReference Include="Microsoft.ApplicationInsights.DependencyCollector" Version="2.5.1" /> <PackageReference Include="Microsoft.ApplicationInsights.DependencyCollector" Version="2.5.1" />
<PackageReference Include="Microsoft.ApplicationInsights.Kubernetes" Version="1.0.0-beta5" /> <PackageReference Include="Microsoft.ApplicationInsights.Kubernetes" Version="1.0.0-beta6" />
<PackageReference Include="Microsoft.ApplicationInsights.ServiceFabric" Version="2.0.1-beta1" /> <PackageReference Include="Microsoft.ApplicationInsights.ServiceFabric" Version="2.0.1-beta1" />
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.5" /> <PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.5" />
<PackageReference Include="mongocsharpdriver" Version="2.5.0" /> <PackageReference Include="mongocsharpdriver" Version="2.5.0" />

View File

@ -26,6 +26,9 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands
[DataMember] [DataMember]
public string UserId { get; private set; } public string UserId { get; private set; }
[DataMember]
public string UserName { get; private set; }
[DataMember] [DataMember]
public string City { get; private set; } public string City { get; private set; }
@ -64,12 +67,13 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands
_orderItems = new List<OrderItemDTO>(); _orderItems = new List<OrderItemDTO>();
} }
public CreateOrderCommand(List<BasketItem> basketItems, string userId, string city, string street, string state, string country, string zipcode, public CreateOrderCommand(List<BasketItem> basketItems, string userId, string userName, string city, string street, string state, string country, string zipcode,
string cardNumber, string cardHolderName, DateTime cardExpiration, string cardNumber, string cardHolderName, DateTime cardExpiration,
string cardSecurityNumber, int cardTypeId) : this() string cardSecurityNumber, int cardTypeId) : this()
{ {
_orderItems = MapToOrderItems(basketItems); _orderItems = MapToOrderItems(basketItems);
UserId = userId; UserId = userId;
UserName = userName;
City = city; City = city;
Street = street; Street = street;
State = state; State = state;

View File

@ -31,7 +31,7 @@
// methods and constructor so validations, invariants and business logic // methods and constructor so validations, invariants and business logic
// make sure that consistency is preserved across the whole aggregate // make sure that consistency is preserved across the whole aggregate
var address = new Address(message.Street, message.City, message.State, message.Country, message.ZipCode); var address = new Address(message.Street, message.City, message.State, message.Country, message.ZipCode);
var order = new Order(message.UserId, address, message.CardTypeId, message.CardNumber, message.CardSecurityNumber, message.CardHolderName, message.CardExpiration); var order = new Order(message.UserId, message.UserName, address, message.CardTypeId, message.CardNumber, message.CardSecurityNumber, message.CardHolderName, message.CardExpiration);
foreach (var item in message.OrderItems) foreach (var item in message.OrderItems)
{ {

View File

@ -0,0 +1,46 @@
using MediatR;
using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.BuyerAggregate;
using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate;
using Microsoft.Extensions.Logging;
using Ordering.API.Application.IntegrationEvents;
using Ordering.API.Application.IntegrationEvents.Events;
using Ordering.Domain.Events;
using System;
using System.Threading;
using System.Threading.Tasks;
namespace Ordering.API.Application.DomainEventHandlers.OrderCancelled
{
public class OrderCancelledDomainEventHandler
: INotificationHandler<OrderCancelledDomainEvent>
{
private readonly IOrderRepository _orderRepository;
private readonly IBuyerRepository _buyerRepository;
private readonly ILoggerFactory _logger;
private readonly IOrderingIntegrationEventService _orderingIntegrationEventService;
public OrderCancelledDomainEventHandler(
IOrderRepository orderRepository,
ILoggerFactory logger,
IBuyerRepository buyerRepository,
IOrderingIntegrationEventService orderingIntegrationEventService)
{
_orderRepository = orderRepository ?? throw new ArgumentNullException(nameof(orderRepository));
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
_buyerRepository = buyerRepository ?? throw new ArgumentNullException(nameof(buyerRepository));
}
public async Task Handle(OrderCancelledDomainEvent orderCancelledDomainEvent, CancellationToken cancellationToken)
{
_logger.CreateLogger(nameof(OrderCancelledDomainEvent))
.LogTrace($"Order with Id: {orderCancelledDomainEvent.Order.Id} has been successfully updated with " +
$"a status order id: {OrderStatus.Shipped.Id}");
var order = await _orderRepository.GetAsync(orderCancelledDomainEvent.Order.Id);
var buyer = await _buyerRepository.FindByIdAsync(order.GetBuyerId.Value.ToString());
var orderStatusChangedToCancelledIntegrationEvent = new OrderStatusChangedToCancelledIntegrationEvent(order.Id, order.OrderStatus.Name, buyer.Name);
await _orderingIntegrationEventService.PublishThroughEventBusAsync(orderStatusChangedToCancelledIntegrationEvent);
}
}
}

View File

@ -1,30 +1,34 @@
namespace Ordering.API.Application.DomainEventHandlers.OrderGracePeriodConfirmed namespace Ordering.API.Application.DomainEventHandlers.OrderGracePeriodConfirmed
{ {
using Domain.Events;
using MediatR; using MediatR;
using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.BuyerAggregate;
using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate; using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Domain.Events;
using System;
using System.Threading.Tasks;
using Ordering.API.Application.IntegrationEvents; using Ordering.API.Application.IntegrationEvents;
using System.Linq;
using Ordering.API.Application.IntegrationEvents.Events; using Ordering.API.Application.IntegrationEvents.Events;
using System;
using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks;
public class OrderStatusChangedToAwaitingValidationDomainEventHandler public class OrderStatusChangedToAwaitingValidationDomainEventHandler
: INotificationHandler<OrderStatusChangedToAwaitingValidationDomainEvent> : INotificationHandler<OrderStatusChangedToAwaitingValidationDomainEvent>
{ {
private readonly IOrderRepository _orderRepository; private readonly IOrderRepository _orderRepository;
private readonly ILoggerFactory _logger; private readonly ILoggerFactory _logger;
private readonly IBuyerRepository _buyerRepository;
private readonly IOrderingIntegrationEventService _orderingIntegrationEventService; private readonly IOrderingIntegrationEventService _orderingIntegrationEventService;
public OrderStatusChangedToAwaitingValidationDomainEventHandler( public OrderStatusChangedToAwaitingValidationDomainEventHandler(
IOrderRepository orderRepository, ILoggerFactory logger, IOrderRepository orderRepository, ILoggerFactory logger,
IBuyerRepository buyerRepository,
IOrderingIntegrationEventService orderingIntegrationEventService) IOrderingIntegrationEventService orderingIntegrationEventService)
{ {
_orderRepository = orderRepository ?? throw new ArgumentNullException(nameof(orderRepository)); _orderRepository = orderRepository ?? throw new ArgumentNullException(nameof(orderRepository));
_logger = logger ?? throw new ArgumentNullException(nameof(logger)); _logger = logger ?? throw new ArgumentNullException(nameof(logger));
_orderingIntegrationEventService = orderingIntegrationEventService; _buyerRepository = buyerRepository;
_orderingIntegrationEventService = orderingIntegrationEventService;
} }
public async Task Handle(OrderStatusChangedToAwaitingValidationDomainEvent orderStatusChangedToAwaitingValidationDomainEvent, CancellationToken cancellationToken) public async Task Handle(OrderStatusChangedToAwaitingValidationDomainEvent orderStatusChangedToAwaitingValidationDomainEvent, CancellationToken cancellationToken)
@ -33,11 +37,15 @@
.LogTrace($"Order with Id: {orderStatusChangedToAwaitingValidationDomainEvent.OrderId} has been successfully updated with " + .LogTrace($"Order with Id: {orderStatusChangedToAwaitingValidationDomainEvent.OrderId} has been successfully updated with " +
$"a status order id: {OrderStatus.AwaitingValidation.Id}"); $"a status order id: {OrderStatus.AwaitingValidation.Id}");
var order = await _orderRepository.GetAsync(orderStatusChangedToAwaitingValidationDomainEvent.OrderId);
var buyer = await _buyerRepository.FindByIdAsync(order.GetBuyerId.Value.ToString());
var orderStockList = orderStatusChangedToAwaitingValidationDomainEvent.OrderItems var orderStockList = orderStatusChangedToAwaitingValidationDomainEvent.OrderItems
.Select(orderItem => new OrderStockItem(orderItem.ProductId, orderItem.GetUnits())); .Select(orderItem => new OrderStockItem(orderItem.ProductId, orderItem.GetUnits()));
var orderStatusChangedToAwaitingValidationIntegrationEvent = new OrderStatusChangedToAwaitingValidationIntegrationEvent( var orderStatusChangedToAwaitingValidationIntegrationEvent = new OrderStatusChangedToAwaitingValidationIntegrationEvent(
orderStatusChangedToAwaitingValidationDomainEvent.OrderId, orderStockList); order.Id, order.OrderStatus.Name, buyer.Name, orderStockList);
await _orderingIntegrationEventService.PublishThroughEventBusAsync(orderStatusChangedToAwaitingValidationIntegrationEvent); await _orderingIntegrationEventService.PublishThroughEventBusAsync(orderStatusChangedToAwaitingValidationIntegrationEvent);
} }
} }

View File

@ -1,30 +1,36 @@
namespace Ordering.API.Application.DomainEventHandlers.OrderPaid namespace Ordering.API.Application.DomainEventHandlers.OrderPaid
{ {
using Domain.Events;
using MediatR; using MediatR;
using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.BuyerAggregate;
using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate; using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Domain.Events;
using System;
using System.Threading.Tasks;
using Ordering.API.Application.IntegrationEvents; using Ordering.API.Application.IntegrationEvents;
using System.Linq;
using Ordering.API.Application.IntegrationEvents.Events; using Ordering.API.Application.IntegrationEvents.Events;
using System;
using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks;
public class OrderStatusChangedToPaidDomainEventHandler public class OrderStatusChangedToPaidDomainEventHandler
: INotificationHandler<OrderStatusChangedToPaidDomainEvent> : INotificationHandler<OrderStatusChangedToPaidDomainEvent>
{ {
private readonly IOrderRepository _orderRepository; private readonly IOrderRepository _orderRepository;
private readonly ILoggerFactory _logger; private readonly ILoggerFactory _logger;
private readonly IBuyerRepository _buyerRepository;
private readonly IOrderingIntegrationEventService _orderingIntegrationEventService; private readonly IOrderingIntegrationEventService _orderingIntegrationEventService;
public OrderStatusChangedToPaidDomainEventHandler( public OrderStatusChangedToPaidDomainEventHandler(
IOrderRepository orderRepository, ILoggerFactory logger, IOrderRepository orderRepository, ILoggerFactory logger,
IOrderingIntegrationEventService orderingIntegrationEventService) IBuyerRepository buyerRepository,
IOrderingIntegrationEventService orderingIntegrationEventService
)
{ {
_orderRepository = orderRepository ?? throw new ArgumentNullException(nameof(orderRepository)); _orderRepository = orderRepository ?? throw new ArgumentNullException(nameof(orderRepository));
_logger = logger ?? throw new ArgumentNullException(nameof(logger)); _logger = logger ?? throw new ArgumentNullException(nameof(logger));
_orderingIntegrationEventService = orderingIntegrationEventService; _buyerRepository = buyerRepository ?? throw new ArgumentNullException(nameof(buyerRepository));
_orderingIntegrationEventService = orderingIntegrationEventService ?? throw new ArgumentNullException(nameof(orderingIntegrationEventService));
} }
public async Task Handle(OrderStatusChangedToPaidDomainEvent orderStatusChangedToPaidDomainEvent, CancellationToken cancellationToken) public async Task Handle(OrderStatusChangedToPaidDomainEvent orderStatusChangedToPaidDomainEvent, CancellationToken cancellationToken)
@ -33,12 +39,19 @@
.LogTrace($"Order with Id: {orderStatusChangedToPaidDomainEvent.OrderId} has been successfully updated with " + .LogTrace($"Order with Id: {orderStatusChangedToPaidDomainEvent.OrderId} has been successfully updated with " +
$"a status order id: {OrderStatus.Paid.Id}"); $"a status order id: {OrderStatus.Paid.Id}");
var order = await _orderRepository.GetAsync(orderStatusChangedToPaidDomainEvent.OrderId);
var buyer = await _buyerRepository.FindByIdAsync(order.GetBuyerId.Value.ToString());
var orderStockList = orderStatusChangedToPaidDomainEvent.OrderItems var orderStockList = orderStatusChangedToPaidDomainEvent.OrderItems
.Select(orderItem => new OrderStockItem(orderItem.ProductId, orderItem.GetUnits())); .Select(orderItem => new OrderStockItem(orderItem.ProductId, orderItem.GetUnits()));
var orderStatusChangedToPaidIntegrationEvent = new OrderStatusChangedToPaidIntegrationEvent(orderStatusChangedToPaidDomainEvent.OrderId, var orderStatusChangedToPaidIntegrationEvent = new OrderStatusChangedToPaidIntegrationEvent(
orderStatusChangedToPaidDomainEvent.OrderId,
order.OrderStatus.Name,
buyer.Name,
orderStockList); orderStockList);
await _orderingIntegrationEventService.PublishThroughEventBusAsync(orderStatusChangedToPaidIntegrationEvent);
await _orderingIntegrationEventService.PublishThroughEventBusAsync(orderStatusChangedToPaidIntegrationEvent);
} }
} }
} }

View File

@ -0,0 +1,47 @@
using MediatR;
using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.BuyerAggregate;
using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate;
using Microsoft.Extensions.Logging;
using Ordering.API.Application.IntegrationEvents;
using Ordering.API.Application.IntegrationEvents.Events;
using Ordering.Domain.Events;
using System;
using System.Threading;
using System.Threading.Tasks;
namespace Ordering.API.Application.DomainEventHandlers.OrderShipped
{
public class OrderShippedDomainEventHandler
: INotificationHandler<OrderShippedDomainEvent>
{
private readonly IOrderRepository _orderRepository;
private readonly IBuyerRepository _buyerRepository;
private readonly IOrderingIntegrationEventService _orderingIntegrationEventService;
private readonly ILoggerFactory _logger;
public OrderShippedDomainEventHandler(
IOrderRepository orderRepository,
ILoggerFactory logger,
IBuyerRepository buyerRepository,
IOrderingIntegrationEventService orderingIntegrationEventService)
{
_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(OrderShippedDomainEvent orderShippedDomainEvent, CancellationToken cancellationToken)
{
_logger.CreateLogger(nameof(OrderShippedDomainEvent))
.LogTrace($"Order with Id: {orderShippedDomainEvent.Order.Id} has been successfully updated with " +
$"a status order id: {OrderStatus.Shipped.Id}");
var order = await _orderRepository.GetAsync(orderShippedDomainEvent.Order.Id);
var buyer = await _buyerRepository.FindByIdAsync(order.GetBuyerId.Value.ToString());
var orderStatusChangedToShippedIntegrationEvent = new OrderStatusChangedToShippedIntegrationEvent(order.Id, order.OrderStatus.Name, buyer.Name);
await _orderingIntegrationEventService.PublishThroughEventBusAsync(orderStatusChangedToShippedIntegrationEvent);
}
}
}

View File

@ -1,7 +1,10 @@
using MediatR; using MediatR;
using Microsoft.AspNetCore.Http;
using Microsoft.eShopOnContainers.Services.Ordering.API.Infrastructure.Services; using Microsoft.eShopOnContainers.Services.Ordering.API.Infrastructure.Services;
using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.BuyerAggregate; using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.BuyerAggregate;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Ordering.API.Application.IntegrationEvents;
using Ordering.API.Application.IntegrationEvents.Events;
using Ordering.Domain.Events; using Ordering.Domain.Events;
using System; using System;
using System.Threading; using System.Threading;
@ -15,23 +18,29 @@ namespace Ordering.API.Application.DomainEventHandlers.OrderStartedEvent
private readonly ILoggerFactory _logger; private readonly ILoggerFactory _logger;
private readonly IBuyerRepository _buyerRepository; private readonly IBuyerRepository _buyerRepository;
private readonly IIdentityService _identityService; private readonly IIdentityService _identityService;
private readonly IOrderingIntegrationEventService _orderingIntegrationEventService;
public ValidateOrAddBuyerAggregateWhenOrderStartedDomainEventHandler(ILoggerFactory logger, IBuyerRepository buyerRepository, IIdentityService identityService) public ValidateOrAddBuyerAggregateWhenOrderStartedDomainEventHandler(
ILoggerFactory logger,
IBuyerRepository buyerRepository,
IIdentityService identityService,
IOrderingIntegrationEventService orderingIntegrationEventService)
{ {
_buyerRepository = buyerRepository ?? throw new ArgumentNullException(nameof(buyerRepository)); _buyerRepository = buyerRepository ?? throw new ArgumentNullException(nameof(buyerRepository));
_identityService = identityService ?? throw new ArgumentNullException(nameof(identityService)); _identityService = identityService ?? throw new ArgumentNullException(nameof(identityService));
_orderingIntegrationEventService = orderingIntegrationEventService ?? throw new ArgumentNullException(nameof(orderingIntegrationEventService));
_logger = logger ?? throw new ArgumentNullException(nameof(logger)); _logger = logger ?? throw new ArgumentNullException(nameof(logger));
} }
public async Task Handle(OrderStartedDomainEvent orderStartedEvent, CancellationToken cancellationToken) public async Task Handle(OrderStartedDomainEvent orderStartedEvent, CancellationToken cancellationToken)
{ {
var cardTypeId = (orderStartedEvent.CardTypeId != 0) ? orderStartedEvent.CardTypeId : 1; var cardTypeId = (orderStartedEvent.CardTypeId != 0) ? orderStartedEvent.CardTypeId : 1;
var buyer = await _buyerRepository.FindAsync(orderStartedEvent.UserId); var buyer = await _buyerRepository.FindAsync(orderStartedEvent.UserId);
bool buyerOriginallyExisted = (buyer == null) ? false : true; bool buyerOriginallyExisted = (buyer == null) ? false : true;
if (!buyerOriginallyExisted) if (!buyerOriginallyExisted)
{ {
buyer = new Buyer(orderStartedEvent.UserId); buyer = new Buyer(orderStartedEvent.UserId, orderStartedEvent.UserName);
} }
buyer.VerifyOrAddPaymentMethod(cardTypeId, buyer.VerifyOrAddPaymentMethod(cardTypeId,
@ -42,11 +51,16 @@ namespace Ordering.API.Application.DomainEventHandlers.OrderStartedEvent
orderStartedEvent.CardExpiration, orderStartedEvent.CardExpiration,
orderStartedEvent.Order.Id); orderStartedEvent.Order.Id);
var buyerUpdated = buyerOriginallyExisted ? _buyerRepository.Update(buyer) : _buyerRepository.Add(buyer); var buyerUpdated = buyerOriginallyExisted ?
_buyerRepository.Update(buyer) :
_buyerRepository.Add(buyer);
await _buyerRepository.UnitOfWork await _buyerRepository.UnitOfWork
.SaveEntitiesAsync(); .SaveEntitiesAsync();
var orderStatusChangedTosubmittedIntegrationEvent = new OrderStatusChangedToSubmittedIntegrationEvent(orderStartedEvent.Order.Id, orderStartedEvent.Order.OrderStatus.Name, buyer.Name);
await _orderingIntegrationEventService.PublishThroughEventBusAsync(orderStatusChangedTosubmittedIntegrationEvent);
_logger.CreateLogger(nameof(ValidateOrAddBuyerAggregateWhenOrderStartedDomainEventHandler)).LogTrace($"Buyer {buyerUpdated.Id} and related payment method were validated or updated for orderId: {orderStartedEvent.Order.Id}."); _logger.CreateLogger(nameof(ValidateOrAddBuyerAggregateWhenOrderStartedDomainEventHandler)).LogTrace($"Buyer {buyerUpdated.Id} and related payment method were validated or updated for orderId: {orderStartedEvent.Order.Id}.");
} }
} }

View File

@ -1,27 +1,32 @@
namespace Ordering.API.Application.DomainEventHandlers.OrderStockConfirmed namespace Ordering.API.Application.DomainEventHandlers.OrderStockConfirmed
{ {
using Domain.Events;
using MediatR; using MediatR;
using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.BuyerAggregate;
using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate; using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Domain.Events;
using System;
using System.Threading.Tasks;
using Ordering.API.Application.IntegrationEvents; using Ordering.API.Application.IntegrationEvents;
using Ordering.API.Application.IntegrationEvents.Events; using Ordering.API.Application.IntegrationEvents.Events;
using System;
using System.Threading; using System.Threading;
using System.Threading.Tasks;
public class OrderStatusChangedToStockConfirmedDomainEventHandler public class OrderStatusChangedToStockConfirmedDomainEventHandler
: INotificationHandler<OrderStatusChangedToStockConfirmedDomainEvent> : INotificationHandler<OrderStatusChangedToStockConfirmedDomainEvent>
{ {
private readonly IOrderRepository _orderRepository; private readonly IOrderRepository _orderRepository;
private readonly IBuyerRepository _buyerRepository;
private readonly ILoggerFactory _logger; private readonly ILoggerFactory _logger;
private readonly IOrderingIntegrationEventService _orderingIntegrationEventService; private readonly IOrderingIntegrationEventService _orderingIntegrationEventService;
public OrderStatusChangedToStockConfirmedDomainEventHandler( public OrderStatusChangedToStockConfirmedDomainEventHandler(
IOrderRepository orderRepository, ILoggerFactory logger, IOrderRepository orderRepository,
IBuyerRepository buyerRepository,
ILoggerFactory logger,
IOrderingIntegrationEventService orderingIntegrationEventService) IOrderingIntegrationEventService orderingIntegrationEventService)
{ {
_orderRepository = orderRepository ?? throw new ArgumentNullException(nameof(orderRepository)); _orderRepository = orderRepository ?? throw new ArgumentNullException(nameof(orderRepository));
_buyerRepository = buyerRepository ?? throw new ArgumentNullException(nameof(buyerRepository));
_logger = logger ?? throw new ArgumentNullException(nameof(logger)); _logger = logger ?? throw new ArgumentNullException(nameof(logger));
_orderingIntegrationEventService = orderingIntegrationEventService; _orderingIntegrationEventService = orderingIntegrationEventService;
} }
@ -32,8 +37,11 @@
.LogTrace($"Order with Id: {orderStatusChangedToStockConfirmedDomainEvent.OrderId} has been successfully updated with " + .LogTrace($"Order with Id: {orderStatusChangedToStockConfirmedDomainEvent.OrderId} has been successfully updated with " +
$"a status order id: {OrderStatus.StockConfirmed.Id}"); $"a status order id: {OrderStatus.StockConfirmed.Id}");
var orderStatusChangedToStockConfirmedIntegrationEvent = new OrderStatusChangedToStockConfirmedIntegrationEvent(orderStatusChangedToStockConfirmedDomainEvent.OrderId); var order = await _orderRepository.GetAsync(orderStatusChangedToStockConfirmedDomainEvent.OrderId);
await _orderingIntegrationEventService.PublishThroughEventBusAsync(orderStatusChangedToStockConfirmedIntegrationEvent); var buyer = await _buyerRepository.FindByIdAsync(order.GetBuyerId.Value.ToString());
var orderStatusChangedToStockConfirmedIntegrationEvent = new OrderStatusChangedToStockConfirmedIntegrationEvent(order.Id, order.OrderStatus.Name, buyer.Name);
await _orderingIntegrationEventService.PublishThroughEventBusAsync(orderStatusChangedToStockConfirmedIntegrationEvent);
} }
} }
} }

View File

@ -17,6 +17,9 @@
public async Task Handle(OrderPaymentSuccededIntegrationEvent @event) public async Task Handle(OrderPaymentSuccededIntegrationEvent @event)
{ {
// Simulate a work time for validating the payment
await Task.Delay(10000);
var orderToUpdate = await _orderRepository.GetAsync(@event.OrderId); var orderToUpdate = await _orderRepository.GetAsync(@event.OrderId);
orderToUpdate.SetPaidStatus(); orderToUpdate.SetPaidStatus();

View File

@ -17,6 +17,9 @@
public async Task Handle(OrderStockConfirmedIntegrationEvent @event) public async Task Handle(OrderStockConfirmedIntegrationEvent @event)
{ {
// Simulate a work time for confirming the stock
await Task.Delay(10000);
var orderToUpdate = await _orderRepository.GetAsync(@event.OrderId); var orderToUpdate = await _orderRepository.GetAsync(@event.OrderId);
orderToUpdate.SetStockConfirmedStatus(); orderToUpdate.SetStockConfirmedStatus();

View File

@ -41,7 +41,7 @@ namespace Ordering.API.Application.IntegrationEvents.EventHandling
if (eventMsg.RequestId != Guid.Empty) if (eventMsg.RequestId != Guid.Empty)
{ {
var createOrderCommand = new CreateOrderCommand(eventMsg.Basket.Items, eventMsg.UserId, eventMsg.City, eventMsg.Street, var createOrderCommand = new CreateOrderCommand(eventMsg.Basket.Items, eventMsg.UserId, eventMsg.UserName, eventMsg.City, eventMsg.Street,
eventMsg.State, eventMsg.Country, eventMsg.ZipCode, eventMsg.State, eventMsg.Country, eventMsg.ZipCode,
eventMsg.CardNumber, eventMsg.CardHolderName, eventMsg.CardExpiration, eventMsg.CardNumber, eventMsg.CardHolderName, eventMsg.CardExpiration,
eventMsg.CardSecurityNumber, eventMsg.CardTypeId); eventMsg.CardSecurityNumber, eventMsg.CardTypeId);

View File

@ -6,13 +6,17 @@
public class OrderStatusChangedToAwaitingValidationIntegrationEvent : IntegrationEvent public class OrderStatusChangedToAwaitingValidationIntegrationEvent : IntegrationEvent
{ {
public int OrderId { get; } public int OrderId { get; }
public string OrderStatus { get; }
public string BuyerName { get; }
public IEnumerable<OrderStockItem> OrderStockItems { get; } public IEnumerable<OrderStockItem> OrderStockItems { get; }
public OrderStatusChangedToAwaitingValidationIntegrationEvent(int orderId, public OrderStatusChangedToAwaitingValidationIntegrationEvent(int orderId, string orderStatus, string buyerName,
IEnumerable<OrderStockItem> orderStockItems) IEnumerable<OrderStockItem> orderStockItems)
{ {
OrderId = orderId; OrderId = orderId;
OrderStockItems = orderStockItems; OrderStockItems = orderStockItems;
OrderStatus = orderStatus;
BuyerName = buyerName;
} }
} }

View File

@ -0,0 +1,22 @@
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Ordering.API.Application.IntegrationEvents.Events
{
public class OrderStatusChangedToCancelledIntegrationEvent : IntegrationEvent
{
public int OrderId { get; }
public string OrderStatus { get; }
public string BuyerName { get; }
public OrderStatusChangedToCancelledIntegrationEvent(int orderId, string orderStatus, string buyerName)
{
OrderId = orderId;
OrderStatus = orderStatus;
BuyerName = buyerName;
}
}
}

View File

@ -6,13 +6,19 @@
public class OrderStatusChangedToPaidIntegrationEvent : IntegrationEvent public class OrderStatusChangedToPaidIntegrationEvent : IntegrationEvent
{ {
public int OrderId { get; } public int OrderId { get; }
public string OrderStatus { get; }
public string BuyerName { get; }
public IEnumerable<OrderStockItem> OrderStockItems { get; } public IEnumerable<OrderStockItem> OrderStockItems { get; }
public OrderStatusChangedToPaidIntegrationEvent(int orderId, public OrderStatusChangedToPaidIntegrationEvent(int orderId,
string orderStatus,
string buyerName,
IEnumerable<OrderStockItem> orderStockItems) IEnumerable<OrderStockItem> orderStockItems)
{ {
OrderId = orderId; OrderId = orderId;
OrderStockItems = orderStockItems; OrderStockItems = orderStockItems;
OrderStatus = orderStatus;
BuyerName = buyerName;
} }
} }
} }

View File

@ -0,0 +1,22 @@
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Ordering.API.Application.IntegrationEvents.Events
{
public class OrderStatusChangedToShippedIntegrationEvent : IntegrationEvent
{
public int OrderId { get; }
public string OrderStatus { get; }
public string BuyerName { get; }
public OrderStatusChangedToShippedIntegrationEvent(int orderId, string orderStatus, string buyerName)
{
OrderId = orderId;
OrderStatus = orderStatus;
BuyerName = buyerName;
}
}
}

View File

@ -5,8 +5,14 @@
public class OrderStatusChangedToStockConfirmedIntegrationEvent : IntegrationEvent public class OrderStatusChangedToStockConfirmedIntegrationEvent : IntegrationEvent
{ {
public int OrderId { get; } public int OrderId { get; }
public string OrderStatus { get; }
public string BuyerName { get; }
public OrderStatusChangedToStockConfirmedIntegrationEvent(int orderId) public OrderStatusChangedToStockConfirmedIntegrationEvent(int orderId, string orderStatus, string buyerName)
=> OrderId = orderId; {
OrderId = orderId;
OrderStatus = orderStatus;
BuyerName = buyerName;
}
} }
} }

View File

@ -0,0 +1,22 @@
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Ordering.API.Application.IntegrationEvents.Events
{
public class OrderStatusChangedToSubmittedIntegrationEvent : IntegrationEvent
{
public int OrderId { get; }
public string OrderStatus { get; }
public string BuyerName { get; }
public OrderStatusChangedToSubmittedIntegrationEvent(int orderId, string orderStatus, string buyerName)
{
OrderId = orderId;
OrderStatus = orderStatus;
BuyerName = buyerName;
}
}
}

View File

@ -8,6 +8,8 @@ namespace Ordering.API.Application.IntegrationEvents.Events
{ {
public string UserId { get; } public string UserId { get; }
public string UserName { get; }
public string City { get; set; } public string City { get; set; }
public string Street { get; set; } public string Street { get; set; }
@ -34,7 +36,7 @@ namespace Ordering.API.Application.IntegrationEvents.Events
public CustomerBasket Basket { get; } public CustomerBasket Basket { get; }
public UserCheckoutAcceptedIntegrationEvent(string userId, string city, string street, public UserCheckoutAcceptedIntegrationEvent(string userId, string userName, string city, string street,
string state, string country, string zipCode, string cardNumber, string cardHolderName, string state, string country, string zipCode, string cardNumber, string cardHolderName,
DateTime cardExpiration, string cardSecurityNumber, int cardTypeId, string buyer, Guid requestId, DateTime cardExpiration, string cardSecurityNumber, int cardTypeId, string buyer, Guid requestId,
CustomerBasket basket) CustomerBasket basket)
@ -53,6 +55,7 @@ namespace Ordering.API.Application.IntegrationEvents.Events
Buyer = buyer; Buyer = buyer;
Basket = basket; Basket = basket;
RequestId = requestId; RequestId = requestId;
UserName = userName;
} }
} }

View File

@ -0,0 +1,238 @@
// <auto-generated />
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage;
using Microsoft.EntityFrameworkCore.Storage.Internal;
using Microsoft.eShopOnContainers.Services.Ordering.Infrastructure;
using System;
namespace Ordering.API.Infrastructure.Migrations
{
[DbContext(typeof(OrderingContext))]
[Migration("20180412143935_NamePropertyInBuyer")]
partial class NamePropertyInBuyer
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "2.0.1-rtm-125")
.HasAnnotation("Relational:Sequence:.orderitemseq", "'orderitemseq', '', '1', '10', '', '', 'Int64', 'False'")
.HasAnnotation("Relational:Sequence:ordering.buyerseq", "'buyerseq', 'ordering', '1', '10', '', '', 'Int64', 'False'")
.HasAnnotation("Relational:Sequence:ordering.orderseq", "'orderseq', 'ordering', '1', '10', '', '', 'Int64', 'False'")
.HasAnnotation("Relational:Sequence:ordering.paymentseq", "'paymentseq', 'ordering', '1', '10', '', '', 'Int64', 'False'")
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.BuyerAggregate.Buyer", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasAnnotation("SqlServer:HiLoSequenceName", "buyerseq")
.HasAnnotation("SqlServer:HiLoSequenceSchema", "ordering")
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.SequenceHiLo);
b.Property<string>("IdentityGuid")
.IsRequired()
.HasMaxLength(200);
b.Property<string>("Name");
b.HasKey("Id");
b.HasIndex("IdentityGuid")
.IsUnique();
b.ToTable("buyers","ordering");
});
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.BuyerAggregate.CardType", b =>
{
b.Property<int>("Id")
.HasDefaultValue(1);
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(200);
b.HasKey("Id");
b.ToTable("cardtypes","ordering");
});
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.BuyerAggregate.PaymentMethod", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasAnnotation("SqlServer:HiLoSequenceName", "paymentseq")
.HasAnnotation("SqlServer:HiLoSequenceSchema", "ordering")
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.SequenceHiLo);
b.Property<string>("Alias")
.IsRequired()
.HasMaxLength(200);
b.Property<int>("BuyerId");
b.Property<string>("CardHolderName")
.IsRequired()
.HasMaxLength(200);
b.Property<string>("CardNumber")
.IsRequired()
.HasMaxLength(25);
b.Property<int>("CardTypeId");
b.Property<DateTime>("Expiration");
b.HasKey("Id");
b.HasIndex("BuyerId");
b.HasIndex("CardTypeId");
b.ToTable("paymentmethods","ordering");
});
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate.Order", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasAnnotation("SqlServer:HiLoSequenceName", "orderseq")
.HasAnnotation("SqlServer:HiLoSequenceSchema", "ordering")
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.SequenceHiLo);
b.Property<int?>("BuyerId");
b.Property<string>("Description");
b.Property<DateTime>("OrderDate");
b.Property<int>("OrderStatusId");
b.Property<int?>("PaymentMethodId");
b.HasKey("Id");
b.HasIndex("BuyerId");
b.HasIndex("OrderStatusId");
b.HasIndex("PaymentMethodId");
b.ToTable("orders","ordering");
});
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate.OrderItem", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasAnnotation("SqlServer:HiLoSequenceName", "orderitemseq")
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.SequenceHiLo);
b.Property<decimal>("Discount");
b.Property<int>("OrderId");
b.Property<string>("PictureUrl");
b.Property<int>("ProductId");
b.Property<string>("ProductName")
.IsRequired();
b.Property<decimal>("UnitPrice");
b.Property<int>("Units");
b.HasKey("Id");
b.HasIndex("OrderId");
b.ToTable("orderItems","ordering");
});
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate.OrderStatus", b =>
{
b.Property<int>("Id")
.HasDefaultValue(1);
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(200);
b.HasKey("Id");
b.ToTable("orderstatus","ordering");
});
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Ordering.Infrastructure.Idempotency.ClientRequest", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd();
b.Property<string>("Name")
.IsRequired();
b.Property<DateTime>("Time");
b.HasKey("Id");
b.ToTable("requests","ordering");
});
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.BuyerAggregate.PaymentMethod", b =>
{
b.HasOne("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.BuyerAggregate.Buyer")
.WithMany("PaymentMethods")
.HasForeignKey("BuyerId")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.BuyerAggregate.CardType", "CardType")
.WithMany()
.HasForeignKey("CardTypeId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate.Order", b =>
{
b.HasOne("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.BuyerAggregate.Buyer")
.WithMany()
.HasForeignKey("BuyerId");
b.HasOne("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate.OrderStatus", "OrderStatus")
.WithMany()
.HasForeignKey("OrderStatusId")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.BuyerAggregate.PaymentMethod")
.WithMany()
.HasForeignKey("PaymentMethodId")
.OnDelete(DeleteBehavior.Restrict);
b.OwnsOne("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate.Address", "Address", b1 =>
{
b1.Property<int>("OrderId");
b1.ToTable("orders","ordering");
b1.HasOne("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate.Order")
.WithOne("Address")
.HasForeignKey("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate.Address", "OrderId")
.OnDelete(DeleteBehavior.Cascade);
});
});
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate.OrderItem", b =>
{
b.HasOne("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate.Order")
.WithMany("OrderItems")
.HasForeignKey("OrderId")
.OnDelete(DeleteBehavior.Cascade);
});
#pragma warning restore 612, 618
}
}
}

View File

@ -0,0 +1,86 @@
using Microsoft.EntityFrameworkCore.Migrations;
using System;
using System.Collections.Generic;
namespace Ordering.API.Infrastructure.Migrations
{
public partial class NamePropertyInBuyer : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "FK_orderItems_orders_OrderId",
schema: "ordering",
table: "orderItems");
migrationBuilder.AddColumn<string>(
name: "Name",
schema: "ordering",
table: "buyers",
nullable: true);
migrationBuilder.AddForeignKey(
name: "FK_orderItems_orders_OrderId",
schema: "ordering",
table: "orderItems",
column: "OrderId",
principalSchema: "ordering",
principalTable: "orders",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "FK_orderItems_orders_OrderId",
schema: "ordering",
table: "orderItems");
migrationBuilder.DropColumn(
name: "Name",
schema: "ordering",
table: "buyers");
migrationBuilder.AddColumn<string>(
name: "City",
schema: "ordering",
table: "orders",
nullable: true);
migrationBuilder.AddColumn<string>(
name: "Country",
schema: "ordering",
table: "orders",
nullable: true);
migrationBuilder.AddColumn<string>(
name: "State",
schema: "ordering",
table: "orders",
nullable: true);
migrationBuilder.AddColumn<string>(
name: "Street",
schema: "ordering",
table: "orders",
nullable: true);
migrationBuilder.AddColumn<string>(
name: "ZipCode",
schema: "ordering",
table: "orders",
nullable: true);
migrationBuilder.AddForeignKey(
name: "FK_orderItems_orders_OrderId",
schema: "ordering",
table: "orderItems",
column: "OrderId",
principalSchema: "ordering",
principalTable: "orders",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
}
}
}

View File

@ -17,7 +17,7 @@ namespace Ordering.API.Migrations
{ {
#pragma warning disable 612, 618 #pragma warning disable 612, 618
modelBuilder modelBuilder
.HasAnnotation("ProductVersion", "2.0.0-preview2-25794") .HasAnnotation("ProductVersion", "2.0.1-rtm-125")
.HasAnnotation("Relational:Sequence:.orderitemseq", "'orderitemseq', '', '1', '10', '', '', 'Int64', 'False'") .HasAnnotation("Relational:Sequence:.orderitemseq", "'orderitemseq', '', '1', '10', '', '', 'Int64', 'False'")
.HasAnnotation("Relational:Sequence:ordering.buyerseq", "'buyerseq', 'ordering', '1', '10', '', '', 'Int64', 'False'") .HasAnnotation("Relational:Sequence:ordering.buyerseq", "'buyerseq', 'ordering', '1', '10', '', '', 'Int64', 'False'")
.HasAnnotation("Relational:Sequence:ordering.orderseq", "'orderseq', 'ordering', '1', '10', '', '', 'Int64', 'False'") .HasAnnotation("Relational:Sequence:ordering.orderseq", "'orderseq', 'ordering', '1', '10', '', '', 'Int64', 'False'")
@ -36,6 +36,8 @@ namespace Ordering.API.Migrations
.IsRequired() .IsRequired()
.HasMaxLength(200); .HasMaxLength(200);
b.Property<string>("Name");
b.HasKey("Id"); b.HasKey("Id");
b.HasIndex("IdentityGuid") b.HasIndex("IdentityGuid")
@ -180,25 +182,6 @@ namespace Ordering.API.Migrations
b.ToTable("requests","ordering"); b.ToTable("requests","ordering");
}); });
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate.Address", b =>
{
b.Property<int?>("OrderId");
b.Property<string>("City");
b.Property<string>("Country");
b.Property<string>("State");
b.Property<string>("Street");
b.Property<string>("ZipCode");
b.HasKey("OrderId");
b.ToTable("orders","ordering");
});
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.BuyerAggregate.PaymentMethod", b => modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.BuyerAggregate.PaymentMethod", b =>
{ {
b.HasOne("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.BuyerAggregate.Buyer") b.HasOne("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.BuyerAggregate.Buyer")
@ -227,6 +210,18 @@ namespace Ordering.API.Migrations
.WithMany() .WithMany()
.HasForeignKey("PaymentMethodId") .HasForeignKey("PaymentMethodId")
.OnDelete(DeleteBehavior.Restrict); .OnDelete(DeleteBehavior.Restrict);
b.OwnsOne("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate.Address", "Address", b1 =>
{
b1.Property<int>("OrderId");
b1.ToTable("orders","ordering");
b1.HasOne("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate.Order")
.WithOne("Address")
.HasForeignKey("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate.Address", "OrderId")
.OnDelete(DeleteBehavior.Cascade);
});
}); });
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate.OrderItem", b => modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate.OrderItem", b =>
@ -236,14 +231,6 @@ namespace Ordering.API.Migrations
.HasForeignKey("OrderId") .HasForeignKey("OrderId")
.OnDelete(DeleteBehavior.Cascade); .OnDelete(DeleteBehavior.Cascade);
}); });
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate.Address", b =>
{
b.HasOne("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate.Order")
.WithOne("Address")
.HasForeignKey("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate.Address", "OrderId")
.OnDelete(DeleteBehavior.Cascade);
});
#pragma warning restore 612, 618 #pragma warning restore 612, 618
} }
} }

View File

@ -8,5 +8,7 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.API.Infrastructure.Servi
public interface IIdentityService public interface IIdentityService
{ {
string GetUserIdentity(); string GetUserIdentity();
string GetUserName();
} }
} }

View File

@ -20,5 +20,10 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.API.Infrastructure.Servi
{ {
return _context.HttpContext.User.FindFirst("sub").Value; return _context.HttpContext.User.FindFirst("sub").Value;
} }
public string GetUserName()
{
return _context.HttpContext.User.Identity.Name;
}
} }
} }

View File

@ -35,7 +35,7 @@
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="4.2.1" /> <PackageReference Include="Autofac.Extensions.DependencyInjection" Version="4.2.1" />
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.2.1" /> <PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.2.1" />
<PackageReference Include="Microsoft.ApplicationInsights.DependencyCollector" Version="2.5.1" /> <PackageReference Include="Microsoft.ApplicationInsights.DependencyCollector" Version="2.5.1" />
<PackageReference Include="Microsoft.ApplicationInsights.Kubernetes" Version="1.0.0-beta5" /> <PackageReference Include="Microsoft.ApplicationInsights.Kubernetes" Version="1.0.0-beta6" />
<PackageReference Include="Microsoft.ApplicationInsights.ServiceFabric" Version="2.0.1-beta1" /> <PackageReference Include="Microsoft.ApplicationInsights.ServiceFabric" Version="2.0.1-beta1" />
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.5" /> <PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.5" />
<PackageReference Include="MediatR" Version="4.0.1" /> <PackageReference Include="MediatR" Version="4.0.1" />

View File

@ -26,7 +26,6 @@
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.HealthChecks; using Microsoft.Extensions.HealthChecks;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Ordering.Infrastructure; using Ordering.Infrastructure;
using RabbitMQ.Client; using RabbitMQ.Client;
@ -199,7 +198,7 @@
} }
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory)
{ {
loggerFactory.AddConsole(Configuration.GetSection("Logging")); loggerFactory.AddConsole(Configuration.GetSection("Logging"));
loggerFactory.AddDebug(); loggerFactory.AddDebug();
@ -220,6 +219,7 @@
app.UseCors("CorsPolicy"); app.UseCors("CorsPolicy");
ConfigureAuth(app); ConfigureAuth(app);
app.UseMvcWithDefaultRoute(); app.UseMvcWithDefaultRoute();
app.UseSwagger() app.UseSwagger()
@ -266,7 +266,7 @@
private void ConfigureAuthService(IServiceCollection services) private void ConfigureAuthService(IServiceCollection services)
{ {
// prevent from mapping "sub" claim to nameidentifier. // prevent from mapping "sub" claim to nameidentifier.
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear(); JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Remove("sub");
var identityUrl = Configuration.GetValue<string>("IdentityUrl"); var identityUrl = Configuration.GetValue<string>("IdentityUrl");
@ -279,7 +279,7 @@
{ {
options.Authority = identityUrl; options.Authority = identityUrl;
options.RequireHttpsMetadata = false; options.RequireHttpsMetadata = false;
options.Audience = "orders"; options.Audience = "orders";
}); });
} }

View File

@ -17,5 +17,6 @@
"ApplicationInsights": { "ApplicationInsights": {
"InstrumentationKey": "" "InstrumentationKey": ""
}, },
"EventBusRetryCount": 5 "EventBusRetryCount": 5,
"EventBusConnection": "localhost"
} }

View File

@ -11,6 +11,8 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.B
{ {
public string IdentityGuid { get; private set; } public string IdentityGuid { get; private set; }
public string Name { get; private set; }
private List<PaymentMethod> _paymentMethods; private List<PaymentMethod> _paymentMethods;
public IEnumerable<PaymentMethod> PaymentMethods => _paymentMethods.AsReadOnly(); public IEnumerable<PaymentMethod> PaymentMethods => _paymentMethods.AsReadOnly();
@ -20,9 +22,10 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.B
_paymentMethods = new List<PaymentMethod>(); _paymentMethods = new List<PaymentMethod>();
} }
public Buyer(string identity) : this() public Buyer(string identity, string name) : this()
{ {
IdentityGuid = !string.IsNullOrWhiteSpace(identity) ? identity : throw new ArgumentNullException(nameof(identity)); IdentityGuid = !string.IsNullOrWhiteSpace(identity) ? identity : throw new ArgumentNullException(nameof(identity));
Name = !string.IsNullOrWhiteSpace(name) ? name : throw new ArgumentNullException(nameof(name));
} }
public PaymentMethod VerifyOrAddPaymentMethod( public PaymentMethod VerifyOrAddPaymentMethod(

View File

@ -11,5 +11,6 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.B
Buyer Add(Buyer buyer); Buyer Add(Buyer buyer);
Buyer Update(Buyer buyer); Buyer Update(Buyer buyer);
Task<Buyer> FindAsync(string BuyerIdentityGuid); Task<Buyer> FindAsync(string BuyerIdentityGuid);
Task<Buyer> FindByIdAsync(string id);
} }
} }

View File

@ -18,6 +18,7 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.O
// Address is a Value Object pattern example persisted as EF Core 2.0 owned entity // Address is a Value Object pattern example persisted as EF Core 2.0 owned entity
public Address Address { get; private set; } public Address Address { get; private set; }
public int? GetBuyerId => _buyerId;
private int? _buyerId; private int? _buyerId;
public OrderStatus OrderStatus { get; private set; } public OrderStatus OrderStatus { get; private set; }
@ -25,6 +26,10 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.O
private string _description; private string _description;
// Draft orders have this set to true. Currently we don't check anywhere the draft status of an Order, but we could do it if needed
private bool _isDraft;
// DDD Patterns comment // DDD Patterns comment
// Using a private collection field, better for DDD Aggregate's encapsulation // Using a private collection field, better for DDD Aggregate's encapsulation
// so OrderItems cannot be added from "outside the AggregateRoot" directly to the collection, // so OrderItems cannot be added from "outside the AggregateRoot" directly to the collection,
@ -34,12 +39,21 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.O
private int? _paymentMethodId; private int? _paymentMethodId;
protected Order() { _orderItems = new List<OrderItem>(); } public static Order NewDraft()
public Order(string userId, Address address, int cardTypeId, string cardNumber, string cardSecurityNumber,
string cardHolderName, DateTime cardExpiration, int? buyerId = null, int? paymentMethodId = null)
{ {
var order = new Order();
order._isDraft = true;
return order;
}
protected Order() {
_orderItems = new List<OrderItem>(); _orderItems = new List<OrderItem>();
_isDraft = false;
}
public Order(string userId, string userName, Address address, int cardTypeId, string cardNumber, string cardSecurityNumber,
string cardHolderName, DateTime cardExpiration, int? buyerId = null, int? paymentMethodId = null) : this()
{
_buyerId = buyerId; _buyerId = buyerId;
_paymentMethodId = paymentMethodId; _paymentMethodId = paymentMethodId;
_orderStatusId = OrderStatus.Submitted.Id; _orderStatusId = OrderStatus.Submitted.Id;
@ -48,7 +62,7 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.O
// Add the OrderStarterDomainEvent to the domain events collection // Add the OrderStarterDomainEvent to the domain events collection
// to be raised/dispatched when comitting changes into the Database [ After DbContext.SaveChanges() ] // to be raised/dispatched when comitting changes into the Database [ After DbContext.SaveChanges() ]
AddOrderStartedDomainEvent(userId, cardTypeId, cardNumber, AddOrderStartedDomainEvent(userId, userName, cardTypeId, cardNumber,
cardSecurityNumber, cardHolderName, cardExpiration); cardSecurityNumber, cardHolderName, cardExpiration);
} }
@ -92,35 +106,34 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.O
} }
public void SetAwaitingValidationStatus() public void SetAwaitingValidationStatus()
{ {
if (_orderStatusId == OrderStatus.Submitted.Id) if (_orderStatusId == OrderStatus.Submitted.Id)
{ {
_orderStatusId = OrderStatus.AwaitingValidation.Id;
AddDomainEvent(new OrderStatusChangedToAwaitingValidationDomainEvent(Id, _orderItems)); AddDomainEvent(new OrderStatusChangedToAwaitingValidationDomainEvent(Id, _orderItems));
} _orderStatusId = OrderStatus.AwaitingValidation.Id;
}
} }
public void SetStockConfirmedStatus() public void SetStockConfirmedStatus()
{ {
if (_orderStatusId == OrderStatus.AwaitingValidation.Id) if (_orderStatusId == OrderStatus.AwaitingValidation.Id)
{ {
AddDomainEvent(new OrderStatusChangedToStockConfirmedDomainEvent(Id));
_orderStatusId = OrderStatus.StockConfirmed.Id; _orderStatusId = OrderStatus.StockConfirmed.Id;
_description = "All the items were confirmed with available stock."; _description = "All the items were confirmed with available stock.";
}
AddDomainEvent(new OrderStatusChangedToStockConfirmedDomainEvent(Id));
}
} }
public void SetPaidStatus() public void SetPaidStatus()
{ {
if (_orderStatusId == OrderStatus.StockConfirmed.Id) if (_orderStatusId == OrderStatus.StockConfirmed.Id)
{ {
AddDomainEvent(new OrderStatusChangedToPaidDomainEvent(Id, OrderItems));
_orderStatusId = OrderStatus.Paid.Id; _orderStatusId = OrderStatus.Paid.Id;
_description = "The payment was performed at a simulated \"American Bank checking bank account endinf on XX35071\""; _description = "The payment was performed at a simulated \"American Bank checking bank account endinf on XX35071\"";
}
AddDomainEvent(new OrderStatusChangedToPaidDomainEvent(Id, OrderItems));
}
} }
public void SetShippedStatus() public void SetShippedStatus()
@ -132,6 +145,7 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.O
_orderStatusId = OrderStatus.Shipped.Id; _orderStatusId = OrderStatus.Shipped.Id;
_description = "The order was shipped."; _description = "The order was shipped.";
AddDomainEvent(new OrderShippedDomainEvent(this));
} }
public void SetCancelledStatus() public void SetCancelledStatus()
@ -144,6 +158,7 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.O
_orderStatusId = OrderStatus.Cancelled.Id; _orderStatusId = OrderStatus.Cancelled.Id;
_description = $"The order was cancelled."; _description = $"The order was cancelled.";
AddDomainEvent(new OrderCancelledDomainEvent(this));
} }
public void SetCancelledStatusWhenStockIsRejected(IEnumerable<int> orderStockRejectedItems) public void SetCancelledStatusWhenStockIsRejected(IEnumerable<int> orderStockRejectedItems)
@ -158,13 +173,13 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.O
var itemsStockRejectedDescription = string.Join(", ", itemsStockRejectedProductNames); var itemsStockRejectedDescription = string.Join(", ", itemsStockRejectedProductNames);
_description = $"The product items don't have stock: ({itemsStockRejectedDescription})."; _description = $"The product items don't have stock: ({itemsStockRejectedDescription}).";
} }
} }
private void AddOrderStartedDomainEvent(string userId, int cardTypeId, string cardNumber, private void AddOrderStartedDomainEvent(string userId, string userName, int cardTypeId, string cardNumber,
string cardSecurityNumber, string cardHolderName, DateTime cardExpiration) string cardSecurityNumber, string cardHolderName, DateTime cardExpiration)
{ {
var orderStartedDomainEvent = new OrderStartedDomainEvent(this, userId, cardTypeId, var orderStartedDomainEvent = new OrderStartedDomainEvent(this, userId, userName, cardTypeId,
cardNumber, cardSecurityNumber, cardNumber, cardSecurityNumber,
cardHolderName, cardExpiration); cardHolderName, cardExpiration);

View File

@ -0,0 +1,18 @@
using MediatR;
using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate;
using System;
using System.Collections.Generic;
using System.Text;
namespace Ordering.Domain.Events
{
public class OrderCancelledDomainEvent : INotification
{
public Order Order { get; }
public OrderCancelledDomainEvent(Order order)
{
Order = order;
}
}
}

View File

@ -0,0 +1,15 @@
using MediatR;
using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate;
namespace Ordering.Domain.Events
{
public class OrderShippedDomainEvent : INotification
{
public Order Order { get; }
public OrderShippedDomainEvent(Order order)
{
Order = order;
}
}
}

View File

@ -12,6 +12,7 @@ namespace Ordering.Domain.Events
public class OrderStartedDomainEvent : INotification public class OrderStartedDomainEvent : INotification
{ {
public string UserId { get; } public string UserId { get; }
public string UserName { get; }
public int CardTypeId { get; } public int CardTypeId { get; }
public string CardNumber { get; } public string CardNumber { get; }
public string CardSecurityNumber { get; } public string CardSecurityNumber { get; }
@ -19,13 +20,14 @@ namespace Ordering.Domain.Events
public DateTime CardExpiration { get; } public DateTime CardExpiration { get; }
public Order Order { get; } public Order Order { get; }
public OrderStartedDomainEvent(Order order, string userId, public OrderStartedDomainEvent(Order order, string userId, string userName,
int cardTypeId, string cardNumber, int cardTypeId, string cardNumber,
string cardSecurityNumber, string cardHolderName, string cardSecurityNumber, string cardHolderName,
DateTime cardExpiration) DateTime cardExpiration)
{ {
Order = order; Order = order;
UserId = userId; UserId = userId;
UserName = userName;
CardTypeId = cardTypeId; CardTypeId = cardTypeId;
CardNumber = cardNumber; CardNumber = cardNumber;
CardSecurityNumber = cardSecurityNumber; CardSecurityNumber = cardSecurityNumber;

View File

@ -26,6 +26,8 @@ namespace Ordering.Infrastructure.EntityConfigurations
buyerConfiguration.HasIndex("IdentityGuid") buyerConfiguration.HasIndex("IdentityGuid")
.IsUnique(true); .IsUnique(true);
buyerConfiguration.Property(b => b.Name);
buyerConfiguration.HasMany(b => b.PaymentMethods) buyerConfiguration.HasMany(b => b.PaymentMethods)
.WithOne() .WithOne()
.HasForeignKey("BuyerId") .HasForeignKey("BuyerId")

View File

@ -54,5 +54,15 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Infrastructure.Repositor
return buyer; return buyer;
} }
public async Task<Buyer> FindByIdAsync(string id)
{
var buyer = await _context.Buyers
.Include(b => b.PaymentMethods)
.Where(b => b.Id == int.Parse(id))
.SingleOrDefaultAsync();
return buyer;
}
} }
} }

View File

@ -0,0 +1,30 @@
using Autofac;
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions;
using Ordering.SignalrHub.IntegrationEvents;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
namespace Ordering.SignalrHub.AutofacModules
{
public class ApplicationModule
: Autofac.Module
{
public string QueriesConnectionString { get; }
public ApplicationModule()
{
}
protected override void Load(ContainerBuilder builder)
{
builder.RegisterAssemblyTypes(typeof(OrderStatusChangedToAwaitingValidationIntegrationEvent).GetTypeInfo().Assembly)
.AsClosedTypesOf(typeof(IIntegrationEventHandler<>));
}
}
}

View File

@ -0,0 +1,20 @@
FROM microsoft/aspnetcore:2.0 AS base
WORKDIR /app
EXPOSE 80
FROM microsoft/aspnetcore-build:2.0 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
FROM build AS publish
RUN dotnet publish Ordering.SignalrHub.csproj -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
ENTRYPOINT ["dotnet", "Ordering.SignalrHub.dll"]

View File

@ -0,0 +1,28 @@
using Microsoft.AspNetCore.SignalR;
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions;
using Ordering.SignalrHub.IntegrationEvents.Events;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Ordering.SignalrHub.IntegrationEvents.EventHandling
{
public class OrderStatusChangedToCancelledIntegrationEventHandler : IIntegrationEventHandler<OrderStatusChangedToCancelledIntegrationEvent>
{
private readonly IHubContext<NotificationsHub> _hubContext;
public OrderStatusChangedToCancelledIntegrationEventHandler(IHubContext<NotificationsHub> hubContext)
{
_hubContext = hubContext ?? throw new ArgumentNullException(nameof(hubContext));
}
public async Task Handle(OrderStatusChangedToCancelledIntegrationEvent @event)
{
await _hubContext.Clients
.Group(@event.BuyerName)
.SendAsync("UpdatedOrderState", new { OrderId = @event.OrderId, Status = @event.OrderStatus });
}
}
}

View File

@ -0,0 +1,26 @@
using Microsoft.AspNetCore.SignalR;
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions;
using Ordering.SignalrHub.IntegrationEvents.Events;
using System;
using System.Threading.Tasks;
namespace Ordering.SignalrHub.IntegrationEvents.EventHandling
{
public class OrderStatusChangedToPaidIntegrationEventHandler : IIntegrationEventHandler<OrderStatusChangedToPaidIntegrationEvent>
{
private readonly IHubContext<NotificationsHub> _hubContext;
public OrderStatusChangedToPaidIntegrationEventHandler(IHubContext<NotificationsHub> hubContext)
{
_hubContext = hubContext ?? throw new ArgumentNullException(nameof(hubContext));
}
public async Task Handle(OrderStatusChangedToPaidIntegrationEvent @event)
{
await _hubContext.Clients
.Group(@event.BuyerName)
.SendAsync("UpdatedOrderState", new { OrderId = @event.OrderId, Status = @event.OrderStatus });
}
}
}

View File

@ -0,0 +1,28 @@
using Microsoft.AspNetCore.SignalR;
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions;
using Ordering.SignalrHub.IntegrationEvents.Events;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Ordering.SignalrHub.IntegrationEvents.EventHandling
{
public class OrderStatusChangedToShippedIntegrationEventHandler : IIntegrationEventHandler<OrderStatusChangedToShippedIntegrationEvent>
{
private readonly IHubContext<NotificationsHub> _hubContext;
public OrderStatusChangedToShippedIntegrationEventHandler(IHubContext<NotificationsHub> hubContext)
{
_hubContext = hubContext ?? throw new ArgumentNullException(nameof(hubContext));
}
public async Task Handle(OrderStatusChangedToShippedIntegrationEvent @event)
{
await _hubContext.Clients
.Group(@event.BuyerName)
.SendAsync("UpdatedOrderState", new { OrderId = @event.OrderId, Status = @event.OrderStatus });
}
}
}

View File

@ -0,0 +1,29 @@
using Microsoft.AspNetCore.SignalR;
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions;
using Ordering.SignalrHub.IntegrationEvents.Events;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Ordering.SignalrHub.IntegrationEvents.EventHandling
{
public class OrderStatusChangedToStockConfirmedIntegrationEventHandler :
IIntegrationEventHandler<OrderStatusChangedToStockConfirmedIntegrationEvent>
{
private readonly IHubContext<NotificationsHub> _hubContext;
public OrderStatusChangedToStockConfirmedIntegrationEventHandler(IHubContext<NotificationsHub> hubContext)
{
_hubContext = hubContext ?? throw new ArgumentNullException(nameof(hubContext));
}
public async Task Handle(OrderStatusChangedToStockConfirmedIntegrationEvent @event)
{
await _hubContext.Clients
.Group(@event.BuyerName)
.SendAsync("UpdatedOrderState", new { OrderId = @event.OrderId, Status = @event.OrderStatus });
}
}
}

View File

@ -0,0 +1,29 @@
using Microsoft.AspNetCore.SignalR;
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions;
using Ordering.SignalrHub.IntegrationEvents.Events;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Ordering.SignalrHub.IntegrationEvents.EventHandling
{
public class OrderStatusChangedToSubmittedIntegrationEventHandler :
IIntegrationEventHandler<OrderStatusChangedToSubmittedIntegrationEvent>
{
private readonly IHubContext<NotificationsHub> _hubContext;
public OrderStatusChangedToSubmittedIntegrationEventHandler(IHubContext<NotificationsHub> hubContext)
{
_hubContext = hubContext ?? throw new ArgumentNullException(nameof(hubContext));
}
public async Task Handle(OrderStatusChangedToSubmittedIntegrationEvent @event)
{
await _hubContext.Clients
.Group(@event.BuyerName)
.SendAsync("UpdatedOrderState", new { OrderId = @event.OrderId, Status = @event.OrderStatus });
}
}
}

View File

@ -0,0 +1,27 @@
using Microsoft.AspNetCore.SignalR;
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Ordering.SignalrHub.IntegrationEvents
{
public class OrderStatusChangedToAwaitingValidationIntegrationEventHandler : IIntegrationEventHandler<OrderStatusChangedToAwaitingValidationIntegrationEvent>
{
private readonly IHubContext<NotificationsHub> _hubContext;
public OrderStatusChangedToAwaitingValidationIntegrationEventHandler(IHubContext<NotificationsHub> hubContext)
{
_hubContext = hubContext ?? throw new ArgumentNullException(nameof(hubContext));
}
public async Task Handle(OrderStatusChangedToAwaitingValidationIntegrationEvent @event)
{
await _hubContext.Clients
.Group(@event.BuyerName)
.SendAsync("UpdatedOrderState", new { OrderId = @event.OrderId, Status = @event.OrderStatus });
}
}
}

View File

@ -0,0 +1,19 @@
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events;
using System.Collections.Generic;
namespace Ordering.SignalrHub.IntegrationEvents
{
public class OrderStatusChangedToAwaitingValidationIntegrationEvent : IntegrationEvent
{
public int OrderId { get; }
public string OrderStatus { get; }
public string BuyerName { get; }
public OrderStatusChangedToAwaitingValidationIntegrationEvent(int orderId, string orderStatus, string buyerName)
{
OrderId = orderId;
OrderStatus = orderStatus;
BuyerName = buyerName;
}
}
}

View File

@ -0,0 +1,22 @@
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Ordering.SignalrHub.IntegrationEvents.Events
{
public class OrderStatusChangedToCancelledIntegrationEvent : IntegrationEvent
{
public int OrderId { get; }
public string OrderStatus { get; }
public string BuyerName { get; }
public OrderStatusChangedToCancelledIntegrationEvent(int orderId, string orderStatus, string buyerName)
{
OrderId = orderId;
OrderStatus = orderStatus;
BuyerName = buyerName;
}
}
}

View File

@ -0,0 +1,23 @@
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Ordering.SignalrHub.IntegrationEvents.Events
{
public class OrderStatusChangedToPaidIntegrationEvent : IntegrationEvent
{
public int OrderId { get; }
public string OrderStatus { get; }
public string BuyerName { get; }
public OrderStatusChangedToPaidIntegrationEvent(int orderId,
string orderStatus, string buyerName)
{
OrderId = orderId;
OrderStatus = orderStatus;
BuyerName = buyerName;
}
}
}

View File

@ -0,0 +1,22 @@
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Ordering.SignalrHub.IntegrationEvents.Events
{
public class OrderStatusChangedToShippedIntegrationEvent : IntegrationEvent
{
public int OrderId { get; }
public string OrderStatus { get; }
public string BuyerName { get; }
public OrderStatusChangedToShippedIntegrationEvent(int orderId, string orderStatus, string buyerName)
{
OrderId = orderId;
OrderStatus = orderStatus;
BuyerName = buyerName;
}
}
}

View File

@ -0,0 +1,18 @@
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events;
namespace Ordering.SignalrHub.IntegrationEvents.Events
{
public class OrderStatusChangedToStockConfirmedIntegrationEvent : IntegrationEvent
{
public int OrderId { get; }
public string OrderStatus { get; }
public string BuyerName { get; }
public OrderStatusChangedToStockConfirmedIntegrationEvent(int orderId, string orderStatus, string buyerName)
{
OrderId = orderId;
OrderStatus = orderStatus;
BuyerName = buyerName;
}
}
}

View File

@ -0,0 +1,22 @@
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Ordering.SignalrHub.IntegrationEvents.Events
{
public class OrderStatusChangedToSubmittedIntegrationEvent : IntegrationEvent
{
public int OrderId { get; }
public string OrderStatus { get; }
public string BuyerName { get; }
public OrderStatusChangedToSubmittedIntegrationEvent(int orderId, string orderStatus, string buyerName)
{
OrderId = orderId;
OrderStatus = orderStatus;
BuyerName = buyerName;
}
}
}

View File

@ -0,0 +1,26 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.SignalR;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Ordering.SignalrHub
{
[Authorize]
public class NotificationsHub : Hub
{
public override async Task OnConnectedAsync()
{
await Groups.AddAsync(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 base.OnDisconnectedAsync(ex);
}
}
}

View File

@ -0,0 +1,26 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp2.0</TargetFramework>
<DockerComposeProjectPath>..\..\..\..\docker-compose.dcproj</DockerComposeProjectPath>
</PropertyGroup>
<ItemGroup>
<Folder Include="wwwroot\" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="4.2.1" />
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.6" />
<PackageReference Include="Microsoft.AspNetCore.SignalR" Version="1.0.0-preview2-final" />
<PackageReference Include="Microsoft.AspNetCore.SignalR.Core" Version="1.0.0-preview2-final" />
<PackageReference Include="Microsoft.AspNetCore.SignalR.Redis" Version="1.0.0-preview2-final" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\BuildingBlocks\EventBus\EventBusRabbitMQ\EventBusRabbitMQ.csproj" />
<ProjectReference Include="..\..\..\BuildingBlocks\EventBus\EventBusServiceBus\EventBusServiceBus.csproj" />
<ProjectReference Include="..\..\..\BuildingBlocks\EventBus\EventBus\EventBus.csproj" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,25 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
namespace Ordering.SignalrHub
{
public class Program
{
public static void Main(string[] args)
{
BuildWebHost(args).Run();
}
public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.Build();
}
}

View File

@ -0,0 +1,27 @@
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:51311/",
"sslPort": 0
}
},
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"Ordering.SignalrHub": {
"commandName": "Project",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"applicationUrl": "http://localhost:51312/"
}
}
}

View File

@ -0,0 +1,214 @@
using Autofac;
using Autofac.Extensions.DependencyInjection;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Builder;
using Microsoft.Azure.ServiceBus;
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus;
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions;
using Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ;
using Microsoft.eShopOnContainers.BuildingBlocks.EventBusServiceBus;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Ordering.SignalrHub.AutofacModules;
using Ordering.SignalrHub.IntegrationEvents;
using Ordering.SignalrHub.IntegrationEvents.EventHandling;
using Ordering.SignalrHub.IntegrationEvents.Events;
using RabbitMQ.Client;
using StackExchange.Redis;
using System;
using System.IdentityModel.Tokens.Jwt;
namespace Ordering.SignalrHub
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
// This method gets called by the runtime. Use this method to add services to the container.
// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
public IServiceProvider ConfigureServices(IServiceCollection services)
{
services.AddCors(options =>
{
options.AddPolicy("CorsPolicy",
builder => builder.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials());
});
if (Configuration.GetValue<string>("IsClusterEnv") == bool.TrueString)
{
services
.AddSignalR()
.AddRedis(Configuration["SignalrStoreConnectionString"]);
}
else
{
services.AddSignalR();
}
if (Configuration.GetValue<bool>("AzureServiceBusEnabled"))
{
services.AddSingleton<IServiceBusPersisterConnection>(sp =>
{
var logger = sp.GetRequiredService<ILogger<DefaultServiceBusPersisterConnection>>();
var serviceBusConnectionString = Configuration["EventBusConnection"];
var serviceBusConnection = new ServiceBusConnectionStringBuilder(serviceBusConnectionString);
return new DefaultServiceBusPersisterConnection(serviceBusConnection, logger);
});
}
else
{
services.AddSingleton<IRabbitMQPersistentConnection>(sp =>
{
var logger = sp.GetRequiredService<ILogger<DefaultRabbitMQPersistentConnection>>();
var factory = new ConnectionFactory()
{
HostName = Configuration["EventBusConnection"]
};
if (!string.IsNullOrEmpty(Configuration["EventBusUserName"]))
{
factory.UserName = Configuration["EventBusUserName"];
}
if (!string.IsNullOrEmpty(Configuration["EventBusPassword"]))
{
factory.Password = Configuration["EventBusPassword"];
}
var retryCount = 5;
if (!string.IsNullOrEmpty(Configuration["EventBusRetryCount"]))
{
retryCount = int.Parse(Configuration["EventBusRetryCount"]);
}
return new DefaultRabbitMQPersistentConnection(factory, logger, retryCount);
});
}
ConfigureAuthService(services);
RegisterEventBus(services);
services.AddOptions();
//configure autofac
var container = new ContainerBuilder();
container.RegisterModule(new ApplicationModule());
container.Populate(services);
return new AutofacServiceProvider(container.Build());
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
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);
}
app.UseCors("CorsPolicy");
app.UseAuthentication();
app.UseSignalR(routes =>
{
routes.MapHub<NotificationsHub>("/notificationhub", options =>
options.Transports = Microsoft.AspNetCore.Http.Connections.TransportType.All);
});
ConfigureEventBus(app);
}
private void ConfigureEventBus(IApplicationBuilder app)
{
var eventBus = app.ApplicationServices.GetRequiredService<IEventBus>();
eventBus.Subscribe<OrderStatusChangedToAwaitingValidationIntegrationEvent, OrderStatusChangedToAwaitingValidationIntegrationEventHandler>();
eventBus.Subscribe<OrderStatusChangedToPaidIntegrationEvent, OrderStatusChangedToPaidIntegrationEventHandler>();
eventBus.Subscribe<OrderStatusChangedToStockConfirmedIntegrationEvent, OrderStatusChangedToStockConfirmedIntegrationEventHandler>();
eventBus.Subscribe<OrderStatusChangedToShippedIntegrationEvent, OrderStatusChangedToShippedIntegrationEventHandler>();
eventBus.Subscribe<OrderStatusChangedToCancelledIntegrationEvent, OrderStatusChangedToCancelledIntegrationEventHandler>();
eventBus.Subscribe<OrderStatusChangedToSubmittedIntegrationEvent, OrderStatusChangedToSubmittedIntegrationEventHandler>();
}
private void ConfigureAuthService(IServiceCollection services)
{
// prevent from mapping "sub" claim to nameidentifier.
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Remove("sub");
var identityUrl = Configuration.GetValue<string>("IdentityUrl");
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(options =>
{
options.Authority = identityUrl;
options.RequireHttpsMetadata = false;
options.Audience = "orders.signalrhub";
});
}
private void RegisterEventBus(IServiceCollection services)
{
var subscriptionClientName = Configuration["SubscriptionClientName"];
if (Configuration.GetValue<bool>("AzureServiceBusEnabled"))
{
services.AddSingleton<IEventBus, EventBusServiceBus>(sp =>
{
var serviceBusPersisterConnection = sp.GetRequiredService<IServiceBusPersisterConnection>();
var iLifetimeScope = sp.GetRequiredService<ILifetimeScope>();
var logger = sp.GetRequiredService<ILogger<EventBusServiceBus>>();
var eventBusSubcriptionsManager = sp.GetRequiredService<IEventBusSubscriptionsManager>();
return new EventBusServiceBus(serviceBusPersisterConnection, logger,
eventBusSubcriptionsManager, subscriptionClientName, iLifetimeScope);
});
}
else
{
services.AddSingleton<IEventBus, EventBusRabbitMQ>(sp =>
{
var rabbitMQPersistentConnection = sp.GetRequiredService<IRabbitMQPersistentConnection>();
var iLifetimeScope = sp.GetRequiredService<ILifetimeScope>();
var logger = sp.GetRequiredService<ILogger<EventBusRabbitMQ>>();
var eventBusSubcriptionsManager = sp.GetRequiredService<IEventBusSubscriptionsManager>();
var retryCount = 5;
if (!string.IsNullOrEmpty(Configuration["EventBusRetryCount"]))
{
retryCount = int.Parse(Configuration["EventBusRetryCount"]);
}
return new EventBusRabbitMQ(rabbitMQPersistentConnection, logger, iLifetimeScope, eventBusSubcriptionsManager, subscriptionClientName, retryCount);
});
}
services.AddSingleton<IEventBusSubscriptionsManager, InMemoryEventBusSubscriptionsManager>();
}
}
}

View File

@ -0,0 +1,15 @@
{
"IdentityUrl": "http://localhost:5105",
"Logging": {
"IncludeScopes": false,
"LogLevel": {
"Default": "Trace",
"System": "Information",
"Microsoft": "Information"
}
},
"AzureServiceBusEnabled": false,
"SubscriptionClientName": "Ordering.signalrhub",
"EventBusRetryCount": 5,
"EventBusConnection": "localhost"
}

View File

@ -10,7 +10,7 @@
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="4.2.1" /> <PackageReference Include="Autofac.Extensions.DependencyInjection" Version="4.2.1" />
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.2.1" /> <PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.2.1" />
<PackageReference Include="Microsoft.ApplicationInsights.DependencyCollector" Version="2.5.1" /> <PackageReference Include="Microsoft.ApplicationInsights.DependencyCollector" Version="2.5.1" />
<PackageReference Include="Microsoft.ApplicationInsights.Kubernetes" Version="1.0.0-beta5" /> <PackageReference Include="Microsoft.ApplicationInsights.Kubernetes" Version="1.0.0-beta6" />
<PackageReference Include="Microsoft.ApplicationInsights.ServiceFabric" Version="2.0.1-beta1" /> <PackageReference Include="Microsoft.ApplicationInsights.ServiceFabric" Version="2.0.1-beta1" />
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.5" /> <PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.5" />
</ItemGroup> </ItemGroup>

View File

@ -8,11 +8,10 @@ namespace Microsoft.eShopOnContainers.WebMVC
public class AppSettings public class AppSettings
{ {
public Connectionstrings ConnectionStrings { get; set; } public Connectionstrings ConnectionStrings { get; set; }
public string CatalogUrl { get; set; }
public string OrderingUrl { get; set; }
public string BasketUrl { get; set; }
public string MarketingUrl { get; set; } public string MarketingUrl { get; set; }
public string LocationsUrl { get; set; }
public string PurchaseUrl { get; set; }
public string SignalrHubUrl { get; set; }
public bool ActivateCampaignDetailFunction { get; set; } public bool ActivateCampaignDetailFunction { get; set; }
public Logging Logging { get; set; } public Logging Logging { get; set; }
public bool UseCustomizationData { get; set; } public bool UseCustomizationData { get; set; }

View File

@ -130,6 +130,8 @@ namespace Microsoft.eShopOnContainers.WebMVC
options.Scope.Add("basket"); options.Scope.Add("basket");
options.Scope.Add("marketing"); options.Scope.Add("marketing");
options.Scope.Add("locations"); options.Scope.Add("locations");
options.Scope.Add("webshoppingagg");
options.Scope.Add("orders.signalrhub");
}); });
} }

View File

@ -8,9 +8,9 @@
<div class="esh-orders"> <div class="esh-orders">
@Html.Partial("_Header", new List<Header>() { @Html.Partial("_Header", new List<Header>() {
new Header() { Controller = "Catalog", Text = "Back to catalog" }, new Header() { Controller = "Catalog", Text = "Back to catalog" },
new Header() { Text = " / " }, new Header() { Text = " / " },
new Header() { Controller = "OrderManagement", Text = "Orders Management" } }) new Header() { Controller = "OrderManagement", Text = "Orders Management" } })
<div class="container"> <div class="container">
<article class="esh-orders-titles row"> <article class="esh-orders-titles row">
@ -20,31 +20,30 @@
<section class="esh-orders-title col-xs-2">Status</section> <section class="esh-orders-title col-xs-2">Status</section>
<section class="esh-orders-title col-xs-2"></section> <section class="esh-orders-title col-xs-2"></section>
</article> </article>
@if (Model != null && Model.Any()) @if (Model != null && Model.Any())
{
foreach (var item in Model)
{ {
<article class="esh-orders-items row"> foreach (var item in Model)
<section class="esh-orders-item col-xs-2">@Html.DisplayFor(modelItem => item.OrderNumber)</section> {
<section class="esh-orders-item col-xs-4">@Html.DisplayFor(modelItem => item.Date)</section> <article class="esh-orders-items row">
<section class="esh-orders-item col-xs-2">$ @Html.DisplayFor(modelItem => item.Total)</section> <section class="esh-orders-item col-xs-2">@Html.DisplayFor(modelItem => item.OrderNumber)</section>
<section class="esh-orders-item col-xs-2">@Html.DisplayFor(modelItem => item.Status)</section> <section class="esh-orders-item col-xs-4">@Html.DisplayFor(modelItem => item.Date)</section>
<section class="esh-orders-item col-xs-1"> <section class="esh-orders-item col-xs-2">$ @Html.DisplayFor(modelItem => item.Total)</section>
<a class="esh-orders-link" asp-controller="Order" asp-action="Detail" asp-route-orderId="@item.OrderNumber">Detail</a> <section class="esh-orders-item col-xs-2">@Html.DisplayFor(modelItem => item.Status)</section>
</section> <section class="esh-orders-item col-xs-1">
<section class="esh-orders-item col-xs-1"> <a class="esh-orders-link" asp-controller="Order" asp-action="Detail" asp-route-orderId="@item.OrderNumber">Detail</a>
@if (item.Status.ToLower() == "submitted") </section>
{ <section class="esh-orders-item col-xs-1">
<a class="esh-orders-link" asp-controller="Order" asp-action="cancel" asp-route-orderId="@item.OrderNumber">Cancel</a> @if (item.Status.ToLower() == "submitted")
} {
</section> <a class="esh-orders-link" asp-controller="Order" asp-action="cancel" asp-route-orderId="@item.OrderNumber">Cancel</a>
</article> }
</section>
</article>
}
} }
}
</div> </div>
</div> </div>
<script>
setTimeout(function () {
window.location.reload(true);
}, 5000);
</script>

View File

@ -20,6 +20,8 @@
<link rel="stylesheet" href="~/css/orders/orders-detail/orders-detail.component.css" /> <link rel="stylesheet" href="~/css/orders/orders-detail/orders-detail.component.css" />
<link rel="stylesheet" href="~/css/orders/orders-new/orders-new.component.css" /> <link rel="stylesheet" href="~/css/orders/orders-new/orders-new.component.css" />
<link rel="stylesheet" href="~/css/override.css" type="text/css" /> <link rel="stylesheet" href="~/css/override.css" type="text/css" />
<link rel="stylesheet" href="~/css/site.min.css" type="text/css" />
</environment> </environment>
<environment names="Staging,Production"> <environment names="Staging,Production">
<link rel="stylesheet" href="https://ajax.aspnetcdn.com/ajax/bootstrap/3.3.7/css/bootstrap.min.css" <link rel="stylesheet" href="https://ajax.aspnetcdn.com/ajax/bootstrap/3.3.7/css/bootstrap.min.css"
@ -84,5 +86,54 @@
</environment> </environment>
@RenderSection("scripts", required: false) @RenderSection("scripts", required: false)
@using Microsoft.AspNetCore.Authentication;
@using Microsoft.Extensions.Options
@inject IOptions<AppSettings> settings
<script type="text/javascript">
if ('@User.Identity.IsAuthenticated' === 'True') {
var timerId;
let connection = stablishConnection();
connection.start().then(function () {
console.log('User Registered to Signalr Hub');
});
registerNotificationHandlers(connection);
}
function stablishConnection() {
let hubHttpConnection = new signalR.HttpConnection('@settings.Value.SignalrHubUrl/hub/notificationhub', {
transport: signalR.TransportType.LongPolling,
accessTokenFactory: () => {
return "Authorization", getToken();
}
});
return new signalR.HubConnection(hubHttpConnection);
}
function registerNotificationHandlers(connection) {
connection.on("UpdatedOrderState", (message) => {
toastr.success('Updated to status: ' + message.status, 'Order Id: ' + message.orderId);
if (window.location.pathname.split("/").pop() === 'Order') {
refreshOrderList();
}
});
}
function getToken() {
return '@Context.GetTokenAsync("access_token").Result';
}
function refreshOrderList() {
clearTimeout(timerId);
timerId = setTimeout(function () {
window.location.reload();
}, 1000);
}
</script>
</body> </body>
</html> </html>

View File

@ -18,9 +18,10 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="BuildBundlerMinifier" Version="2.6.375" />
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.2.1" /> <PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.2.1" />
<PackageReference Include="Microsoft.ApplicationInsights.DependencyCollector" Version="2.5.1" /> <PackageReference Include="Microsoft.ApplicationInsights.DependencyCollector" Version="2.5.1" />
<PackageReference Include="Microsoft.ApplicationInsights.Kubernetes" Version="1.0.0-beta5" /> <PackageReference Include="Microsoft.ApplicationInsights.Kubernetes" Version="1.0.0-beta6" />
<PackageReference Include="Microsoft.ApplicationInsights.ServiceFabric" Version="2.0.1-beta1" /> <PackageReference Include="Microsoft.ApplicationInsights.ServiceFabric" Version="2.0.1-beta1" />
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.5" /> <PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.5" />
<PackageReference Include="Microsoft.AspNetCore.DataProtection.Redis" Version="0.3.1" /> <PackageReference Include="Microsoft.AspNetCore.DataProtection.Redis" Version="0.3.1" />

View File

@ -8,6 +8,20 @@
"wwwroot/css/**/*.css" "wwwroot/css/**/*.css"
] ]
}, },
{
"outputFileName": "wwwroot/js/site.js",
"inputFiles": [
"wwwroot/lib/signalr/signalr.js",
"wwwroot/lib/toastr/toastr.js"
],
// Optionally specify minification options
"minify": {
"enabled": false,
"renameLocals": true
},
// Optinally generate .map file
"sourceMap": false
},
{ {
"outputFileName": "wwwroot/js/site.min.js", "outputFileName": "wwwroot/js/site.min.js",
"inputFiles": [ "inputFiles": [

26
src/Web/WebMVC/package-lock.json generated Normal file
View File

@ -0,0 +1,26 @@
{
"name": "asp.net",
"version": "1.0.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"@aspnet/signalr": {
"version": "1.0.0-preview2-final",
"resolved": "https://registry.npmjs.org/@aspnet/signalr/-/signalr-1.0.0-preview2-final.tgz",
"integrity": "sha512-XbqGbAG9Ow4L5Sc4n81A2S8lHSlxBNTjFm3WZQA94cIolPnW0bPK2u14UMooXRXxzjBtJViJMN/aoxWRwTWxig=="
},
"jquery": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/jquery/-/jquery-3.3.1.tgz",
"integrity": "sha512-Ubldcmxp5np52/ENotGxlLe6aGMvmF4R8S6tZjsP6Knsaxd/xp3Zrh50cG93lR6nPXyUFwzN3ZSOQI0wRJNdGg=="
},
"toastr": {
"version": "2.1.4",
"resolved": "https://registry.npmjs.org/toastr/-/toastr-2.1.4.tgz",
"integrity": "sha1-i0O+ZPudDEFIcURvLbjoyk6V8YE=",
"requires": {
"jquery": "3.3.1"
}
}
}
}

View File

@ -0,0 +1,10 @@
{
"version": "1.0.0",
"name": "asp.net",
"private": true,
"devDependencies": {},
"dependencies": {
"@aspnet/signalr": "^1.0.0-preview2-final",
"toastr": "^2.1.4"
}
}

Some files were not shown because too many files have changed in this diff Show More