Browse Source

Merge pull request #1 from dotnet-architecture/dev

upd
pull/1934/head
Taras Kovalenko 7 years ago
committed by GitHub
parent
commit
8676343f66
107 changed files with 12507 additions and 6572 deletions
  1. +14
    -15
      .env
  2. +1
    -0
      .gitattributes
  3. +3
    -1
      README.md
  4. +11
    -0
      branch-guide.md
  5. +1
    -0
      cli-linux/build-bits-linux.sh
  6. +1
    -0
      cli-linux/docker-compose.local.build.yml
  7. +0
    -3
      cli-linux/prepare-spa-app.sh
  8. +0
    -1
      cli-linux/run.sh
  9. +2
    -2
      cli-windows/add-firewall-rules-for-sts-auth-thru-docker.ps1
  10. +0
    -20
      deploy/az/azurefunctions/azurefunctionsdeploy.json
  11. +82
    -23
      docker-compose-windows.override.yml
  12. +88
    -17
      docker-compose-windows.prod.yml
  13. +30
    -3
      docker-compose-windows.yml
  14. +7
    -3
      docker-compose.ci.build.yml
  15. +7
    -0
      docker-compose.override.yml
  16. +12
    -3
      docker-compose.prod.yml
  17. BIN
      docs/Containerized Docker Application Lifecycle with Microsoft Platform and Tools (eBook).pdf
  18. BIN
      docs/Containerized-Docker-Application-Lifecycle-with-Microsoft-Platform-and-Tools-(eBook)_v1.1.pdf
  19. BIN
      docs/Enterprise-Application-Patterns-using-XamarinForms.pdf
  20. +3
    -1
      eShopOnContainers-MobileApps.sln
  21. +424
    -1
      eShopOnContainers.sln
  22. +1
    -1
      global.json
  23. BIN
      img/k8s/deploy_script_task.png
  24. +24
    -10
      k8s/README.CICD.k8s.md
  25. +11
    -1
      k8s/README.k8s.md
  26. +17
    -0
      k8s/conf-files.md
  27. +11
    -4
      k8s/deploy.ps1
  28. +45
    -0
      k8s/deployments.yaml
  29. BIN
      k8s/img/blob_creation.png
  30. BIN
      k8s/img/deploy_script_task.png
  31. BIN
      k8s/img/get_kubectlbin_task.png
  32. BIN
      k8s/img/get_kubectlconfig_task.png
  33. +12
    -0
      k8s/readme.md
  34. +0
    -0
      readme/README.ENV.md
  35. +79
    -0
      readme/readme-docker-compose.md
  36. +19
    -0
      readme/readme.md
  37. +5
    -3
      src/BuildingBlocks/EventBus/EventBusServiceBus/EventBusServiceBus.cs
  38. +5
    -5
      src/BuildingBlocks/Resilience/Resilience.Http/StandardHttpClient.cs
  39. +1
    -6
      src/Mobile/eShopOnContainers/eShopOnContainers.Core/App.xaml
  40. +23
    -0
      src/Mobile/eShopOnContainers/eShopOnContainers.Core/Helpers/RandomNumberGenerator.cs
  41. +4
    -4
      src/Mobile/eShopOnContainers/eShopOnContainers.Core/Helpers/ServicesHelper.cs
  42. +2
    -2
      src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Common/Common.cs
  43. +21
    -3
      src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Identity/IdentityService.cs
  44. +2
    -2
      src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Marketing/CampaignMockService.cs
  45. +1
    -1
      src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Marketing/CampaignService.cs
  46. +7
    -7
      src/Mobile/eShopOnContainers/eShopOnContainers.Core/ViewModels/SettingsViewModel.cs
  47. +3
    -0
      src/Mobile/eShopOnContainers/eShopOnContainers.Core/Views/CampaignDetailsView.xaml
  48. +1
    -1
      src/Mobile/eShopOnContainers/eShopOnContainers.Core/Views/CampaignView.xaml
  49. +5
    -1
      src/Mobile/eShopOnContainers/eShopOnContainers.Core/Views/LoginView.xaml
  50. +4
    -2
      src/Mobile/eShopOnContainers/eShopOnContainers.Core/Views/SettingsView.xaml
  51. +1
    -0
      src/Mobile/eShopOnContainers/eShopOnContainers.Core/eShopOnContainers.Core.csproj
  52. +1
    -0
      src/Mobile/eShopOnContainers/eShopOnContainers.Core/project.json
  53. +18
    -0
      src/Mobile/eShopOnContainers/eShopOnContainers.Droid/eShopOnContainers.Droid.csproj
  54. +6
    -0
      src/Mobile/eShopOnContainers/eShopOnContainers.Droid/packages.config
  55. +2
    -0
      src/Mobile/eShopOnContainers/eShopOnContainers.TestRunner.Droid/Resources/Resource.Designer.cs
  56. +18
    -0
      src/Mobile/eShopOnContainers/eShopOnContainers.TestRunner.Droid/eShopOnContainers.TestRunner.Droid.csproj
  57. +6
    -0
      src/Mobile/eShopOnContainers/eShopOnContainers.TestRunner.Droid/packages.config
  58. +22
    -2
      src/Mobile/eShopOnContainers/eShopOnContainers.TestRunner.iOS/eShopOnContainers.TestRunner.iOS.csproj
  59. +6
    -0
      src/Mobile/eShopOnContainers/eShopOnContainers.TestRunner.iOS/packages.config
  60. +1
    -0
      src/Mobile/eShopOnContainers/eShopOnContainers.Windows/project.json
  61. +20
    -1
      src/Mobile/eShopOnContainers/eShopOnContainers.iOS/eShopOnContainers.iOS.csproj
  62. +6
    -0
      src/Mobile/eShopOnContainers/eShopOnContainers.iOS/packages.config
  63. BIN
      src/Services/Catalog/Catalog.API/Setup/CatalogItems.zip
  64. +8
    -0
      src/Services/GracePeriod/GracePeriodManager/Dockerfile.nanowin
  65. +1
    -0
      src/Services/Identity/Identity.API/Configuration/Config.cs
  66. +8
    -0
      src/Services/Location/Locations.API/Dockerfile.nanowin
  67. +8
    -0
      src/Services/Marketing/Marketing.API/Dockerfile.nanowin
  68. +23
    -0
      src/Services/Ordering/Ordering.API/Application/Behaviors/LoggingBehavior.cs
  69. +7
    -18
      src/Services/Ordering/Ordering.API/Application/Behaviors/ValidatorBehavior.cs
  70. +0
    -34
      src/Services/Ordering/Ordering.API/Application/Decorators/LogDecorator.cs
  71. +10
    -15
      src/Services/Ordering/Ordering.API/Infrastructure/AutofacModules/MediatorModule.cs
  72. +8
    -0
      src/Services/Payment/Payment.API/Dockerfile.nanowin
  73. +2
    -0
      src/Web/WebMVC/WebMVC.csproj
  74. +11322
    -3390
      src/Web/WebSPA/package-lock.json
  75. +3
    -3
      src/Web/WebSPA/package.json
  76. +8
    -0
      src/Web/WebStatus/Dockerfile.nanowin
  77. +0
    -5
      src/Web/WebStatus/Views/Shared/_Layout.cshtml
  78. +0
    -18
      src/Web/WebStatus/Views/Shared/_ValidationScriptsPartial.cshtml
  79. +1
    -3
      src/Web/WebStatus/bower.json
  80. +0
    -1
      src/Web/WebStatus/wwwroot/images/banner1.svg
  81. +0
    -1
      src/Web/WebStatus/wwwroot/images/banner2.svg
  82. +0
    -1
      src/Web/WebStatus/wwwroot/images/banner3.svg
  83. +0
    -1
      src/Web/WebStatus/wwwroot/images/banner4.svg
  84. +0
    -1
      src/Web/WebStatus/wwwroot/js/site.js
  85. +0
    -0
      src/Web/WebStatus/wwwroot/js/site.min.js
  86. +0
    -44
      src/Web/WebStatus/wwwroot/lib/jquery-validation-unobtrusive/.bower.json
  87. +0
    -416
      src/Web/WebStatus/wwwroot/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js
  88. +0
    -5
      src/Web/WebStatus/wwwroot/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js
  89. +0
    -40
      src/Web/WebStatus/wwwroot/lib/jquery-validation/.bower.json
  90. +0
    -22
      src/Web/WebStatus/wwwroot/lib/jquery-validation/LICENSE.md
  91. +0
    -998
      src/Web/WebStatus/wwwroot/lib/jquery-validation/dist/additional-methods.js
  92. +0
    -4
      src/Web/WebStatus/wwwroot/lib/jquery-validation/dist/additional-methods.min.js
  93. +0
    -1398
      src/Web/WebStatus/wwwroot/lib/jquery-validation/dist/jquery.validate.js
  94. +0
    -4
      src/Web/WebStatus/wwwroot/lib/jquery-validation/dist/jquery.validate.min.js
  95. BIN
      vsts-docs/builds/images/android-build-step1.png
  96. BIN
      vsts-docs/builds/images/android-build-step2.png
  97. BIN
      vsts-docs/builds/images/android-build-step3.png
  98. BIN
      vsts-docs/builds/images/android-build-step4.png
  99. BIN
      vsts-docs/builds/images/android-build-step5.png
  100. BIN
      vsts-docs/builds/images/android-build.png

+ 14
- 15
.env View File

@ -7,18 +7,17 @@
ESHOP_EXTERNAL_DNS_NAME_OR_IP=localhost ESHOP_EXTERNAL_DNS_NAME_OR_IP=localhost
ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP=10.121.122.92 ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP=10.121.122.92
#ESHOP_AZURE_REDIS_BASKET_DB=
#ESHOP_AZURE_STORAGE_CATALOG=
#ESHOP_AZURE_STORAGE_MARKETING=
#ESHOP_AZURE_SERVICE_BUS=
#ESHOP_AZURE_COSMOSDB=
#ESHOP_AZURE_CATALOG_DB=
#ESHOP_AZURE_IDENTITY_DB=
#ESHOP_AZURE_ORDERING_DB=
#ESHOP_AZURE_MARKETING_DB=
#ESHOP_AZUREFUNC_CAMPAIGN_DETAILS_URI=
#ESHOP_AZURE_STORAGE_CATALOG_NAME=
#ESHOP_AZURE_STORAGE_CATALOG_KEY=
#ESHOP_AZURE_STORAGE_MARKETING_NAME=
#ESHOP_AZURE_STORAGE_MARKETING_KEY=
#ESHOP_AZURE_REDIS_BASKET_DB=<YourAzureRedisBasketInfo>
#ESHOP_AZURE_STORAGE_CATALOG=<YourAzureStorageCatalog>
#ESHOP_AZURE_STORAGE_MARKETING=<YourAzureStorageMarketing>
#ESHOP_AZURE_SERVICE_BUS=<YourAzureServiceBusInfo>
#ESHOP_AZURE_COSMOSDB=<YourAzureCosmosDBConnData>
#ESHOP_AZURE_CATALOG_DB=<YourAzureSQLDBCatalogDBConnString>
#ESHOP_AZURE_IDENTITY_DB=<YourAzureSQLDBIdentityDBConnString>
#ESHOP_AZURE_ORDERING_DB=<YourAzureSQLDBOrderingDBConnString>
#ESHOP_AZURE_MARKETING_DB=<YourAzureSQLDBMarketingDBConnString>
#ESHOP_AZUREFUNC_CAMPAIGN_DETAILS_URI=<YourAzureFunctionCampaignDetailsURI>
#ESHOP_AZURE_STORAGE_CATALOG_NAME=<YourAzureStorageCatalogName>
#ESHOP_AZURE_STORAGE_CATALOG_KEY=<YourAzureStorageCatalogKey>
#ESHOP_AZURE_STORAGE_MARKETING_NAME=<YourAzureStorageMarketingName>
#ESHOP_AZURE_STORAGE_MARKETING_KEY=<YourAzureStorageMarketingKey>

+ 1
- 0
.gitattributes View File

@ -2,6 +2,7 @@
# Set default behavior to automatically normalize line endings. # Set default behavior to automatically normalize line endings.
############################################################################### ###############################################################################
* text=auto * text=auto
*.sh text eol=lf
############################################################################### ###############################################################################
# Set default behavior for command prompt diff. # Set default behavior for command prompt diff.


+ 3
- 1
README.md View File

@ -2,6 +2,8 @@
Sample .NET Core reference application, powered by Microsoft, based on a simplified microservices architecture and Docker containers. <p> Sample .NET Core reference application, powered by Microsoft, based on a simplified microservices architecture and Docker containers. <p>
**Note for Pull Requests**: 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, if possible. **Note for Pull Requests**: 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, if possible.
>**PLEASE** Read our [branch guide](./branch-guide.md) to know about our branching policy
> ### DISCLAIMER > ### DISCLAIMER
> **IMPORTANT:** The current state of this sample application is **BETA**, consider it version a 0.1 foundational version, therefore, many areas could be improved and change significantly while refactoring current code and implementing new features. **Feedback with improvements and pull requests from the community will be highly appreciated and accepted.** > **IMPORTANT:** The current state of this sample application is **BETA**, consider it version a 0.1 foundational version, therefore, many areas could be improved and change significantly while refactoring current code and implementing new features. **Feedback with improvements and pull requests from the community will be highly appreciated and accepted.**
> >
@ -41,7 +43,7 @@ You can download them and start reviewing these Guides/eBooks here:
| Architecting & Developing | Containers Lifecycle & CI/CD | App patterns with Xamarin.Forms | | Architecting & Developing | Containers Lifecycle & CI/CD | App patterns with Xamarin.Forms |
| ------------ | ------------| ------------| | ------------ | ------------| ------------|
| <a href='https://aka.ms/microservicesebook'><img src="img/ebook_arch_dev_microservices_containers_cover.png"> </a> | <a href='https://aka.ms/dockerlifecycleebook'> <img src="img/ebook_containers_lifecycle.png"> </a> | <a href='https://aka.ms/xamarinpatternsebook'> <img src="img/xamarin-enterprise-patterns-ebook-cover-small.png"> </a> | | <a href='https://aka.ms/microservicesebook'><img src="img/ebook_arch_dev_microservices_containers_cover.png"> </a> | <a href='https://aka.ms/dockerlifecycleebook'> <img src="img/ebook_containers_lifecycle.png"> </a> | <a href='https://aka.ms/xamarinpatternsebook'> <img src="img/xamarin-enterprise-patterns-ebook-cover-small.png"> </a> |
| <sup> <a href='https://aka.ms/microservicesebook'>**Download** (First Edition)</a> </sup> | <sup> <a href='https://aka.ms/dockerlifecycleebook'>**Download** (First Edition from late 2016) </a> </sup> | <sup> <a href='https://aka.ms/xamarinpatternsebook'>**Download** (First Edition) </a> </sup> |
| <sup> <a href='https://aka.ms/microservicesebook'>**Download** (First Edition)</a> </sup> | <sup> <a href='https://aka.ms/dockerlifecycleebook'>**Download** (First Edition) </a> </sup> | <sup> <a href='https://aka.ms/xamarinpatternsebook'>**Download** (First Edition) </a> </sup> |
Send feedback to [dotnet-architecture-ebooks-feedback@service.microsoft.com](dotnet-architecture-ebooks-feedback@service.microsoft.com) Send feedback to [dotnet-architecture-ebooks-feedback@service.microsoft.com](dotnet-architecture-ebooks-feedback@service.microsoft.com)
<p> <p>


+ 11
- 0
branch-guide.md View File

@ -0,0 +1,11 @@
# eShopOnContainers - BRANCH GUIDE
Following are the most important branches:
- `dev`: Contains the latest code **and it is the branch actively developed**. Note that **all PRs must be against `dev` branch to be considered**.
- `master`: Synced time to time from dev. It contains "stable" code, although not the latest one. We plan to do periodic merges from `dev` to `master`, but we are not doing it right now.
- `netcore2`: Contains NETCore 2.0 (preview2) based code. All APIs and webs are migrated to netcore2 except `Identity.API` which still uses netcore1.1 (because of Identity Server). Dockerfiles are updated also. Use this branch to test the NETCore 2.0 code. You can also submit PR to this branch if they are related to netcore2.
Any other branch is considered temporary and could be deleted at any time. Do not do any PR to them!
Thanks!

+ 1
- 0
cli-linux/build-bits-linux.sh View File

@ -50,3 +50,4 @@ done
# No need to build the images, docker build or docker compose will # No need to build the images, docker build or docker compose will
# do that using the images and containers defined in the docker-compose.yml file. # do that using the images and containers defined in the docker-compose.yml file.
#

+ 1
- 0
cli-linux/docker-compose.local.build.yml View File

@ -7,3 +7,4 @@ services:
- .:/src - .:/src
working_dir: /src working_dir: /src
command: /bin/bash -c "chmod -x ./cli-linux/build-bits-linux.sh && ./cli-linux/build-bits-linux.sh" command: /bin/bash -c "chmod -x ./cli-linux/build-bits-linux.sh && ./cli-linux/build-bits-linux.sh"

+ 0
- 3
cli-linux/prepare-spa-app.sh View File

@ -1,7 +1,4 @@
# Build SPA app # Build SPA app
pushd $(pwd)/src/Web/WebSPA pushd $(pwd)/src/Web/WebSPA
npm rebuild node-sass npm rebuild node-sass
#npm run build:prod #npm run build:prod

+ 0
- 1
cli-linux/run.sh View File

@ -4,4 +4,3 @@ docker rm $(docker ps -a -q)
docker images |grep -v REPOSITORY|awk '{print $1}'|xargs -L1 docker pull docker images |grep -v REPOSITORY|awk '{print $1}'|xargs -L1 docker pull
export ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP=$(curl ipinfo.io/ip) export ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP=$(curl ipinfo.io/ip)
docker-compose -f docker-compose.images.yml -f docker-compose.prod.yml up -d --force-recreate docker-compose -f docker-compose.images.yml -f docker-compose.prod.yml up -d --force-recreate

+ 2
- 2
cli-windows/add-firewall-rules-for-sts-auth-thru-docker.ps1 View File

@ -21,6 +21,6 @@ try {
Write-Host "Rule found" Write-Host "Rule found"
} }
catch [Exception] { catch [Exception] {
New-NetFirewallRule -DisplayName eShopOnContainers-Inbound -Confirm -Description "eShopOnContainers Inbound Rule for port range 5100-5105" -LocalAddress Any -LocalPort 5100-5110 -Protocol tcp -RemoteAddress Any -RemotePort Any -Direction Inbound
New-NetFirewallRule -DisplayName eShopOnContainers-Outbound -Confirm -Description "eShopOnContainers Outbound Rule for port range 5100-5105" -LocalAddress Any -LocalPort 5100-5110 -Protocol tcp -RemoteAddress Any -RemotePort Any -Direction Outbound
New-NetFirewallRule -DisplayName eShopOnContainers-Inbound -Confirm -Description "eShopOnContainers Inbound Rule for port range 5100-5110" -LocalAddress Any -LocalPort 5100-5110 -Protocol tcp -RemoteAddress Any -RemotePort Any -Direction Inbound
New-NetFirewallRule -DisplayName eShopOnContainers-Outbound -Confirm -Description "eShopOnContainers Outbound Rule for port range 5100-5110" -LocalAddress Any -LocalPort 5100-5110 -Protocol tcp -RemoteAddress Any -RemotePort Any -Direction Outbound
} }

+ 0
- 20
deploy/az/azurefunctions/azurefunctionsdeploy.json View File

@ -13,30 +13,10 @@
"SitesEshopfunctionsName": "[parameters('SitesEshopfunctionsName')]", "SitesEshopfunctionsName": "[parameters('SitesEshopfunctionsName')]",
"WebConfigName": "[concat(variables('SitesEshopfunctionsName'), '/web')]", "WebConfigName": "[concat(variables('SitesEshopfunctionsName'), '/web')]",
"Location": "[resourceGroup().location]", "Location": "[resourceGroup().location]",
"EshopAccountsDatabase": "[concat(variables('SitesEshopfunctionsName'), 'db')]",
"ServerFarmPlan": "[concat(trim(variables('location')), 'Plan')]", "ServerFarmPlan": "[concat(trim(variables('location')), 'Plan')]",
"StorageAccounts": "[concat(variables('SitesEshopfunctionsName'), 'st')]" "StorageAccounts": "[concat(variables('SitesEshopfunctionsName'), 'st')]"
}, },
"resources": [ "resources": [
{
"type": "Microsoft.DocumentDB/databaseAccounts",
"kind": "GlobalDocumentDB",
"name": "[variables('EshopAccountsDatabase')]",
"apiVersion": "2015-04-08",
"location": "[variables('Location')]",
"tags": {},
"scale": null,
"properties": {
"databaseAccountOfferType": "Standard",
"consistencyPolicy": {
"defaultConsistencyLevel": "Session",
"maxIntervalInSeconds": 5,
"maxStalenessPrefix": 100
},
"name": null
},
"dependsOn": []
},
{ {
"type": "Microsoft.Storage/storageAccounts", "type": "Microsoft.Storage/storageAccounts",
"sku": { "sku": {


+ 82
- 23
docker-compose-windows.override.yml View File

@ -12,9 +12,11 @@ services:
environment: environment:
- ASPNETCORE_ENVIRONMENT=Development - ASPNETCORE_ENVIRONMENT=Development
- ASPNETCORE_URLS=http://0.0.0.0:80 - ASPNETCORE_URLS=http://0.0.0.0:80
- ConnectionString=basket.data
- identityUrl=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5105. at range 5100-5105.
- EventBusConnection=rabbitmq
- ConnectionString=${ESHOP_AZURE_REDIS_BASKET_DB:-basket.data}
- identityUrl=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5110.
- IdentityUrlExternal=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5105
- EventBusConnection=${ESHOP_AZURE_SERVICE_BUS:-rabbitmq}
- AzureServiceBusEnabled=False
ports: ports:
- "5103:80" - "5103:80"
@ -22,9 +24,13 @@ services:
environment: environment:
- ASPNETCORE_ENVIRONMENT=Development - ASPNETCORE_ENVIRONMENT=Development
- ASPNETCORE_URLS=http://0.0.0.0:80 - ASPNETCORE_URLS=http://0.0.0.0:80
- ConnectionString=Server=sql.data;Database=Microsoft.eShopOnContainers.Services.CatalogDb;User Id=sa;Password=Pass@word
- ExternalCatalogBaseUrl=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5101 #Local: You need to open your local dev-machine firewall at range 5100-5105. at range 5100-5105.
- EventBusConnection=rabbitmq
- ConnectionString=${ESHOP_AZURE_CATALOG_DB:-Server=sql.data;Database=Microsoft.eShopOnContainers.Services.CatalogDb;User Id=sa;Password=Pass@word}
- PicBaseUrl=${ESHOP_AZURE_STORAGE_CATALOG:-http://localhost:5101/api/v1/catalog/items/[0]/pic/} #Local: You need to open your local dev-machine firewall at range 5100-5110.
- EventBusConnection=${ESHOP_AZURE_SERVICE_BUS:-rabbitmq}
- AzureStorageAccountName=${ESHOP_AZURE_STORAGE_CATALOG_NAME}
- AzureStorageAccountKey=${ESHOP_AZURE_STORAGE_CATALOG_KEY}
- UseCustomizationData=True
- AzureServiceBusEnabled=False
ports: ports:
- "5101:80" - "5101:80"
@ -33,8 +39,14 @@ services:
- ASPNETCORE_ENVIRONMENT=Development - ASPNETCORE_ENVIRONMENT=Development
- ASPNETCORE_URLS=http://0.0.0.0:80 - ASPNETCORE_URLS=http://0.0.0.0:80
- SpaClient=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5104 - SpaClient=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5104
- ConnectionStrings__DefaultConnection=Server=sql.data;Database=Microsoft.eShopOnContainers.Service.IdentityDb;User Id=sa;Password=Pass@word
- MvcClient=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5100 #Local: You need to open your local dev-machine firewall at range 5100-5105.
- XamarinCallback=http://${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}:5105/xamarincallback #localhost do not work for UWP login, so we have to use "external" IP always
- ConnectionStrings__DefaultConnection=${ESHOP_AZURE_IDENTITY_DB:-Server=sql.data;Database=Microsoft.eShopOnContainers.Service.IdentityDb;User Id=sa;Password=Pass@word}
- MvcClient=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5100 #Local: You need to open your local dev-machine firewall at range 5100-5110.
- LocationApiClient=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5109
- MarketingApiClient=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5110
- BasketApiClient=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5103
- OrderingApiClient=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5102
- UseCustomizationData=True
ports: ports:
- "5105:80" - "5105:80"
@ -42,9 +54,12 @@ services:
environment: environment:
- ASPNETCORE_ENVIRONMENT=Development - ASPNETCORE_ENVIRONMENT=Development
- ASPNETCORE_URLS=http://0.0.0.0:80 - ASPNETCORE_URLS=http://0.0.0.0:80
- ConnectionString=Server=sql.data;Database=Microsoft.eShopOnContainers.Services.OrderingDb;User Id=sa;Password=Pass@word
- identityUrl=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5105. at range 5100-5105.
- EventBusConnection=rabbitmq
- ConnectionString=${ESHOP_AZURE_ORDERING_DB:-Server=sql.data;Database=Microsoft.eShopOnContainers.Services.OrderingDb;User Id=sa;Password=Pass@word}
- identityUrl=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5110.
- IdentityUrlExternal=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5105
- EventBusConnection=${ESHOP_AZURE_SERVICE_BUS:-rabbitmq}
- UseCustomizationData=True
- AzureServiceBusEnabled=False
ports: ports:
- "5102:80" - "5102:80"
@ -55,11 +70,14 @@ services:
- CatalogUrl=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5101 - CatalogUrl=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5101
- OrderingUrl=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5102 - OrderingUrl=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5102
- 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.
- BasketUrl=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5103
- BasketUrl=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5103
- MarketingUrl=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5110
- 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.
- BasketUrlHC=http://basket.api/hc
- BasketUrlHC=http://basket.api/hc
- MarketingUrlHC=http://marketing.api/hc
- UseCustomizationData=True
ports: ports:
- "5104:80" - "5104:80"
@ -70,8 +88,9 @@ services:
- CatalogUrl=http://catalog.api - CatalogUrl=http://catalog.api
- OrderingUrl=http://ordering.api - OrderingUrl=http://ordering.api
- BasketUrl=http://basket.api - BasketUrl=http://basket.api
- IdentityUrl=http://10.0.75.1:5105 #Local: Use 10.0.75.1 in a "Docker for Windows" environment, if using "localhost" from browser.
#Remote: Use ${ESHOP_EXTERNAL_DNS_NAME_OR_IP} if using external IP or DNS name from browser.
- IdentityUrl=http://10.0.75.1:5105
- MarketingUrl=http://marketing.api #Local: Use 10.0.75.1 in a "Docker for Windows" environment, if using "localhost" from browser.
- UseCustomizationData=True #Remote: Use ${ESHOP_EXTERNAL_DNS_NAME_OR_IP} if using external IP or DNS name from browser.
ports: ports:
- "5100:80" - "5100:80"
@ -90,10 +109,12 @@ services:
environment: environment:
- ASPNETCORE_ENVIRONMENT=Development - ASPNETCORE_ENVIRONMENT=Development
- ASPNETCORE_URLS=http://0.0.0.0:80 - ASPNETCORE_URLS=http://0.0.0.0:80
- ConnectionString=mongodb://nosql.data
- ConnectionString=${ESHOP_AZURE_COSMOSDB:-mongodb://nosql.data}
- Database=LocationsDb - Database=LocationsDb
- identityUrl=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5105. at range 5100-5105.
- EventBusConnection=rabbitmq
- identityUrl=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5110.
- IdentityUrlExternal=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5105
- EventBusConnection=${ESHOP_AZURE_SERVICE_BUS:-rabbitmq}
- AzureServiceBusEnabled=False
ports: ports:
- "5109:80" - "5109:80"
@ -101,10 +122,48 @@ services:
environment: environment:
- ASPNETCORE_ENVIRONMENT=Development - ASPNETCORE_ENVIRONMENT=Development
- ASPNETCORE_URLS=http://0.0.0.0:80 - ASPNETCORE_URLS=http://0.0.0.0:80
- ConnectionString=Server=sql.data;Database=Microsoft.eShopOnContainers.Services.MarketingDb;User Id=sa;Password=Pass@word
- EventBusConnection=rabbitmq
- MongoConnectionString=mongodb://nosql.data
- ConnectionString=${ESHOP_AZURE_MARKETING_DB:-Server=sql.data;Database=Microsoft.eShopOnContainers.Services.MarketingDb;User Id=sa;Password=Pass@word}
- MongoConnectionString=${ESHOP_AZURE_COSMOSDB:-mongodb://nosql.data}
- MongoDatabase=MarketingDb - MongoDatabase=MarketingDb
- identityUrl=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5105. at range 5100-5105.
- EventBusConnection=${ESHOP_AZURE_SERVICE_BUS:-rabbitmq}
- identityUrl=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5110.
- IdentityUrlExternal=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5105
- CampaignDetailFunctionUri=${ESHOP_AZUREFUNC_CAMPAIGN_DETAILS_URI}
- PicBaseUrl=${ESHOP_AZURE_STORAGE_MARKETING:-http://localhost:5110/api/v1/campaigns/[0]/pic/}
- AzureStorageAccountName=${ESHOP_AZURE_STORAGE_MARKETING_NAME}
- AzureStorageAccountKey=${ESHOP_AZURE_STORAGE_MARKETING_KEY}
- AzureServiceBusEnabled=False
ports:
- "5110:80"
graceperiodmanager:
environment:
- ASPNETCORE_ENVIRONMENT=Development
- ASPNETCORE_URLS=http://0.0.0.0:80
- ConnectionString=Server=sql.data;Database=Microsoft.eShopOnContainers.Services.OrderingDb;User Id=sa;Password=Pass@word
- EventBusConnection=${ESHOP_AZURE_SERVICE_BUS:-rabbitmq}
- AzureServiceBusEnabled=False
webstatus:
environment:
- ASPNETCORE_ENVIRONMENT=Development
- ASPNETCORE_URLS=http://0.0.0.0:80
- CatalogUrl=http://catalog.api/hc
- OrderingUrl=http://ordering.api/hc
- BasketUrl=http://basket.api/hc
- IdentityUrl=http://identity.api/hc
- LocationsUrl=http://locations.api/hc
- MarketingUrl=http://marketing.api/hc
- mvc=http://webmvc/hc
- spa=http://webspa/hc
ports:
- "5107:80"
payment.api:
environment:
- ASPNETCORE_ENVIRONMENT=Development
- ASPNETCORE_URLS=http://0.0.0.0:80
- EventBusConnection=${ESHOP_AZURE_SERVICE_BUS:-rabbitmq}
- AzureServiceBusEnabled=False
ports: ports:
- "5110:80"
- "5108:80"

+ 88
- 17
docker-compose-windows.prod.yml View File

@ -17,8 +17,10 @@ services:
environment: environment:
- ASPNETCORE_ENVIRONMENT=Production - ASPNETCORE_ENVIRONMENT=Production
- ASPNETCORE_URLS=http://0.0.0.0:80 - ASPNETCORE_URLS=http://0.0.0.0:80
- ConnectionString=basket.data
- identityUrl=http://identity.api #Local: You need to open your host's firewall at range 5100-5105. at range 5100-5105.
- ConnectionString=${ESHOP_AZURE_REDIS_BASKET_DB:-basket.data}
- identityUrl=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5110.
- IdentityUrlExternal=http://${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}:5105
- EventBusConnection=${ESHOP_AZURE_SERVICE_BUS:-rabbitmq}
ports: ports:
- "5103:5103" - "5103:5103"
@ -26,8 +28,12 @@ services:
environment: environment:
- ASPNETCORE_ENVIRONMENT=Production - ASPNETCORE_ENVIRONMENT=Production
- ASPNETCORE_URLS=http://0.0.0.0:80 - ASPNETCORE_URLS=http://0.0.0.0:80
- ConnectionString=Server=sql.data;Database=Microsoft.eShopOnContainers.Services.CatalogDb;User Id=sa;Password=Pass@word
- ExternalCatalogBaseUrl=http://${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}:5101 #Local: You need to open your host's firewall at range 5100-5105. at range 5100-5105.
- ConnectionString=${ESHOP_AZURE_CATALOG_DB:-Server=sql.data;Database=Microsoft.eShopOnContainers.Services.CatalogDb;User Id=sa;Password=Pass@word}
- PicBaseUrl=${ESHOP_AZURE_STORAGE_CATALOG} #Local: You need to open your local dev-machine firewall at range 5100-5110.
- EventBusConnection=${ESHOP_AZURE_SERVICE_BUS:-rabbitmq}
- AzureStorageAccountName=${ESHOP_AZURE_STORAGE_CATALOG_NAME}
- AzureStorageAccountKey=${ESHOP_AZURE_STORAGE_CATALOG_KEY}
- UseCustomizationData=True
ports: ports:
- "5101:80" - "5101:80"
@ -36,8 +42,14 @@ services:
- ASPNETCORE_ENVIRONMENT=Production - ASPNETCORE_ENVIRONMENT=Production
- ASPNETCORE_URLS=http://0.0.0.0:80 - ASPNETCORE_URLS=http://0.0.0.0:80
- SpaClient=http://${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}:5104 - SpaClient=http://${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}:5104
- ConnectionStrings__DefaultConnection=Server=sql.data;Database=Microsoft.eShopOnContainers.Service.IdentityDb;User Id=sa;Password=Pass@word
- MvcClient=http://${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}:5100 #Local: You need to open your host's firewall at range 5100-5105.
- XamarinCallback=http://${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}:5105/xamarincallback
- ConnectionStrings__DefaultConnection=${ESHOP_AZURE_IDENTITY_DB:-Server=sql.data;Database=Microsoft.eShopOnContainers.Service.IdentityDb;User Id=sa;Password=Pass@word}
- MvcClient=http://${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}:5100 #Local: You need to open your local dev-machine firewall at range 5100-5110.
- LocationApiClient=http://${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}:5109
- MarketingApiClient=http://${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}:5110
- BasketApiClient=http://${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}:5103
- OrderingApiClient=http://${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}:5102
- UseCustomizationData=True
ports: ports:
- "5105:80" - "5105:80"
@ -45,8 +57,11 @@ services:
environment: environment:
- ASPNETCORE_ENVIRONMENT=Production - ASPNETCORE_ENVIRONMENT=Production
- ASPNETCORE_URLS=http://0.0.0.0:80 - ASPNETCORE_URLS=http://0.0.0.0:80
- ConnectionString=Server=sql.data;Database=Microsoft.eShopOnContainers.Services.OrderingDb;User Id=sa;Password=Pass@word
- identityUrl=http://identity.api:5105 #Local: You need to open your host's firewall at range 5100-5105. at range 5100-5105.
- ConnectionString=${ESHOP_AZURE_ORDERING_DB:-Server=sql.data;Database=Microsoft.eShopOnContainers.Services.OrderingDb;User Id=sa;Password=Pass@word}
- identityUrl=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5110.
- IdentityUrlExternal=http://${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}:5105
- EventBusConnection=${ESHOP_AZURE_SERVICE_BUS:-rabbitmq}
- UseCustomizationData=True
ports: ports:
- "5102:80" - "5102:80"
@ -56,12 +71,15 @@ services:
- ASPNETCORE_URLS=http://0.0.0.0 - ASPNETCORE_URLS=http://0.0.0.0
- CatalogUrl=http://${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}:5101 - CatalogUrl=http://${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}:5101
- OrderingUrl=http://${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}:5102 - OrderingUrl=http://${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}:5102
- IdentityUrl=http://${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}:5105 #Local: You need to open your host's firewall at range 5100-5105. at range 5100-5105.
- BasketUrl=http://${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}:5103
- IdentityUrl=http://${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}:5105 #Local: You need to open your host's firewall at range 5100-5110.
- BasketUrl=http://${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}:5103
- MarketingUrl=http://${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}:5110
- 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.
- BasketUrlHC=http://basket.api/hc
- BasketUrlHC=http://basket.api/hc
- MarketingUrlHC=http://marketing.api/hc
- UseCustomizationData=True
ports: ports:
- "5104:80" - "5104:80"
@ -73,6 +91,7 @@ services:
- OrderingUrl=http://ordering.api - OrderingUrl=http://ordering.api
- IdentityUrl=http://${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}:5105 #Local: Use ${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}, if using external IP or DNS name from browser. - IdentityUrl=http://${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}:5105 #Local: Use ${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}, if using external IP or DNS name from browser.
- BasketUrl=http://basket.api - BasketUrl=http://basket.api
- MarketingUrl=http://marketing.api
ports: ports:
- "5100:80" - "5100:80"
@ -80,17 +99,69 @@ services:
environment: environment:
- ASPNETCORE_ENVIRONMENT=Production - ASPNETCORE_ENVIRONMENT=Production
- ASPNETCORE_URLS=http://0.0.0.0:80 - ASPNETCORE_URLS=http://0.0.0.0:80
- ConnectionString=Server=sql.data;Database=Microsoft.eShopOnContainers.Services.MarketingDb;User Id=sa;Password=Pass@word
- EventBusConnection=rabbitmq
- MongoConnectionString=mongodb://nosql.data
- ConnectionString=${ESHOP_AZURE_MARKETING_DB:-Server=sql.data;Database=Microsoft.eShopOnContainers.Services.MarketingDb;User Id=sa;Password=Pass@word}
- MongoConnectionString=${ESHOP_AZURE_COSMOSDB:-mongodb://nosql.data}
- MongoDatabase=MarketingDb - MongoDatabase=MarketingDb
- identityUrl=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5105. at range 5100-5105.
- EventBusConnection=${ESHOP_AZURE_SERVICE_BUS:-rabbitmq}
- identityUrl=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5110.
- IdentityUrlExternal=http://${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}:5105
- CampaignDetailFunctionUri=${ESHOP_AZUREFUNC_CAMPAIGN_DETAILS_URI}
- PicBaseUrl=${ESHOP_AZURE_STORAGE_MARKETING}
- AzureStorageAccountName=${ESHOP_AZURE_STORAGE_MARKETING_NAME}
- AzureStorageAccountKey=${ESHOP_AZURE_STORAGE_MARKETING_KEY}
ports: ports:
- "5110:80" - "5110:80"
graceperiodmanager:
environment:
- ASPNETCORE_ENVIRONMENT=Production
- ASPNETCORE_URLS=http://0.0.0.0:80
- ConnectionString=Server=sql.data;Database=Microsoft.eShopOnContainers.Services.OrderingDb;User Id=sa;Password=Pass@word
- EventBusConnection=${ESHOP_AZURE_SERVICE_BUS:-rabbitmq}
sql.data: sql.data:
environment: environment:
- SA_PASSWORD=Pass@word - SA_PASSWORD=Pass@word
- ACCEPT_EULA=Y - ACCEPT_EULA=Y
ports: ports:
- "5433:1433"
- "5433:1433"
nosql.data:
ports:
- "27017:27017"
webstatus:
environment:
- ASPNETCORE_ENVIRONMENT=Production
- ASPNETCORE_URLS=http://0.0.0.0:80
- CatalogUrl=http://catalog.api/hc
- OrderingUrl=http://ordering.api/hc
- BasketUrl=http://basket.api/hc
- IdentityUrl=http://identity.api/hc
- LocationsUrl=http://locations.api/hc
- MarketingUrl=http://marketing.api/hc
- mvc=http://webmvc/hc
- spa=http://webspa/hc
ports:
- "5107:80"
payment.api:
environment:
- ASPNETCORE_ENVIRONMENT=Production
- ASPNETCORE_URLS=http://0.0.0.0:5108
- EventBusConnection=${ESHOP_AZURE_SERVICE_BUS:-rabbitmq}
ports:
- "5108:80"
locations.api:
environment:
- ASPNETCORE_ENVIRONMENT=Production
- ASPNETCORE_URLS=http://0.0.0.0:80
- ConnectionString=${ESHOP_AZURE_COSMOSDB:-mongodb://nosql.data}
- Database=LocationsDb
- identityUrl=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5110.
- IdentityUrlExternal=http://${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}:5105
- EventBusConnection=${ESHOP_AZURE_SERVICE_BUS:-rabbitmq}
ports:
- "5109:80"

+ 30
- 3
docker-compose-windows.yml View File

@ -9,6 +9,7 @@ services:
depends_on: depends_on:
- basket.data - basket.data
- identity.api - identity.api
- rabbitmq
catalog.api: catalog.api:
image: eshop/catalog.api-win:${TAG:-latest} image: eshop/catalog.api-win:${TAG:-latest}
@ -17,6 +18,7 @@ services:
dockerfile: Dockerfile.nanowin dockerfile: Dockerfile.nanowin
depends_on: depends_on:
- sql.data - sql.data
- rabbitmq
identity.api: identity.api:
image: eshop/identity.api-win:${TAG:-latest} image: eshop/identity.api-win:${TAG:-latest}
@ -33,6 +35,7 @@ services:
dockerfile: Dockerfile.nanowin dockerfile: Dockerfile.nanowin
depends_on: depends_on:
- sql.data - sql.data
- rabbitmq
webspa: webspa:
image: eshop/webspa-win:${TAG:-latest} image: eshop/webspa-win:${TAG:-latest}
@ -53,12 +56,19 @@ services:
- ordering.api - ordering.api
- identity.api - identity.api
- basket.api - basket.api
- marketing.api
webstatus:
image: eshop/webstatus:${TAG:-latest}
build:
context: ./src/Web/WebStatus
dockerfile: Dockerfile.nanowin
locations.api: locations.api:
image: eshop/locations.api:${TAG:-latest} image: eshop/locations.api:${TAG:-latest}
build: build:
context: ./src/Services/Location/Locations.API context: ./src/Services/Location/Locations.API
dockerfile: Dockerfile
dockerfile: Dockerfile.nanowin
depends_on: depends_on:
- nosql.data - nosql.data
- rabbitmq - rabbitmq
@ -67,7 +77,7 @@ services:
image: eshop/marketing.api:${TAG:-latest} image: eshop/marketing.api:${TAG:-latest}
build: build:
context: ./src/Services/Marketing/Marketing.API context: ./src/Services/Marketing/Marketing.API
dockerfile: Dockerfile
dockerfile: Dockerfile.nanowin
depends_on: depends_on:
- sql.data - sql.data
- nosql.data - nosql.data
@ -95,7 +105,24 @@ services:
# dockerfile: Dockerfile.nanowin # dockerfile: Dockerfile.nanowin
ports: ports:
- "5672:5672" - "5672:5672"
graceperiodmanager:
image: eshop/graceperiodmanager:${TAG:-latest}
build:
context: ./src/Services/GracePeriod/GracePeriodManager
dockerfile: Dockerfile.nanowin
depends_on:
- sql.data
- rabbitmq
payment.api:
image: eshop/payment.api:${TAG:-latest}
build:
context: ./src/Services/Payment/Payment.API
dockerfile: Dockerfile.nanowin
depends_on:
- rabbitmq
networks: networks:
default: default:
external: external:


+ 7
- 3
docker-compose.ci.build.yml View File

@ -7,8 +7,12 @@ services:
- .:/src - .:/src
- ./cli-linux:/cli-linux - ./cli-linux:/cli-linux
working_dir: /src working_dir: /src
# DO NOT USE the sln file to compile because msbuild issue (https://github.com/Microsoft/msbuild/issues/2153)
# command: /bin/bash -c "pushd ./src/Web/WebSPA && npm rebuild node-sass && popd && dotnet restore ./eShopOnContainers-ServicesAndWebApps.sln && dotnet publish ./eShopOnContainers-ServicesAndWebApps.sln -c Release -o ./obj/Docker/publish"
# NOTE: Using build-bits-linux.sh triggers the same MSBUILD error :( (but at least, less frequently)
# 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 restore ./eShopOnContainers-ServicesAndWebApps.sln && 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" command: /bin/bash -c "pushd ./src/Web/WebSPA && npm rebuild node-sass && popd && pushd /cli-linux && ./build-bits-linux.sh /src"

+ 7
- 0
docker-compose.override.yml View File

@ -16,6 +16,7 @@ services:
- identityUrl=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5110. - identityUrl=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5110.
- IdentityUrlExternal=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5105 - IdentityUrlExternal=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5105
- EventBusConnection=${ESHOP_AZURE_SERVICE_BUS:-rabbitmq} - EventBusConnection=${ESHOP_AZURE_SERVICE_BUS:-rabbitmq}
- AzureServiceBusEnabled=False
ports: ports:
- "5103:80" - "5103:80"
@ -29,6 +30,7 @@ services:
- AzureStorageAccountName=${ESHOP_AZURE_STORAGE_CATALOG_NAME} - AzureStorageAccountName=${ESHOP_AZURE_STORAGE_CATALOG_NAME}
- AzureStorageAccountKey=${ESHOP_AZURE_STORAGE_CATALOG_KEY} - AzureStorageAccountKey=${ESHOP_AZURE_STORAGE_CATALOG_KEY}
- UseCustomizationData=True - UseCustomizationData=True
- AzureServiceBusEnabled=False
ports: ports:
- "5101:80" - "5101:80"
@ -57,6 +59,7 @@ services:
- IdentityUrlExternal=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5105 - IdentityUrlExternal=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5105
- EventBusConnection=${ESHOP_AZURE_SERVICE_BUS:-rabbitmq} - EventBusConnection=${ESHOP_AZURE_SERVICE_BUS:-rabbitmq}
- UseCustomizationData=True - UseCustomizationData=True
- AzureServiceBusEnabled=False
ports: ports:
- "5102:80" - "5102:80"
@ -74,6 +77,7 @@ services:
- PicBaseUrl=${ESHOP_AZURE_STORAGE_MARKETING:-http://localhost:5110/api/v1/campaigns/[0]/pic/} - PicBaseUrl=${ESHOP_AZURE_STORAGE_MARKETING:-http://localhost:5110/api/v1/campaigns/[0]/pic/}
- AzureStorageAccountName=${ESHOP_AZURE_STORAGE_MARKETING_NAME} - AzureStorageAccountName=${ESHOP_AZURE_STORAGE_MARKETING_NAME}
- AzureStorageAccountKey=${ESHOP_AZURE_STORAGE_MARKETING_KEY} - AzureStorageAccountKey=${ESHOP_AZURE_STORAGE_MARKETING_KEY}
- AzureServiceBusEnabled=False
ports: ports:
- "5110:80" - "5110:80"
@ -83,6 +87,7 @@ services:
- ASPNETCORE_URLS=http://0.0.0.0:80 - ASPNETCORE_URLS=http://0.0.0.0:80
- ConnectionString=Server=sql.data;Database=Microsoft.eShopOnContainers.Services.OrderingDb;User Id=sa;Password=Pass@word - ConnectionString=Server=sql.data;Database=Microsoft.eShopOnContainers.Services.OrderingDb;User Id=sa;Password=Pass@word
- EventBusConnection=${ESHOP_AZURE_SERVICE_BUS:-rabbitmq} - EventBusConnection=${ESHOP_AZURE_SERVICE_BUS:-rabbitmq}
- AzureServiceBusEnabled=False
webspa: webspa:
environment: environment:
@ -147,6 +152,7 @@ services:
- ASPNETCORE_ENVIRONMENT=Development - ASPNETCORE_ENVIRONMENT=Development
- ASPNETCORE_URLS=http://0.0.0.0:80 - ASPNETCORE_URLS=http://0.0.0.0:80
- EventBusConnection=${ESHOP_AZURE_SERVICE_BUS:-rabbitmq} - EventBusConnection=${ESHOP_AZURE_SERVICE_BUS:-rabbitmq}
- AzureServiceBusEnabled=False
ports: ports:
- "5108:80" - "5108:80"
@ -159,5 +165,6 @@ services:
- identityUrl=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5110. - identityUrl=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5110.
- IdentityUrlExternal=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5105 - IdentityUrlExternal=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5105
- EventBusConnection=${ESHOP_AZURE_SERVICE_BUS:-rabbitmq} - EventBusConnection=${ESHOP_AZURE_SERVICE_BUS:-rabbitmq}
- AzureServiceBusEnabled=False
ports: ports:
- "5109:80" - "5109:80"

+ 12
- 3
docker-compose.prod.yml View File

@ -19,6 +19,7 @@ services:
- ASPNETCORE_URLS=http://0.0.0.0:80 - ASPNETCORE_URLS=http://0.0.0.0:80
- ConnectionString=${ESHOP_AZURE_REDIS_BASKET_DB:-basket.data} - ConnectionString=${ESHOP_AZURE_REDIS_BASKET_DB:-basket.data}
- identityUrl=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5110. - identityUrl=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5110.
- IdentityUrlExternal=http://${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}:5105
- EventBusConnection=${ESHOP_AZURE_SERVICE_BUS:-rabbitmq} - EventBusConnection=${ESHOP_AZURE_SERVICE_BUS:-rabbitmq}
ports: ports:
- "5103:80" - "5103:80"
@ -26,7 +27,7 @@ services:
catalog.api: catalog.api:
environment: environment:
- ASPNETCORE_ENVIRONMENT=Production - ASPNETCORE_ENVIRONMENT=Production
ASPNETCORE_URLS=http://0.0.0.0:80
- ASPNETCORE_URLS=http://0.0.0.0:80
- ConnectionString=${ESHOP_AZURE_CATALOG_DB:-Server=sql.data;Database=Microsoft.eShopOnContainers.Services.CatalogDb;User Id=sa;Password=Pass@word} - ConnectionString=${ESHOP_AZURE_CATALOG_DB:-Server=sql.data;Database=Microsoft.eShopOnContainers.Services.CatalogDb;User Id=sa;Password=Pass@word}
- PicBaseUrl=${ESHOP_AZURE_STORAGE_CATALOG} #Local: You need to open your local dev-machine firewall at range 5100-5110. - PicBaseUrl=${ESHOP_AZURE_STORAGE_CATALOG} #Local: You need to open your local dev-machine firewall at range 5100-5110.
- EventBusConnection=${ESHOP_AZURE_SERVICE_BUS:-rabbitmq} - EventBusConnection=${ESHOP_AZURE_SERVICE_BUS:-rabbitmq}
@ -41,9 +42,13 @@ services:
- ASPNETCORE_ENVIRONMENT=Production - ASPNETCORE_ENVIRONMENT=Production
- ASPNETCORE_URLS=http://0.0.0.0:80 - ASPNETCORE_URLS=http://0.0.0.0:80
- SpaClient=http://${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}:5104 - SpaClient=http://${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}:5104
- ConnectionStrings__DefaultConnection=${ESHOP_AZURE_IDENTITY_DB:-Server=sql.data;Database=Microsoft.eShopOnContainers.Service.IdentityDb;User Id=sa;Password=Pass@word}
- MvcClient=http://${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}:5100 #Local: You need to open your host's firewall at range 5100-5110.
- XamarinCallback=http://${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}:5105/xamarincallback - XamarinCallback=http://${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}:5105/xamarincallback
- ConnectionStrings__DefaultConnection=${ESHOP_AZURE_IDENTITY_DB:-Server=sql.data;Database=Microsoft.eShopOnContainers.Service.IdentityDb;User Id=sa;Password=Pass@word}
- MvcClient=http://${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}:5100 #Local: You need to open your local dev-machine firewall at range 5100-5110.
- LocationApiClient=http://${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}:5109
- MarketingApiClient=http://${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}:5110
- BasketApiClient=http://${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}:5103
- OrderingApiClient=http://${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}:5102
- UseCustomizationData=True - UseCustomizationData=True
ports: ports:
- "5105:80" - "5105:80"
@ -54,6 +59,7 @@ services:
- ASPNETCORE_URLS=http://0.0.0.0:80 - 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} - ConnectionString=${ESHOP_AZURE_ORDERING_DB:-Server=sql.data;Database=Microsoft.eShopOnContainers.Services.OrderingDb;User Id=sa;Password=Pass@word}
- identityUrl=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5110. - identityUrl=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5110.
- IdentityUrlExternal=http://${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}:5105
- EventBusConnection=${ESHOP_AZURE_SERVICE_BUS:-rabbitmq} - EventBusConnection=${ESHOP_AZURE_SERVICE_BUS:-rabbitmq}
- UseCustomizationData=True - UseCustomizationData=True
ports: ports:
@ -68,6 +74,7 @@ services:
- MongoDatabase=MarketingDb - MongoDatabase=MarketingDb
- EventBusConnection=${ESHOP_AZURE_SERVICE_BUS:-rabbitmq} - EventBusConnection=${ESHOP_AZURE_SERVICE_BUS:-rabbitmq}
- identityUrl=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5110. - identityUrl=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5110.
- IdentityUrlExternal=http://${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}:5105
- CampaignDetailFunctionUri=${ESHOP_AZUREFUNC_CAMPAIGN_DETAILS_URI} - CampaignDetailFunctionUri=${ESHOP_AZUREFUNC_CAMPAIGN_DETAILS_URI}
- PicBaseUrl=${ESHOP_AZURE_STORAGE_MARKETING} - PicBaseUrl=${ESHOP_AZURE_STORAGE_MARKETING}
- AzureStorageAccountName=${ESHOP_AZURE_STORAGE_MARKETING_NAME} - AzureStorageAccountName=${ESHOP_AZURE_STORAGE_MARKETING_NAME}
@ -90,6 +97,7 @@ services:
- OrderingUrl=http://${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}:5102 - OrderingUrl=http://${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}:5102
- IdentityUrl=http://${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}:5105 #Local: You need to open your host's firewall at range 5100-5110. - IdentityUrl=http://${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}:5105 #Local: You need to open your host's firewall at range 5100-5110.
- BasketUrl=http://${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}:5103 - BasketUrl=http://${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}:5103
- MarketingUrl=http://${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}:5110
- 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.
@ -153,6 +161,7 @@ services:
- ConnectionString=${ESHOP_AZURE_COSMOSDB:-mongodb://nosql.data} - ConnectionString=${ESHOP_AZURE_COSMOSDB:-mongodb://nosql.data}
- Database=LocationsDb - Database=LocationsDb
- identityUrl=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5110. - identityUrl=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5110.
- IdentityUrlExternal=http://${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}:5105
- EventBusConnection=${ESHOP_AZURE_SERVICE_BUS:-rabbitmq} - EventBusConnection=${ESHOP_AZURE_SERVICE_BUS:-rabbitmq}
ports: ports:
- "5109:80" - "5109:80"

BIN
docs/Containerized Docker Application Lifecycle with Microsoft Platform and Tools (eBook).pdf View File


BIN
docs/Containerized-Docker-Application-Lifecycle-with-Microsoft-Platform-and-Tools-(eBook)_v1.1.pdf View File


BIN
docs/Enterprise-Application-Patterns-using-XamarinForms.pdf View File


+ 3
- 1
eShopOnContainers-MobileApps.sln 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.26228.9
VisualStudioVersion = 15.0.26430.16
MinimumVisualStudioVersion = 10.0.40219.1 MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{932D8224-11F6-4D07-B109-DA28AD288A63}" Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{932D8224-11F6-4D07-B109-DA28AD288A63}"
EndProject EndProject
@ -473,6 +473,8 @@ Global
{A7337243-33B8-463A-87AD-944B75EFD820}.AppStore|x86.Build.0 = Release|x86 {A7337243-33B8-463A-87AD-944B75EFD820}.AppStore|x86.Build.0 = Release|x86
{A7337243-33B8-463A-87AD-944B75EFD820}.AppStore|x86.Deploy.0 = Release|x86 {A7337243-33B8-463A-87AD-944B75EFD820}.AppStore|x86.Deploy.0 = Release|x86
{A7337243-33B8-463A-87AD-944B75EFD820}.Debug|Any CPU.ActiveCfg = Debug|x86 {A7337243-33B8-463A-87AD-944B75EFD820}.Debug|Any CPU.ActiveCfg = Debug|x86
{A7337243-33B8-463A-87AD-944B75EFD820}.Debug|Any CPU.Build.0 = Debug|x86
{A7337243-33B8-463A-87AD-944B75EFD820}.Debug|Any CPU.Deploy.0 = Debug|x86
{A7337243-33B8-463A-87AD-944B75EFD820}.Debug|ARM.ActiveCfg = Debug|ARM {A7337243-33B8-463A-87AD-944B75EFD820}.Debug|ARM.ActiveCfg = Debug|ARM
{A7337243-33B8-463A-87AD-944B75EFD820}.Debug|ARM.Build.0 = Debug|ARM {A7337243-33B8-463A-87AD-944B75EFD820}.Debug|ARM.Build.0 = Debug|ARM
{A7337243-33B8-463A-87AD-944B75EFD820}.Debug|ARM.Deploy.0 = Debug|ARM {A7337243-33B8-463A-87AD-944B75EFD820}.Debug|ARM.Deploy.0 = Debug|ARM


+ 424
- 1
eShopOnContainers.sln 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.26430.13
VisualStudioVersion = 15.0.26430.6
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}"
ProjectSection(ProjectDependencies) = postProject ProjectSection(ProjectDependencies) = postProject
@ -40,6 +40,9 @@ EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{A857AD10-40FF-4303-BEC2-FF1C58D5735E}" Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{A857AD10-40FF-4303-BEC2-FF1C58D5735E}"
EndProject EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Services", "Services", "{EF0337F2-ED00-4643-89FD-EE10863F1870}" Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Services", "Services", "{EF0337F2-ED00-4643-89FD-EE10863F1870}"
ProjectSection(SolutionItems) = preProject
test\Services\LoadTest\LoadTest.csproj = test\Services\LoadTest\LoadTest.csproj
EndProjectSection
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WebMVC", "src\Web\WebMVC\WebMVC.csproj", "{F0333D8E-0B27-42B7-B2C6-78F3657624E2}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WebMVC", "src\Web\WebMVC\WebMVC.csproj", "{F0333D8E-0B27-42B7-B2C6-78F3657624E2}"
EndProject EndProject
@ -105,6 +108,30 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WebStatus", "src\Web\WebSta
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.HealthChecks.SqlServer", "src\BuildingBlocks\HealthChecks\src\Microsoft.Extensions.HealthChecks.SqlServer\Microsoft.Extensions.HealthChecks.SqlServer.csproj", "{6CCC4F1B-602D-4FAD-91A7-002CC86C7612}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.HealthChecks.SqlServer", "src\BuildingBlocks\HealthChecks\src\Microsoft.Extensions.HealthChecks.SqlServer\Microsoft.Extensions.HealthChecks.SqlServer.csproj", "{6CCC4F1B-602D-4FAD-91A7-002CC86C7612}"
EndProject EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "DataProtection", "DataProtection", "{CC0FD121-5E19-44B6-B23F-0FE3D1B821D3}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DataProtection", "src\BuildingBlocks\DataProtection\DataProtection\DataProtection.csproj", "{237CA273-8555-4944-B87D-5B65AB3A788C}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Location", "Location", "{0CF40BE0-A463-4E4F-A29C-C7427D04DC4F}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Locations.API", "src\Services\Location\Locations.API\Locations.API.csproj", "{B30E0E82-9EA4-49D6-BA0D-BA8E5FA48800}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Marketing", "Marketing", "{72704C77-5C90-4705-B2A4-7A6E3B02FF08}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Marketing.API", "src\Services\Marketing\Marketing.API\Marketing.API.csproj", "{5E319B6A-9F04-4113-ABF9-AB8CD1F7A0B5}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EventBusServiceBus", "src\BuildingBlocks\EventBus\EventBusServiceBus\EventBusServiceBus.csproj", "{26906157-98E3-4DF8-80F6-866B9686887C}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EventBus.Tests", "src\BuildingBlocks\EventBus\EventBus.Tests\EventBus.Tests.csproj", "{8AE2AAA3-4507-4BEE-9250-4D16F87015B4}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.HealthChecks.AzureStorage", "src\BuildingBlocks\HealthChecks\src\Microsoft.Extensions.HealthChecks.AzureStorage\Microsoft.Extensions.HealthChecks.AzureStorage.csproj", "{1CFFC16D-0D4A-47B3-9316-2A04ABD4A7AD}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GracePeriodManager", "src\Services\GracePeriod\GracePeriodManager\GracePeriodManager.csproj", "{6C6A69FE-A484-4E75-AFEC-827EA354AF46}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Payment", "Payment", "{D5D3841D-F282-4E60-B9CB-267A1BF2D893}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Payment.API", "src\Services\Payment\Payment.API\Payment.API.csproj", "{2A795FEA-2EB7-45F5-9B30-35E0810CB238}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Ad-Hoc|Any CPU = Ad-Hoc|Any CPU Ad-Hoc|Any CPU = Ad-Hoc|Any CPU
@ -1466,6 +1493,390 @@ Global
{6CCC4F1B-602D-4FAD-91A7-002CC86C7612}.Release|x64.Build.0 = Release|Any CPU {6CCC4F1B-602D-4FAD-91A7-002CC86C7612}.Release|x64.Build.0 = Release|Any CPU
{6CCC4F1B-602D-4FAD-91A7-002CC86C7612}.Release|x86.ActiveCfg = Release|Any CPU {6CCC4F1B-602D-4FAD-91A7-002CC86C7612}.Release|x86.ActiveCfg = Release|Any CPU
{6CCC4F1B-602D-4FAD-91A7-002CC86C7612}.Release|x86.Build.0 = Release|Any CPU {6CCC4F1B-602D-4FAD-91A7-002CC86C7612}.Release|x86.Build.0 = Release|Any CPU
{237CA273-8555-4944-B87D-5B65AB3A788C}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
{237CA273-8555-4944-B87D-5B65AB3A788C}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
{237CA273-8555-4944-B87D-5B65AB3A788C}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU
{237CA273-8555-4944-B87D-5B65AB3A788C}.Ad-Hoc|ARM.Build.0 = Debug|Any CPU
{237CA273-8555-4944-B87D-5B65AB3A788C}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
{237CA273-8555-4944-B87D-5B65AB3A788C}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
{237CA273-8555-4944-B87D-5B65AB3A788C}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{237CA273-8555-4944-B87D-5B65AB3A788C}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
{237CA273-8555-4944-B87D-5B65AB3A788C}.Ad-Hoc|x64.ActiveCfg = Debug|Any CPU
{237CA273-8555-4944-B87D-5B65AB3A788C}.Ad-Hoc|x64.Build.0 = Debug|Any CPU
{237CA273-8555-4944-B87D-5B65AB3A788C}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU
{237CA273-8555-4944-B87D-5B65AB3A788C}.Ad-Hoc|x86.Build.0 = Debug|Any CPU
{237CA273-8555-4944-B87D-5B65AB3A788C}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
{237CA273-8555-4944-B87D-5B65AB3A788C}.AppStore|Any CPU.Build.0 = Debug|Any CPU
{237CA273-8555-4944-B87D-5B65AB3A788C}.AppStore|ARM.ActiveCfg = Debug|Any CPU
{237CA273-8555-4944-B87D-5B65AB3A788C}.AppStore|ARM.Build.0 = Debug|Any CPU
{237CA273-8555-4944-B87D-5B65AB3A788C}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
{237CA273-8555-4944-B87D-5B65AB3A788C}.AppStore|iPhone.Build.0 = Debug|Any CPU
{237CA273-8555-4944-B87D-5B65AB3A788C}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{237CA273-8555-4944-B87D-5B65AB3A788C}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
{237CA273-8555-4944-B87D-5B65AB3A788C}.AppStore|x64.ActiveCfg = Debug|Any CPU
{237CA273-8555-4944-B87D-5B65AB3A788C}.AppStore|x64.Build.0 = Debug|Any CPU
{237CA273-8555-4944-B87D-5B65AB3A788C}.AppStore|x86.ActiveCfg = Debug|Any CPU
{237CA273-8555-4944-B87D-5B65AB3A788C}.AppStore|x86.Build.0 = Debug|Any CPU
{237CA273-8555-4944-B87D-5B65AB3A788C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{237CA273-8555-4944-B87D-5B65AB3A788C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{237CA273-8555-4944-B87D-5B65AB3A788C}.Debug|ARM.ActiveCfg = Debug|Any CPU
{237CA273-8555-4944-B87D-5B65AB3A788C}.Debug|ARM.Build.0 = Debug|Any CPU
{237CA273-8555-4944-B87D-5B65AB3A788C}.Debug|iPhone.ActiveCfg = Debug|Any CPU
{237CA273-8555-4944-B87D-5B65AB3A788C}.Debug|iPhone.Build.0 = Debug|Any CPU
{237CA273-8555-4944-B87D-5B65AB3A788C}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{237CA273-8555-4944-B87D-5B65AB3A788C}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
{237CA273-8555-4944-B87D-5B65AB3A788C}.Debug|x64.ActiveCfg = Debug|Any CPU
{237CA273-8555-4944-B87D-5B65AB3A788C}.Debug|x64.Build.0 = Debug|Any CPU
{237CA273-8555-4944-B87D-5B65AB3A788C}.Debug|x86.ActiveCfg = Debug|Any CPU
{237CA273-8555-4944-B87D-5B65AB3A788C}.Debug|x86.Build.0 = Debug|Any CPU
{237CA273-8555-4944-B87D-5B65AB3A788C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{237CA273-8555-4944-B87D-5B65AB3A788C}.Release|Any CPU.Build.0 = Release|Any CPU
{237CA273-8555-4944-B87D-5B65AB3A788C}.Release|ARM.ActiveCfg = Release|Any CPU
{237CA273-8555-4944-B87D-5B65AB3A788C}.Release|ARM.Build.0 = Release|Any CPU
{237CA273-8555-4944-B87D-5B65AB3A788C}.Release|iPhone.ActiveCfg = Release|Any CPU
{237CA273-8555-4944-B87D-5B65AB3A788C}.Release|iPhone.Build.0 = Release|Any CPU
{237CA273-8555-4944-B87D-5B65AB3A788C}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{237CA273-8555-4944-B87D-5B65AB3A788C}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{237CA273-8555-4944-B87D-5B65AB3A788C}.Release|x64.ActiveCfg = Release|Any CPU
{237CA273-8555-4944-B87D-5B65AB3A788C}.Release|x64.Build.0 = Release|Any CPU
{237CA273-8555-4944-B87D-5B65AB3A788C}.Release|x86.ActiveCfg = Release|Any CPU
{237CA273-8555-4944-B87D-5B65AB3A788C}.Release|x86.Build.0 = Release|Any CPU
{B30E0E82-9EA4-49D6-BA0D-BA8E5FA48800}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
{B30E0E82-9EA4-49D6-BA0D-BA8E5FA48800}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
{B30E0E82-9EA4-49D6-BA0D-BA8E5FA48800}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU
{B30E0E82-9EA4-49D6-BA0D-BA8E5FA48800}.Ad-Hoc|ARM.Build.0 = Debug|Any CPU
{B30E0E82-9EA4-49D6-BA0D-BA8E5FA48800}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
{B30E0E82-9EA4-49D6-BA0D-BA8E5FA48800}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
{B30E0E82-9EA4-49D6-BA0D-BA8E5FA48800}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{B30E0E82-9EA4-49D6-BA0D-BA8E5FA48800}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
{B30E0E82-9EA4-49D6-BA0D-BA8E5FA48800}.Ad-Hoc|x64.ActiveCfg = Debug|Any CPU
{B30E0E82-9EA4-49D6-BA0D-BA8E5FA48800}.Ad-Hoc|x64.Build.0 = Debug|Any CPU
{B30E0E82-9EA4-49D6-BA0D-BA8E5FA48800}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU
{B30E0E82-9EA4-49D6-BA0D-BA8E5FA48800}.Ad-Hoc|x86.Build.0 = Debug|Any CPU
{B30E0E82-9EA4-49D6-BA0D-BA8E5FA48800}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
{B30E0E82-9EA4-49D6-BA0D-BA8E5FA48800}.AppStore|Any CPU.Build.0 = Debug|Any CPU
{B30E0E82-9EA4-49D6-BA0D-BA8E5FA48800}.AppStore|ARM.ActiveCfg = Debug|Any CPU
{B30E0E82-9EA4-49D6-BA0D-BA8E5FA48800}.AppStore|ARM.Build.0 = Debug|Any CPU
{B30E0E82-9EA4-49D6-BA0D-BA8E5FA48800}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
{B30E0E82-9EA4-49D6-BA0D-BA8E5FA48800}.AppStore|iPhone.Build.0 = Debug|Any CPU
{B30E0E82-9EA4-49D6-BA0D-BA8E5FA48800}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{B30E0E82-9EA4-49D6-BA0D-BA8E5FA48800}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
{B30E0E82-9EA4-49D6-BA0D-BA8E5FA48800}.AppStore|x64.ActiveCfg = Debug|Any CPU
{B30E0E82-9EA4-49D6-BA0D-BA8E5FA48800}.AppStore|x64.Build.0 = Debug|Any CPU
{B30E0E82-9EA4-49D6-BA0D-BA8E5FA48800}.AppStore|x86.ActiveCfg = Debug|Any CPU
{B30E0E82-9EA4-49D6-BA0D-BA8E5FA48800}.AppStore|x86.Build.0 = Debug|Any CPU
{B30E0E82-9EA4-49D6-BA0D-BA8E5FA48800}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B30E0E82-9EA4-49D6-BA0D-BA8E5FA48800}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B30E0E82-9EA4-49D6-BA0D-BA8E5FA48800}.Debug|ARM.ActiveCfg = Debug|Any CPU
{B30E0E82-9EA4-49D6-BA0D-BA8E5FA48800}.Debug|ARM.Build.0 = Debug|Any CPU
{B30E0E82-9EA4-49D6-BA0D-BA8E5FA48800}.Debug|iPhone.ActiveCfg = Debug|Any CPU
{B30E0E82-9EA4-49D6-BA0D-BA8E5FA48800}.Debug|iPhone.Build.0 = Debug|Any CPU
{B30E0E82-9EA4-49D6-BA0D-BA8E5FA48800}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{B30E0E82-9EA4-49D6-BA0D-BA8E5FA48800}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
{B30E0E82-9EA4-49D6-BA0D-BA8E5FA48800}.Debug|x64.ActiveCfg = Debug|Any CPU
{B30E0E82-9EA4-49D6-BA0D-BA8E5FA48800}.Debug|x64.Build.0 = Debug|Any CPU
{B30E0E82-9EA4-49D6-BA0D-BA8E5FA48800}.Debug|x86.ActiveCfg = Debug|Any CPU
{B30E0E82-9EA4-49D6-BA0D-BA8E5FA48800}.Debug|x86.Build.0 = Debug|Any CPU
{B30E0E82-9EA4-49D6-BA0D-BA8E5FA48800}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B30E0E82-9EA4-49D6-BA0D-BA8E5FA48800}.Release|Any CPU.Build.0 = Release|Any CPU
{B30E0E82-9EA4-49D6-BA0D-BA8E5FA48800}.Release|ARM.ActiveCfg = Release|Any CPU
{B30E0E82-9EA4-49D6-BA0D-BA8E5FA48800}.Release|ARM.Build.0 = Release|Any CPU
{B30E0E82-9EA4-49D6-BA0D-BA8E5FA48800}.Release|iPhone.ActiveCfg = Release|Any CPU
{B30E0E82-9EA4-49D6-BA0D-BA8E5FA48800}.Release|iPhone.Build.0 = Release|Any CPU
{B30E0E82-9EA4-49D6-BA0D-BA8E5FA48800}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{B30E0E82-9EA4-49D6-BA0D-BA8E5FA48800}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{B30E0E82-9EA4-49D6-BA0D-BA8E5FA48800}.Release|x64.ActiveCfg = Release|Any CPU
{B30E0E82-9EA4-49D6-BA0D-BA8E5FA48800}.Release|x64.Build.0 = Release|Any CPU
{B30E0E82-9EA4-49D6-BA0D-BA8E5FA48800}.Release|x86.ActiveCfg = Release|Any CPU
{B30E0E82-9EA4-49D6-BA0D-BA8E5FA48800}.Release|x86.Build.0 = Release|Any CPU
{5E319B6A-9F04-4113-ABF9-AB8CD1F7A0B5}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
{5E319B6A-9F04-4113-ABF9-AB8CD1F7A0B5}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
{5E319B6A-9F04-4113-ABF9-AB8CD1F7A0B5}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU
{5E319B6A-9F04-4113-ABF9-AB8CD1F7A0B5}.Ad-Hoc|ARM.Build.0 = Debug|Any CPU
{5E319B6A-9F04-4113-ABF9-AB8CD1F7A0B5}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
{5E319B6A-9F04-4113-ABF9-AB8CD1F7A0B5}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
{5E319B6A-9F04-4113-ABF9-AB8CD1F7A0B5}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{5E319B6A-9F04-4113-ABF9-AB8CD1F7A0B5}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
{5E319B6A-9F04-4113-ABF9-AB8CD1F7A0B5}.Ad-Hoc|x64.ActiveCfg = Debug|Any CPU
{5E319B6A-9F04-4113-ABF9-AB8CD1F7A0B5}.Ad-Hoc|x64.Build.0 = Debug|Any CPU
{5E319B6A-9F04-4113-ABF9-AB8CD1F7A0B5}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU
{5E319B6A-9F04-4113-ABF9-AB8CD1F7A0B5}.Ad-Hoc|x86.Build.0 = Debug|Any CPU
{5E319B6A-9F04-4113-ABF9-AB8CD1F7A0B5}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
{5E319B6A-9F04-4113-ABF9-AB8CD1F7A0B5}.AppStore|Any CPU.Build.0 = Debug|Any CPU
{5E319B6A-9F04-4113-ABF9-AB8CD1F7A0B5}.AppStore|ARM.ActiveCfg = Debug|Any CPU
{5E319B6A-9F04-4113-ABF9-AB8CD1F7A0B5}.AppStore|ARM.Build.0 = Debug|Any CPU
{5E319B6A-9F04-4113-ABF9-AB8CD1F7A0B5}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
{5E319B6A-9F04-4113-ABF9-AB8CD1F7A0B5}.AppStore|iPhone.Build.0 = Debug|Any CPU
{5E319B6A-9F04-4113-ABF9-AB8CD1F7A0B5}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{5E319B6A-9F04-4113-ABF9-AB8CD1F7A0B5}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
{5E319B6A-9F04-4113-ABF9-AB8CD1F7A0B5}.AppStore|x64.ActiveCfg = Debug|Any CPU
{5E319B6A-9F04-4113-ABF9-AB8CD1F7A0B5}.AppStore|x64.Build.0 = Debug|Any CPU
{5E319B6A-9F04-4113-ABF9-AB8CD1F7A0B5}.AppStore|x86.ActiveCfg = Debug|Any CPU
{5E319B6A-9F04-4113-ABF9-AB8CD1F7A0B5}.AppStore|x86.Build.0 = Debug|Any CPU
{5E319B6A-9F04-4113-ABF9-AB8CD1F7A0B5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5E319B6A-9F04-4113-ABF9-AB8CD1F7A0B5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5E319B6A-9F04-4113-ABF9-AB8CD1F7A0B5}.Debug|ARM.ActiveCfg = Debug|Any CPU
{5E319B6A-9F04-4113-ABF9-AB8CD1F7A0B5}.Debug|ARM.Build.0 = Debug|Any CPU
{5E319B6A-9F04-4113-ABF9-AB8CD1F7A0B5}.Debug|iPhone.ActiveCfg = Debug|Any CPU
{5E319B6A-9F04-4113-ABF9-AB8CD1F7A0B5}.Debug|iPhone.Build.0 = Debug|Any CPU
{5E319B6A-9F04-4113-ABF9-AB8CD1F7A0B5}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{5E319B6A-9F04-4113-ABF9-AB8CD1F7A0B5}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
{5E319B6A-9F04-4113-ABF9-AB8CD1F7A0B5}.Debug|x64.ActiveCfg = Debug|Any CPU
{5E319B6A-9F04-4113-ABF9-AB8CD1F7A0B5}.Debug|x64.Build.0 = Debug|Any CPU
{5E319B6A-9F04-4113-ABF9-AB8CD1F7A0B5}.Debug|x86.ActiveCfg = Debug|Any CPU
{5E319B6A-9F04-4113-ABF9-AB8CD1F7A0B5}.Debug|x86.Build.0 = Debug|Any CPU
{5E319B6A-9F04-4113-ABF9-AB8CD1F7A0B5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5E319B6A-9F04-4113-ABF9-AB8CD1F7A0B5}.Release|Any CPU.Build.0 = Release|Any CPU
{5E319B6A-9F04-4113-ABF9-AB8CD1F7A0B5}.Release|ARM.ActiveCfg = Release|Any CPU
{5E319B6A-9F04-4113-ABF9-AB8CD1F7A0B5}.Release|ARM.Build.0 = Release|Any CPU
{5E319B6A-9F04-4113-ABF9-AB8CD1F7A0B5}.Release|iPhone.ActiveCfg = Release|Any CPU
{5E319B6A-9F04-4113-ABF9-AB8CD1F7A0B5}.Release|iPhone.Build.0 = Release|Any CPU
{5E319B6A-9F04-4113-ABF9-AB8CD1F7A0B5}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{5E319B6A-9F04-4113-ABF9-AB8CD1F7A0B5}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{5E319B6A-9F04-4113-ABF9-AB8CD1F7A0B5}.Release|x64.ActiveCfg = Release|Any CPU
{5E319B6A-9F04-4113-ABF9-AB8CD1F7A0B5}.Release|x64.Build.0 = Release|Any CPU
{5E319B6A-9F04-4113-ABF9-AB8CD1F7A0B5}.Release|x86.ActiveCfg = Release|Any CPU
{5E319B6A-9F04-4113-ABF9-AB8CD1F7A0B5}.Release|x86.Build.0 = Release|Any CPU
{26906157-98E3-4DF8-80F6-866B9686887C}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
{26906157-98E3-4DF8-80F6-866B9686887C}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
{26906157-98E3-4DF8-80F6-866B9686887C}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU
{26906157-98E3-4DF8-80F6-866B9686887C}.Ad-Hoc|ARM.Build.0 = Debug|Any CPU
{26906157-98E3-4DF8-80F6-866B9686887C}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
{26906157-98E3-4DF8-80F6-866B9686887C}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
{26906157-98E3-4DF8-80F6-866B9686887C}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{26906157-98E3-4DF8-80F6-866B9686887C}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
{26906157-98E3-4DF8-80F6-866B9686887C}.Ad-Hoc|x64.ActiveCfg = Debug|Any CPU
{26906157-98E3-4DF8-80F6-866B9686887C}.Ad-Hoc|x64.Build.0 = Debug|Any CPU
{26906157-98E3-4DF8-80F6-866B9686887C}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU
{26906157-98E3-4DF8-80F6-866B9686887C}.Ad-Hoc|x86.Build.0 = Debug|Any CPU
{26906157-98E3-4DF8-80F6-866B9686887C}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
{26906157-98E3-4DF8-80F6-866B9686887C}.AppStore|Any CPU.Build.0 = Debug|Any CPU
{26906157-98E3-4DF8-80F6-866B9686887C}.AppStore|ARM.ActiveCfg = Debug|Any CPU
{26906157-98E3-4DF8-80F6-866B9686887C}.AppStore|ARM.Build.0 = Debug|Any CPU
{26906157-98E3-4DF8-80F6-866B9686887C}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
{26906157-98E3-4DF8-80F6-866B9686887C}.AppStore|iPhone.Build.0 = Debug|Any CPU
{26906157-98E3-4DF8-80F6-866B9686887C}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{26906157-98E3-4DF8-80F6-866B9686887C}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
{26906157-98E3-4DF8-80F6-866B9686887C}.AppStore|x64.ActiveCfg = Debug|Any CPU
{26906157-98E3-4DF8-80F6-866B9686887C}.AppStore|x64.Build.0 = Debug|Any CPU
{26906157-98E3-4DF8-80F6-866B9686887C}.AppStore|x86.ActiveCfg = Debug|Any CPU
{26906157-98E3-4DF8-80F6-866B9686887C}.AppStore|x86.Build.0 = Debug|Any CPU
{26906157-98E3-4DF8-80F6-866B9686887C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{26906157-98E3-4DF8-80F6-866B9686887C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{26906157-98E3-4DF8-80F6-866B9686887C}.Debug|ARM.ActiveCfg = Debug|Any CPU
{26906157-98E3-4DF8-80F6-866B9686887C}.Debug|ARM.Build.0 = Debug|Any CPU
{26906157-98E3-4DF8-80F6-866B9686887C}.Debug|iPhone.ActiveCfg = Debug|Any CPU
{26906157-98E3-4DF8-80F6-866B9686887C}.Debug|iPhone.Build.0 = Debug|Any CPU
{26906157-98E3-4DF8-80F6-866B9686887C}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{26906157-98E3-4DF8-80F6-866B9686887C}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
{26906157-98E3-4DF8-80F6-866B9686887C}.Debug|x64.ActiveCfg = Debug|Any CPU
{26906157-98E3-4DF8-80F6-866B9686887C}.Debug|x64.Build.0 = Debug|Any CPU
{26906157-98E3-4DF8-80F6-866B9686887C}.Debug|x86.ActiveCfg = Debug|Any CPU
{26906157-98E3-4DF8-80F6-866B9686887C}.Debug|x86.Build.0 = Debug|Any CPU
{26906157-98E3-4DF8-80F6-866B9686887C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{26906157-98E3-4DF8-80F6-866B9686887C}.Release|Any CPU.Build.0 = Release|Any CPU
{26906157-98E3-4DF8-80F6-866B9686887C}.Release|ARM.ActiveCfg = Release|Any CPU
{26906157-98E3-4DF8-80F6-866B9686887C}.Release|ARM.Build.0 = Release|Any CPU
{26906157-98E3-4DF8-80F6-866B9686887C}.Release|iPhone.ActiveCfg = Release|Any CPU
{26906157-98E3-4DF8-80F6-866B9686887C}.Release|iPhone.Build.0 = Release|Any CPU
{26906157-98E3-4DF8-80F6-866B9686887C}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{26906157-98E3-4DF8-80F6-866B9686887C}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{26906157-98E3-4DF8-80F6-866B9686887C}.Release|x64.ActiveCfg = Release|Any CPU
{26906157-98E3-4DF8-80F6-866B9686887C}.Release|x64.Build.0 = Release|Any CPU
{26906157-98E3-4DF8-80F6-866B9686887C}.Release|x86.ActiveCfg = Release|Any CPU
{26906157-98E3-4DF8-80F6-866B9686887C}.Release|x86.Build.0 = Release|Any CPU
{8AE2AAA3-4507-4BEE-9250-4D16F87015B4}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
{8AE2AAA3-4507-4BEE-9250-4D16F87015B4}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
{8AE2AAA3-4507-4BEE-9250-4D16F87015B4}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU
{8AE2AAA3-4507-4BEE-9250-4D16F87015B4}.Ad-Hoc|ARM.Build.0 = Debug|Any CPU
{8AE2AAA3-4507-4BEE-9250-4D16F87015B4}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
{8AE2AAA3-4507-4BEE-9250-4D16F87015B4}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
{8AE2AAA3-4507-4BEE-9250-4D16F87015B4}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{8AE2AAA3-4507-4BEE-9250-4D16F87015B4}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
{8AE2AAA3-4507-4BEE-9250-4D16F87015B4}.Ad-Hoc|x64.ActiveCfg = Debug|Any CPU
{8AE2AAA3-4507-4BEE-9250-4D16F87015B4}.Ad-Hoc|x64.Build.0 = Debug|Any CPU
{8AE2AAA3-4507-4BEE-9250-4D16F87015B4}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU
{8AE2AAA3-4507-4BEE-9250-4D16F87015B4}.Ad-Hoc|x86.Build.0 = Debug|Any CPU
{8AE2AAA3-4507-4BEE-9250-4D16F87015B4}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
{8AE2AAA3-4507-4BEE-9250-4D16F87015B4}.AppStore|Any CPU.Build.0 = Debug|Any CPU
{8AE2AAA3-4507-4BEE-9250-4D16F87015B4}.AppStore|ARM.ActiveCfg = Debug|Any CPU
{8AE2AAA3-4507-4BEE-9250-4D16F87015B4}.AppStore|ARM.Build.0 = Debug|Any CPU
{8AE2AAA3-4507-4BEE-9250-4D16F87015B4}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
{8AE2AAA3-4507-4BEE-9250-4D16F87015B4}.AppStore|iPhone.Build.0 = Debug|Any CPU
{8AE2AAA3-4507-4BEE-9250-4D16F87015B4}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{8AE2AAA3-4507-4BEE-9250-4D16F87015B4}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
{8AE2AAA3-4507-4BEE-9250-4D16F87015B4}.AppStore|x64.ActiveCfg = Debug|Any CPU
{8AE2AAA3-4507-4BEE-9250-4D16F87015B4}.AppStore|x64.Build.0 = Debug|Any CPU
{8AE2AAA3-4507-4BEE-9250-4D16F87015B4}.AppStore|x86.ActiveCfg = Debug|Any CPU
{8AE2AAA3-4507-4BEE-9250-4D16F87015B4}.AppStore|x86.Build.0 = Debug|Any CPU
{8AE2AAA3-4507-4BEE-9250-4D16F87015B4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8AE2AAA3-4507-4BEE-9250-4D16F87015B4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8AE2AAA3-4507-4BEE-9250-4D16F87015B4}.Debug|ARM.ActiveCfg = Debug|Any CPU
{8AE2AAA3-4507-4BEE-9250-4D16F87015B4}.Debug|ARM.Build.0 = Debug|Any CPU
{8AE2AAA3-4507-4BEE-9250-4D16F87015B4}.Debug|iPhone.ActiveCfg = Debug|Any CPU
{8AE2AAA3-4507-4BEE-9250-4D16F87015B4}.Debug|iPhone.Build.0 = Debug|Any CPU
{8AE2AAA3-4507-4BEE-9250-4D16F87015B4}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{8AE2AAA3-4507-4BEE-9250-4D16F87015B4}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
{8AE2AAA3-4507-4BEE-9250-4D16F87015B4}.Debug|x64.ActiveCfg = Debug|Any CPU
{8AE2AAA3-4507-4BEE-9250-4D16F87015B4}.Debug|x64.Build.0 = Debug|Any CPU
{8AE2AAA3-4507-4BEE-9250-4D16F87015B4}.Debug|x86.ActiveCfg = Debug|Any CPU
{8AE2AAA3-4507-4BEE-9250-4D16F87015B4}.Debug|x86.Build.0 = Debug|Any CPU
{8AE2AAA3-4507-4BEE-9250-4D16F87015B4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8AE2AAA3-4507-4BEE-9250-4D16F87015B4}.Release|Any CPU.Build.0 = Release|Any CPU
{8AE2AAA3-4507-4BEE-9250-4D16F87015B4}.Release|ARM.ActiveCfg = Release|Any CPU
{8AE2AAA3-4507-4BEE-9250-4D16F87015B4}.Release|ARM.Build.0 = Release|Any CPU
{8AE2AAA3-4507-4BEE-9250-4D16F87015B4}.Release|iPhone.ActiveCfg = Release|Any CPU
{8AE2AAA3-4507-4BEE-9250-4D16F87015B4}.Release|iPhone.Build.0 = Release|Any CPU
{8AE2AAA3-4507-4BEE-9250-4D16F87015B4}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{8AE2AAA3-4507-4BEE-9250-4D16F87015B4}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{8AE2AAA3-4507-4BEE-9250-4D16F87015B4}.Release|x64.ActiveCfg = Release|Any CPU
{8AE2AAA3-4507-4BEE-9250-4D16F87015B4}.Release|x64.Build.0 = Release|Any CPU
{8AE2AAA3-4507-4BEE-9250-4D16F87015B4}.Release|x86.ActiveCfg = Release|Any CPU
{8AE2AAA3-4507-4BEE-9250-4D16F87015B4}.Release|x86.Build.0 = Release|Any CPU
{1CFFC16D-0D4A-47B3-9316-2A04ABD4A7AD}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
{1CFFC16D-0D4A-47B3-9316-2A04ABD4A7AD}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
{1CFFC16D-0D4A-47B3-9316-2A04ABD4A7AD}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU
{1CFFC16D-0D4A-47B3-9316-2A04ABD4A7AD}.Ad-Hoc|ARM.Build.0 = Debug|Any CPU
{1CFFC16D-0D4A-47B3-9316-2A04ABD4A7AD}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
{1CFFC16D-0D4A-47B3-9316-2A04ABD4A7AD}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
{1CFFC16D-0D4A-47B3-9316-2A04ABD4A7AD}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{1CFFC16D-0D4A-47B3-9316-2A04ABD4A7AD}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
{1CFFC16D-0D4A-47B3-9316-2A04ABD4A7AD}.Ad-Hoc|x64.ActiveCfg = Debug|Any CPU
{1CFFC16D-0D4A-47B3-9316-2A04ABD4A7AD}.Ad-Hoc|x64.Build.0 = Debug|Any CPU
{1CFFC16D-0D4A-47B3-9316-2A04ABD4A7AD}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU
{1CFFC16D-0D4A-47B3-9316-2A04ABD4A7AD}.Ad-Hoc|x86.Build.0 = Debug|Any CPU
{1CFFC16D-0D4A-47B3-9316-2A04ABD4A7AD}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
{1CFFC16D-0D4A-47B3-9316-2A04ABD4A7AD}.AppStore|Any CPU.Build.0 = Debug|Any CPU
{1CFFC16D-0D4A-47B3-9316-2A04ABD4A7AD}.AppStore|ARM.ActiveCfg = Debug|Any CPU
{1CFFC16D-0D4A-47B3-9316-2A04ABD4A7AD}.AppStore|ARM.Build.0 = Debug|Any CPU
{1CFFC16D-0D4A-47B3-9316-2A04ABD4A7AD}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
{1CFFC16D-0D4A-47B3-9316-2A04ABD4A7AD}.AppStore|iPhone.Build.0 = Debug|Any CPU
{1CFFC16D-0D4A-47B3-9316-2A04ABD4A7AD}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{1CFFC16D-0D4A-47B3-9316-2A04ABD4A7AD}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
{1CFFC16D-0D4A-47B3-9316-2A04ABD4A7AD}.AppStore|x64.ActiveCfg = Debug|Any CPU
{1CFFC16D-0D4A-47B3-9316-2A04ABD4A7AD}.AppStore|x64.Build.0 = Debug|Any CPU
{1CFFC16D-0D4A-47B3-9316-2A04ABD4A7AD}.AppStore|x86.ActiveCfg = Debug|Any CPU
{1CFFC16D-0D4A-47B3-9316-2A04ABD4A7AD}.AppStore|x86.Build.0 = Debug|Any CPU
{1CFFC16D-0D4A-47B3-9316-2A04ABD4A7AD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1CFFC16D-0D4A-47B3-9316-2A04ABD4A7AD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1CFFC16D-0D4A-47B3-9316-2A04ABD4A7AD}.Debug|ARM.ActiveCfg = Debug|Any CPU
{1CFFC16D-0D4A-47B3-9316-2A04ABD4A7AD}.Debug|ARM.Build.0 = Debug|Any CPU
{1CFFC16D-0D4A-47B3-9316-2A04ABD4A7AD}.Debug|iPhone.ActiveCfg = Debug|Any CPU
{1CFFC16D-0D4A-47B3-9316-2A04ABD4A7AD}.Debug|iPhone.Build.0 = Debug|Any CPU
{1CFFC16D-0D4A-47B3-9316-2A04ABD4A7AD}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{1CFFC16D-0D4A-47B3-9316-2A04ABD4A7AD}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
{1CFFC16D-0D4A-47B3-9316-2A04ABD4A7AD}.Debug|x64.ActiveCfg = Debug|Any CPU
{1CFFC16D-0D4A-47B3-9316-2A04ABD4A7AD}.Debug|x64.Build.0 = Debug|Any CPU
{1CFFC16D-0D4A-47B3-9316-2A04ABD4A7AD}.Debug|x86.ActiveCfg = Debug|Any CPU
{1CFFC16D-0D4A-47B3-9316-2A04ABD4A7AD}.Debug|x86.Build.0 = Debug|Any CPU
{1CFFC16D-0D4A-47B3-9316-2A04ABD4A7AD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1CFFC16D-0D4A-47B3-9316-2A04ABD4A7AD}.Release|Any CPU.Build.0 = Release|Any CPU
{1CFFC16D-0D4A-47B3-9316-2A04ABD4A7AD}.Release|ARM.ActiveCfg = Release|Any CPU
{1CFFC16D-0D4A-47B3-9316-2A04ABD4A7AD}.Release|ARM.Build.0 = Release|Any CPU
{1CFFC16D-0D4A-47B3-9316-2A04ABD4A7AD}.Release|iPhone.ActiveCfg = Release|Any CPU
{1CFFC16D-0D4A-47B3-9316-2A04ABD4A7AD}.Release|iPhone.Build.0 = Release|Any CPU
{1CFFC16D-0D4A-47B3-9316-2A04ABD4A7AD}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{1CFFC16D-0D4A-47B3-9316-2A04ABD4A7AD}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{1CFFC16D-0D4A-47B3-9316-2A04ABD4A7AD}.Release|x64.ActiveCfg = Release|Any CPU
{1CFFC16D-0D4A-47B3-9316-2A04ABD4A7AD}.Release|x64.Build.0 = Release|Any CPU
{1CFFC16D-0D4A-47B3-9316-2A04ABD4A7AD}.Release|x86.ActiveCfg = Release|Any CPU
{1CFFC16D-0D4A-47B3-9316-2A04ABD4A7AD}.Release|x86.Build.0 = Release|Any CPU
{6C6A69FE-A484-4E75-AFEC-827EA354AF46}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
{6C6A69FE-A484-4E75-AFEC-827EA354AF46}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
{6C6A69FE-A484-4E75-AFEC-827EA354AF46}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU
{6C6A69FE-A484-4E75-AFEC-827EA354AF46}.Ad-Hoc|ARM.Build.0 = Debug|Any CPU
{6C6A69FE-A484-4E75-AFEC-827EA354AF46}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
{6C6A69FE-A484-4E75-AFEC-827EA354AF46}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
{6C6A69FE-A484-4E75-AFEC-827EA354AF46}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{6C6A69FE-A484-4E75-AFEC-827EA354AF46}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
{6C6A69FE-A484-4E75-AFEC-827EA354AF46}.Ad-Hoc|x64.ActiveCfg = Debug|Any CPU
{6C6A69FE-A484-4E75-AFEC-827EA354AF46}.Ad-Hoc|x64.Build.0 = Debug|Any CPU
{6C6A69FE-A484-4E75-AFEC-827EA354AF46}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU
{6C6A69FE-A484-4E75-AFEC-827EA354AF46}.Ad-Hoc|x86.Build.0 = Debug|Any CPU
{6C6A69FE-A484-4E75-AFEC-827EA354AF46}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
{6C6A69FE-A484-4E75-AFEC-827EA354AF46}.AppStore|Any CPU.Build.0 = Debug|Any CPU
{6C6A69FE-A484-4E75-AFEC-827EA354AF46}.AppStore|ARM.ActiveCfg = Debug|Any CPU
{6C6A69FE-A484-4E75-AFEC-827EA354AF46}.AppStore|ARM.Build.0 = Debug|Any CPU
{6C6A69FE-A484-4E75-AFEC-827EA354AF46}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
{6C6A69FE-A484-4E75-AFEC-827EA354AF46}.AppStore|iPhone.Build.0 = Debug|Any CPU
{6C6A69FE-A484-4E75-AFEC-827EA354AF46}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{6C6A69FE-A484-4E75-AFEC-827EA354AF46}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
{6C6A69FE-A484-4E75-AFEC-827EA354AF46}.AppStore|x64.ActiveCfg = Debug|Any CPU
{6C6A69FE-A484-4E75-AFEC-827EA354AF46}.AppStore|x64.Build.0 = Debug|Any CPU
{6C6A69FE-A484-4E75-AFEC-827EA354AF46}.AppStore|x86.ActiveCfg = Debug|Any CPU
{6C6A69FE-A484-4E75-AFEC-827EA354AF46}.AppStore|x86.Build.0 = Debug|Any CPU
{6C6A69FE-A484-4E75-AFEC-827EA354AF46}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6C6A69FE-A484-4E75-AFEC-827EA354AF46}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6C6A69FE-A484-4E75-AFEC-827EA354AF46}.Debug|ARM.ActiveCfg = Debug|Any CPU
{6C6A69FE-A484-4E75-AFEC-827EA354AF46}.Debug|ARM.Build.0 = Debug|Any CPU
{6C6A69FE-A484-4E75-AFEC-827EA354AF46}.Debug|iPhone.ActiveCfg = Debug|Any CPU
{6C6A69FE-A484-4E75-AFEC-827EA354AF46}.Debug|iPhone.Build.0 = Debug|Any CPU
{6C6A69FE-A484-4E75-AFEC-827EA354AF46}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{6C6A69FE-A484-4E75-AFEC-827EA354AF46}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
{6C6A69FE-A484-4E75-AFEC-827EA354AF46}.Debug|x64.ActiveCfg = Debug|Any CPU
{6C6A69FE-A484-4E75-AFEC-827EA354AF46}.Debug|x64.Build.0 = Debug|Any CPU
{6C6A69FE-A484-4E75-AFEC-827EA354AF46}.Debug|x86.ActiveCfg = Debug|Any CPU
{6C6A69FE-A484-4E75-AFEC-827EA354AF46}.Debug|x86.Build.0 = Debug|Any CPU
{6C6A69FE-A484-4E75-AFEC-827EA354AF46}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6C6A69FE-A484-4E75-AFEC-827EA354AF46}.Release|Any CPU.Build.0 = Release|Any CPU
{6C6A69FE-A484-4E75-AFEC-827EA354AF46}.Release|ARM.ActiveCfg = Release|Any CPU
{6C6A69FE-A484-4E75-AFEC-827EA354AF46}.Release|ARM.Build.0 = Release|Any CPU
{6C6A69FE-A484-4E75-AFEC-827EA354AF46}.Release|iPhone.ActiveCfg = Release|Any CPU
{6C6A69FE-A484-4E75-AFEC-827EA354AF46}.Release|iPhone.Build.0 = Release|Any CPU
{6C6A69FE-A484-4E75-AFEC-827EA354AF46}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{6C6A69FE-A484-4E75-AFEC-827EA354AF46}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{6C6A69FE-A484-4E75-AFEC-827EA354AF46}.Release|x64.ActiveCfg = Release|Any CPU
{6C6A69FE-A484-4E75-AFEC-827EA354AF46}.Release|x64.Build.0 = Release|Any CPU
{6C6A69FE-A484-4E75-AFEC-827EA354AF46}.Release|x86.ActiveCfg = Release|Any CPU
{6C6A69FE-A484-4E75-AFEC-827EA354AF46}.Release|x86.Build.0 = Release|Any CPU
{2A795FEA-2EB7-45F5-9B30-35E0810CB238}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
{2A795FEA-2EB7-45F5-9B30-35E0810CB238}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
{2A795FEA-2EB7-45F5-9B30-35E0810CB238}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU
{2A795FEA-2EB7-45F5-9B30-35E0810CB238}.Ad-Hoc|ARM.Build.0 = Debug|Any CPU
{2A795FEA-2EB7-45F5-9B30-35E0810CB238}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
{2A795FEA-2EB7-45F5-9B30-35E0810CB238}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
{2A795FEA-2EB7-45F5-9B30-35E0810CB238}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{2A795FEA-2EB7-45F5-9B30-35E0810CB238}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
{2A795FEA-2EB7-45F5-9B30-35E0810CB238}.Ad-Hoc|x64.ActiveCfg = Debug|Any CPU
{2A795FEA-2EB7-45F5-9B30-35E0810CB238}.Ad-Hoc|x64.Build.0 = Debug|Any CPU
{2A795FEA-2EB7-45F5-9B30-35E0810CB238}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU
{2A795FEA-2EB7-45F5-9B30-35E0810CB238}.Ad-Hoc|x86.Build.0 = Debug|Any CPU
{2A795FEA-2EB7-45F5-9B30-35E0810CB238}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
{2A795FEA-2EB7-45F5-9B30-35E0810CB238}.AppStore|Any CPU.Build.0 = Debug|Any CPU
{2A795FEA-2EB7-45F5-9B30-35E0810CB238}.AppStore|ARM.ActiveCfg = Debug|Any CPU
{2A795FEA-2EB7-45F5-9B30-35E0810CB238}.AppStore|ARM.Build.0 = Debug|Any CPU
{2A795FEA-2EB7-45F5-9B30-35E0810CB238}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
{2A795FEA-2EB7-45F5-9B30-35E0810CB238}.AppStore|iPhone.Build.0 = Debug|Any CPU
{2A795FEA-2EB7-45F5-9B30-35E0810CB238}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{2A795FEA-2EB7-45F5-9B30-35E0810CB238}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
{2A795FEA-2EB7-45F5-9B30-35E0810CB238}.AppStore|x64.ActiveCfg = Debug|Any CPU
{2A795FEA-2EB7-45F5-9B30-35E0810CB238}.AppStore|x64.Build.0 = Debug|Any CPU
{2A795FEA-2EB7-45F5-9B30-35E0810CB238}.AppStore|x86.ActiveCfg = Debug|Any CPU
{2A795FEA-2EB7-45F5-9B30-35E0810CB238}.AppStore|x86.Build.0 = Debug|Any CPU
{2A795FEA-2EB7-45F5-9B30-35E0810CB238}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2A795FEA-2EB7-45F5-9B30-35E0810CB238}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2A795FEA-2EB7-45F5-9B30-35E0810CB238}.Debug|ARM.ActiveCfg = Debug|Any CPU
{2A795FEA-2EB7-45F5-9B30-35E0810CB238}.Debug|ARM.Build.0 = Debug|Any CPU
{2A795FEA-2EB7-45F5-9B30-35E0810CB238}.Debug|iPhone.ActiveCfg = Debug|Any CPU
{2A795FEA-2EB7-45F5-9B30-35E0810CB238}.Debug|iPhone.Build.0 = Debug|Any CPU
{2A795FEA-2EB7-45F5-9B30-35E0810CB238}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{2A795FEA-2EB7-45F5-9B30-35E0810CB238}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
{2A795FEA-2EB7-45F5-9B30-35E0810CB238}.Debug|x64.ActiveCfg = Debug|Any CPU
{2A795FEA-2EB7-45F5-9B30-35E0810CB238}.Debug|x64.Build.0 = Debug|Any CPU
{2A795FEA-2EB7-45F5-9B30-35E0810CB238}.Debug|x86.ActiveCfg = Debug|Any CPU
{2A795FEA-2EB7-45F5-9B30-35E0810CB238}.Debug|x86.Build.0 = Debug|Any CPU
{2A795FEA-2EB7-45F5-9B30-35E0810CB238}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2A795FEA-2EB7-45F5-9B30-35E0810CB238}.Release|Any CPU.Build.0 = Release|Any CPU
{2A795FEA-2EB7-45F5-9B30-35E0810CB238}.Release|ARM.ActiveCfg = Release|Any CPU
{2A795FEA-2EB7-45F5-9B30-35E0810CB238}.Release|ARM.Build.0 = Release|Any CPU
{2A795FEA-2EB7-45F5-9B30-35E0810CB238}.Release|iPhone.ActiveCfg = Release|Any CPU
{2A795FEA-2EB7-45F5-9B30-35E0810CB238}.Release|iPhone.Build.0 = Release|Any CPU
{2A795FEA-2EB7-45F5-9B30-35E0810CB238}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{2A795FEA-2EB7-45F5-9B30-35E0810CB238}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{2A795FEA-2EB7-45F5-9B30-35E0810CB238}.Release|x64.ActiveCfg = Release|Any CPU
{2A795FEA-2EB7-45F5-9B30-35E0810CB238}.Release|x64.Build.0 = Release|Any CPU
{2A795FEA-2EB7-45F5-9B30-35E0810CB238}.Release|x86.ActiveCfg = Release|Any CPU
{2A795FEA-2EB7-45F5-9B30-35E0810CB238}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
@ -1514,5 +1925,17 @@ Global
{D92EB452-7A72-4B26-A8ED-0204CD376BC4} = {D13768ED-5AF1-4E09-96DD-FF6E7A2E5E06} {D92EB452-7A72-4B26-A8ED-0204CD376BC4} = {D13768ED-5AF1-4E09-96DD-FF6E7A2E5E06}
{23FB706A-2701-41E9-8BF9-28936001CA41} = {E279BF0F-7F66-4F3A-A3AB-2CDA66C1CD04} {23FB706A-2701-41E9-8BF9-28936001CA41} = {E279BF0F-7F66-4F3A-A3AB-2CDA66C1CD04}
{6CCC4F1B-602D-4FAD-91A7-002CC86C7612} = {96CE8CE7-BC97-4A53-899F-5EB63D7BBF7B} {6CCC4F1B-602D-4FAD-91A7-002CC86C7612} = {96CE8CE7-BC97-4A53-899F-5EB63D7BBF7B}
{CC0FD121-5E19-44B6-B23F-0FE3D1B821D3} = {1EF3AC0F-F27C-46DD-AC53-D762D2C11C45}
{237CA273-8555-4944-B87D-5B65AB3A788C} = {CC0FD121-5E19-44B6-B23F-0FE3D1B821D3}
{0CF40BE0-A463-4E4F-A29C-C7427D04DC4F} = {91CF7717-08AB-4E65-B10E-0B426F01E2E8}
{B30E0E82-9EA4-49D6-BA0D-BA8E5FA48800} = {0CF40BE0-A463-4E4F-A29C-C7427D04DC4F}
{72704C77-5C90-4705-B2A4-7A6E3B02FF08} = {91CF7717-08AB-4E65-B10E-0B426F01E2E8}
{5E319B6A-9F04-4113-ABF9-AB8CD1F7A0B5} = {72704C77-5C90-4705-B2A4-7A6E3B02FF08}
{26906157-98E3-4DF8-80F6-866B9686887C} = {B473B70F-0796-4862-B1AD-BB742D93B868}
{8AE2AAA3-4507-4BEE-9250-4D16F87015B4} = {B473B70F-0796-4862-B1AD-BB742D93B868}
{1CFFC16D-0D4A-47B3-9316-2A04ABD4A7AD} = {96CE8CE7-BC97-4A53-899F-5EB63D7BBF7B}
{6C6A69FE-A484-4E75-AFEC-827EA354AF46} = {0BD0DB92-2D98-44D9-9AC0-C59186D59B0B}
{D5D3841D-F282-4E60-B9CB-267A1BF2D893} = {91CF7717-08AB-4E65-B10E-0B426F01E2E8}
{2A795FEA-2EB7-45F5-9B30-35E0810CB238} = {D5D3841D-F282-4E60-B9CB-267A1BF2D893}
EndGlobalSection EndGlobalSection
EndGlobal EndGlobal

+ 1
- 1
global.json View File

@ -1,5 +1,5 @@
{ {
"sdk": { "sdk": {
"version":"1.0.4"
"version":"1.1.0"
} }
} }

BIN
img/k8s/deploy_script_task.png View File

Before After
Width: 1408  |  Height: 527  |  Size: 36 KiB

README.CICD.k8s.md → k8s/README.CICD.k8s.md View File

@ -5,44 +5,58 @@ For k8s CI/CD pipeline delivery a series of tasks must be created in VSTS to dep
* 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 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 gen-k8s-env.ps1 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:
>``` >```
>./gen-k8s-env -resourceGroupName k8sGroup -location westeurope -registryName k8sregistry -orchestratorName k8s-cluster -dnsName k8s-dns >./gen-k8s-env -resourceGroupName k8sGroup -location westeurope -registryName k8sregistry -orchestratorName k8s-cluster -dnsName k8s-dns
>``` >```
* An `Azure Blob storage`. It is needed for storing the kubernetes config file used by the hosted agent to access to Kubernetes cluster. Example: * An `Azure Blob storage`. It is needed for storing the kubernetes config file used by the hosted agent to access to Kubernetes cluster. Example:
<img src="img/k8s/blob_creation.png">
<img src="./img/k8s/blob_creation.png">
* Upload the `kubernetes config file` to the blob storage previously created. Execute the following command which will download the config file into the directory `c:\Users\<User>\.kube\` and then, upload it to your blob storage: * Upload the `kubernetes config file` to the blob storage previously created. Execute the following command which will download the config file into the directory `c:\Users\<User>\.kube\` and then, upload it to your blob storage:
>``` >```
>https://eshopk8s.blob.core.windows.net/k8s-config/config >https://eshopk8s.blob.core.windows.net/k8s-config/config
>``` >```
## Create the VSTS tasks ## Create the VSTS tasks
1. Create a `Download File` task to download the kubernetes binary `kubectl` to the hosted agent. For example: 1. Create a `Download File` task to download the kubernetes binary `kubectl` to the hosted agent. For example:
>``` >```
>https://storage.googleapis.com/kubernetes-release/release/v0.0.1.7.0-alpha.0/bin/windows/386/kubectl.exe >https://storage.googleapis.com/kubernetes-release/release/v0.0.1.7.0-alpha.0/bin/windows/386/kubectl.exe
>``` >```
<img src="img/k8s/get_kubectlbin_task.png">
<img src="./img/get_kubectlbin_task.png">
2. Create a Download File task to download the kubernetes config file to the hosted agent. For example: 2. Create a Download File task to download the kubernetes config file to the hosted agent. For example:
>``` >```
>https://eshopk8s.blob.core.windows.net/k8s-config/config >https://eshopk8s.blob.core.windows.net/k8s-config/config
>``` >```
<img src="img/k8s/get_kubectlconfig_task.png">
<img src="./img/k8s/get_kubectlconfig_task.png">
3. Create a powershell task to execute the k8s deployment script. For example: 3. Create a powershell task to execute the k8s deployment script. For example:
* Deployment script path * Deployment script path
>``` >```
>$(System.DefaultWorkingDirectory)/All Microservices/docker-compose/deploy.ps1 >$(System.DefaultWorkingDirectory)/All Microservices/docker-compose/deploy.ps1
>``` >```
* Deployment script path arguments. Where:
- userDockerHub: indicates if Docker Hub is used instead of ACR
- deployCI: indicates that it is a CI/CD deployment
- execPath: path where the k8s binary is stored
- kubeconfigPath: path where the k8s config file is stored
* Deployment script path arguments. Use value:
>``` >```
>-deployCI $true -useDockerHub $true -execPath '$(System.DefaultWorkingDirectory)/' -kubeconfigPath '$(System.DefaultWorkingDirectory)/'
>-deployCI $true -execPath '$(System.DefaultWorkingDirectory)/' -kubeconfigPath '$(System.DefaultWorkingDirectory)/' -deployInfrastructure $true -imageTag dev -configFile '$(System.DefaultWorkingDirectory)/$(Build.DefinitionName)/docker-compose/conf_local.yml'
>``` >```
<img src="img/k8s/deploy_script_task.png">
- deployCI: Must be set to `$true`. This avoids create images (always are pulled from registry) and compile bits.
- deployInfrastructure: Can be set to `$false` if don't want to deploy infrastructure containers (like Redis, rabbit, SQL,...).
- imageTag: Image tag to pull from k8s.
- configFile: Configuration file (refer to [README.k8s.md](./README.k8s.md) for more info). This file is part of the VSTS build output.
- execPath: path where the k8s binary is stored
- kubeconfigPath: path where the k8s config file is stored
You can use additional parameters (i.e. pass registry and user/password to use custom registry instead of DockerHub. Plase, refer to [README.k8s.md](./README.k8s.md) for more info.
<img src="./img/k8s/deploy_script_task.png">

README.k8s.md → k8s/README.k8s.md View File

@ -5,9 +5,11 @@ The k8s directory contains Kubernetes configuration for the eShopOnContainers ap
* 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 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 gen-k8s-env.ps1 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:
>``` >```
>./gen-k8s-env -resourceGroupName k8sGroup -location westeurope -registryName k8sregistry -orchestratorName k8s-cluster -dnsName k8s-dns >./gen-k8s-env -resourceGroupName k8sGroup -location westeurope -registryName k8sregistry -orchestratorName k8s-cluster -dnsName k8s-dns
>``` >```
* 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.
* The Kubernetes command line client, `kubectl`. * The Kubernetes command line client, `kubectl`.
@ -17,11 +19,13 @@ The k8s directory contains Kubernetes configuration for the eShopOnContainers ap
1. Open a PowerShell command line at the `k8s` directory of your local eShopOnContainers repository. 1. Open a PowerShell command line at the `k8s` directory of your local eShopOnContainers repository.
1. Ensure `docker`, `docker-compose`, and `kubectl` are on the path, and configured for your Docker machine and Kubernetes cluster. 1. Ensure `docker`, `docker-compose`, and `kubectl` are on the path, and configured for your Docker machine and Kubernetes cluster.
1. Run `deploy.ps1` with your registry information. The Docker username and password are provided by Azure Container Registry, and can be retrieved from the Azure portal. Optionally, ACR credentials can be obtained by running the following command: 1. Run `deploy.ps1` with your registry information. The Docker username and password are provided by Azure Container Registry, and can be retrieved from the Azure portal. Optionally, ACR credentials can be obtained by running the following command:
>``` >```
>az acr credential show -n eshopregistry >az acr credential show -n eshopregistry
>``` >```
Once the user and password are retrieved, run the following script for deployment. For example: Once the user and password are retrieved, run the following script for deployment. For example:
>``` >```
>./deploy.ps1 -registry myregistry.azurecr.io -dockerUser User -dockerPassword SecretPassword -configFile file_with_config.json >./deploy.ps1 -registry myregistry.azurecr.io -dockerUser User -dockerPassword SecretPassword -configFile file_with_config.json
>``` >```
@ -54,6 +58,12 @@ The script accepts following parameters:
+ `deployInfrastructure`: If `true` infrastructure containers (rabbitmq, mongo, redis, sql) will be deployed in k8s. If `false` those containers (and its related deployments and services in k8s) won't be deployed. + `deployInfrastructure`: If `true` infrastructure containers (rabbitmq, mongo, redis, sql) will be deployed in k8s. If `false` those containers (and its related deployments and services in k8s) won't be deployed.
+ `dockerOrg`: Name of the organization in the registry where the images are (or will be pushed). Default value is `eshop` (which has images provided by Microsoft) + `dockerOrg`: Name of the organization in the registry where the images are (or will be pushed). Default value is `eshop` (which has images provided by Microsoft)
**Important:** If you **don't pass the `-buildBits $true` the script won't build and publish the projects** to their `obj/Docker/publish` folder. If any project is not published, you'll be receiving errors like:
```
ERROR: Service 'xxxxxxx' failed to build: COPY failed: stat /var/lib/docker/tmp/docker-builder123456789/obj/Docker/publish: no such file or directory
```
### Typical usages of the script: ### Typical usages of the script:
Build all projects, and deploy all them in k8s including infrastructure containers in a organization called `foo` in Docker Hub. Images will be tagged with my current git branch and containers will use the configuration set in `conf_local.yml` file: Build all projects, and deploy all them in k8s including infrastructure containers in a organization called `foo` in Docker Hub. Images will be tagged with my current git branch and containers will use the configuration set in `conf_local.yml` file:
@ -72,4 +82,4 @@ Deploy k8s using public images that Microsoft provides:
``` ```
./deploy.ps1 -buildImages $false -configFile conf_local.yml -imageTag master ./deploy.ps1 -buildImages $false -configFile conf_local.yml -imageTag master
```
```

+ 17
- 0
k8s/conf-files.md View File

@ -0,0 +1,17 @@
# YAML files used to deploy to k8s
This is just a brief enumeration of the configuration files used to create the k8s objects. Use as reference to find where specific object is.
- `deployments.yaml` Contains the definition of all deployments of the eShopOnContainers. Do not contain any infrastructure deployment (so no SQL, Redis, ...).
- `services.yaml` Contains the definition of all services of the eShopOnContainers. Do not contain any infrastructure service (so no SQL, Redis, ...).
- `basket-data.yaml` Contains the definition of the Redis (used by basket.api) deployment and service
- `nosql-data.yaml` Contains the definition of the Mongodb (used by locations and marketing) deployment and service
- `sql-data.yaml` Contains the definition of the SQL server deployment and service
- `rabbitmq.yaml` Contains the definition of the RabbitMQ deployment and service
- `keystore-data.yaml` Contains the deployment and service definition of the Redis used to mantain coherence between all the ASP.NET Identity keystores.
- `conf_local.yaml` Contains the configuration map that configures all the Pods to use "local" containers (that is all containers in k8s)
- `conf_cloud.yaml` Contains the configuration map that configures all the Pods to use "cloud" resources (that is use Azure resources instead infrastructure containers). This file is provided with no valid values, just for example.
- `frontend.yaml` Contains the deployment and service definition of the NGINX frontend used as reverse-proxy
- For more information what kubernetes deployments are, read [Kubernetes help](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/)
- For more information what kubernetes services are, read [Kubernetes help](https://kubernetes.io/docs/concepts/services-networking/service/)

+ 11
- 4
k8s/deploy.ps1 View File

@ -136,7 +136,8 @@ ExecKube -cmd 'create configmap urls `
--from-literal=BasketHealthCheckUrl=http://basket/hc ` --from-literal=BasketHealthCheckUrl=http://basket/hc `
--from-literal=CatalogUrl=http://$($externalDns)/catalog-api ` --from-literal=CatalogUrl=http://$($externalDns)/catalog-api `
--from-literal=CatalogHealthCheckUrl=http://catalog/hc ` --from-literal=CatalogHealthCheckUrl=http://catalog/hc `
--from-literal=PicBaseUrl=http://$($externalDns)/catalog-api/api/v1/catalog/items/[0]/pic/ `
--from-literal=PicBaseUrl=http://$($externalDns)/catalog-api/api/v1/catalog/items/[0]/pic/ `
--from-literal=Marketing_PicBaseUrl=http://$($externalDns)/marketing-api/api/v1/campaigns/[0]/pic/ `
--from-literal=IdentityUrl=http://$($externalDns)/identity ` --from-literal=IdentityUrl=http://$($externalDns)/identity `
--from-literal=IdentityHealthCheckUrl=http://identity/hc ` --from-literal=IdentityHealthCheckUrl=http://identity/hc `
--from-literal=OrderingUrl=http://ordering ` --from-literal=OrderingUrl=http://ordering `
@ -146,15 +147,21 @@ ExecKube -cmd 'create configmap urls `
--from-literal=MvcClientOrderingUrl=http://ordering ` --from-literal=MvcClientOrderingUrl=http://ordering `
--from-literal=MvcClientCatalogUrl=http://catalog ` --from-literal=MvcClientCatalogUrl=http://catalog `
--from-literal=MvcClientBasketUrl=http://basket ` --from-literal=MvcClientBasketUrl=http://basket `
--from-literal=WebSpaHealthCheckUrl=http://webspa/hc `
--from-literal=MvcClientMarketingUrl=http://marketing `
--from-literal=MarketingHealthCheckUrl=http://marketing/hc ` --from-literal=MarketingHealthCheckUrl=http://marketing/hc `
--from-literal=WebSpaHealthCheckUrl=http://webspa/hc `
--from-literal=SpaClientMarketingExternalUrl=http://$($externalDns)/marketing-api `
--from-literal=SpaClientOrderingExternalUrl=http://$($externalDns)/ordering-api ` --from-literal=SpaClientOrderingExternalUrl=http://$($externalDns)/ordering-api `
--from-literal=SpaClientCatalogExternalUrl=http://$($externalDns)/catalog-api ` --from-literal=SpaClientCatalogExternalUrl=http://$($externalDns)/catalog-api `
--from-literal=SpaClientBasketExternalUrl=http://$($externalDns)/basket-api ` --from-literal=SpaClientBasketExternalUrl=http://$($externalDns)/basket-api `
--from-literal=SpaClientIdentityExternalUrl=http://$($externalDns)/identity ` --from-literal=SpaClientIdentityExternalUrl=http://$($externalDns)/identity `
--from-literal=LocationsHealthCheckUrl=http://locations/hc ` --from-literal=LocationsHealthCheckUrl=http://locations/hc `
--from-literal=SpaClientExternalUrl=http://$($externalDns)'
--from-literal=SpaClientExternalUrl=http://$($externalDns) `
--from-literal=LocationApiClient=http://$($externalDns)/locations-api `
--from-literal=MarketingApiClient=http://$($externalDns)/marketing-api `
--from-literal=BasketApiClient=http://$($externalDns)/basket-api `
--from-literal=OrderingApiClient=http://$($externalDns)/ordering-api'
ExecKube -cmd 'label configmap urls app=eshop' ExecKube -cmd 'label configmap urls app=eshop'
Write-Host "Deploying configuration from $configFile" -ForegroundColor Yellow Write-Host "Deploying configuration from $configFile" -ForegroundColor Yellow


+ 45
- 0
k8s/deployments.yaml View File

@ -127,6 +127,26 @@ spec:
configMapKeyRef: configMapKeyRef:
name: urls name: urls
key: SpaClientExternalUrl key: SpaClientExternalUrl
- name: LocationApiClient
valueFrom:
configMapKeyRef:
name: urls
key: LocationApiClient
- name: MarketingApiClient
valueFrom:
configMapKeyRef:
name: urls
key: MarketingApiClient
- name: BasketApiClient
valueFrom:
configMapKeyRef:
name: urls
key: BasketApiClient
- name: OrderingApiClient
valueFrom:
configMapKeyRef:
name: urls
key: OrderingApiClient
ports: ports:
- containerPort: 80 - containerPort: 80
imagePullSecrets: imagePullSecrets:
@ -267,6 +287,11 @@ spec:
configMapKeyRef: configMapKeyRef:
name: urls name: urls
key: IdentityUrl key: IdentityUrl
- name: IdentityUrlExternal
valueFrom:
configMapKeyRef:
name: urls
key: IdentityUrl
ports: ports:
- containerPort: 80 - containerPort: 80
imagePullSecrets: imagePullSecrets:
@ -321,6 +346,16 @@ spec:
configMapKeyRef: configMapKeyRef:
name: urls name: urls
key: IdentityUrl key: IdentityUrl
- name: IdentityUrlExternal
valueFrom:
configMapKeyRef:
name: urls
key: IdentityUrl
- name: PicBaseUrl
valueFrom:
configMapKeyRef:
name: urls
key: Marketing_PicBaseUrl
ports: ports:
- containerPort: 80 - containerPort: 80
imagePullSecrets: imagePullSecrets:
@ -411,6 +446,11 @@ spec:
configMapKeyRef: configMapKeyRef:
name: urls name: urls
key: MvcClientOrderingUrl key: MvcClientOrderingUrl
- name: MarketingUrl
valueFrom:
configMapKeyRef:
name: urls
key: MvcClientMarketingUrl
ports: ports:
- containerPort: 80 - containerPort: 80
imagePullSecrets: imagePullSecrets:
@ -531,6 +571,11 @@ spec:
configMapKeyRef: configMapKeyRef:
name: urls name: urls
key: SpaClientOrderingExternalUrl key: SpaClientOrderingExternalUrl
- name: MarketingUrl
valueFrom:
configMapKeyRef:
name: urls
key: SpaClientMarketingExternalUrl
- name: BasketUrlHC - name: BasketUrlHC
valueFrom: valueFrom:
configMapKeyRef: configMapKeyRef:


BIN
img/k8s/blob_creation.png → k8s/img/blob_creation.png View File


BIN
k8s/img/deploy_script_task.png View File


BIN
img/k8s/get_kubectlbin_task.png → k8s/img/get_kubectlbin_task.png View File


BIN
img/k8s/get_kubectlconfig_task.png → k8s/img/get_kubectlconfig_task.png View File


+ 12
- 0
k8s/readme.md View File

@ -0,0 +1,12 @@
# Kubernetes (k8s) deploy information
This folder contains files needed to **create** a ACS with Kubernetes in Azure and to **deploy** eShopServices in a existing Kubernetes:
- `gen-k8s-env.ps1` Script to create a ACS with Kubernetes in Azure
- `deploy.ps1` Script to deploy eShopOnContainers in a existing k8s
Refer to file [README.k8s.md](./README.k8s.md) for detailed information
Refer to file [README.CICD.k8s.md](./README.CICD.k8s.md) for information about how to set a VSTS build for deploying on k8s
Refer to file [conf-files.md](./conf-files.md) for a brief descriptio of every YAML file in this folder

README.ENV.md → readme/README.ENV.md View File


+ 79
- 0
readme/readme-docker-compose.md View File

@ -0,0 +1,79 @@
# Docker-compose yaml files
In the root folder of the repo are all docker-compose files (`docker-compose*.yml`). Here is a list of all of them and what is their purpose:
## Container build
* `docker-compose.ci.build.yml`: This file is for starting the build container to build the project using a container that has all needed prerequisites. Refer to [corresponding wiki section](https://github.com/dotnet-architecture/eShopOnContainers/wiki/03.-Setting-the-eShopOnContainers-solution-up-in-a-Windows-CLI-environment-(dotnet-CLI,-Docker-CLI-and-VS-Code)#build-the-bits-through-the-build-container-image) for more information.
## Files needed to run eShopOnContainers locally
* `docker-compose.yml`: This file contains **the definition of all images needed for running eShopOnContainers**.
* `docker-compose.override.yml`: This file contains the base configuration for all images of the previous file
Usually these two files are using together. The standard way to start eShopOnContainers from CLI is:
```
docker-compose -f docker-compose.yml -f docker-compose.override.yml
```
This will start eShopOnContainers with all containers running locally, and it is the default development environment.
## Files needed to run eShopOnContainers on a remote docker host
* `docker-compose.prod.yml`: This file is a replacement of the `docker-compose.override.yml` but contains some configurations more suitable for a "production" environment or when you need to run the services using an external docker host.
```
docker-compose -f docker-compose.yml -f docker-compose.prod.yml
```
When using this file the following environments variables must be set:
* `ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP` with the IP or DNS name of the docker host that runs the services (can use `localhost` if needed).
* `ESHOP_AZURE_STORAGE_CATALOG` with the URL of the Azure Storage that will host the catalog images
* `ESHOP_AZURE_STORAGE_MARKETING` with the URL of the Azure Storage that will host the marketing campaign images
You might wonder why an external image resource (storage) is needed when using `docker-compose.prod.yml` instead of `docker-compose.override.yml`. Answer to this is related to a limitation of Docker Compose file format. This is how we set the environment configuration of Catalog microservice in `docker-compose.override.yml`:
```
PicBaseUrl=${ESHOP_AZURE_STORAGE_CATALOG:-http://localhost:5101/api/v1/catalog/items/[0]/pic/}
```
The `PicBaseUrl` variable is set to the value of `ESHOP_AZURE_STORAGE_CATALOG` if this variable is set to any value other than blank string. If not, the value is set to `http://localhost:5101/api/v1/catalog/items/[0]/pic/`. That works perfectly in a local environment where you run all your services in `localhost` and setting `ESHOP_AZURE_STORAGE_CATALOG` you can use or not Azure Storage for the images (if you don't use Azure Storage images are served locally by catalog servide). But when you run the services in a external docker host, specified in `ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP`, the configuration should be as follows:
```
PicBaseUrl=${ESHOP_AZURE_STORAGE_CATALOG:-http://${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}:5101/api/v1/catalog/items/[0]/pic/}
```
So, use `ESHOP_AZURE_STORAGE_CATALOG` if set, and if not use `http://${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}:5101/api/v1/catalog/items/[0]/pic/}`. Unfortunately seems that docker-compose do not substitute variables inside variables, so the value that `PicBaseUrl` gets if `ESHOP_AZURE_STORAGE_CATALOG` is not set is literally `http://${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}:5101/api/v1/catalog/items/[0]/pic/}` without any substitution.
**For more information** about docker-compose variable substitution read the [compose docs](https://docs.docker.com/compose/compose-file/#variable-substitution).
## Other files
* `docker-compose.nobuild.yml`: This file contains the definition of all images needed to run the eShopOnContainers. Contains **the same images that `docker-compose.yml`** but without any `build` instruction. If you use this file instead of `docker-compose.yml` when launching the project and you don't have the images built locally, **the images will be pulled from dockerhub**. This file is not intended for development usage, but for some CI/CD scenarios.
* `docker-compose.vs.debug.yml`: This file is used by Docker Tools of VS2017, and should not be used directly.
* `docker-compose.vs.release.yml`: This file is used by Docker Tools of VS2017, and should not be used directly.
**Note**: The reason why we need the `docker-compose.nobuild.yml` is that [docker-compose issue #3391](https://github.com/docker/compose/issues/3391). Once solved, parameter `--no-build` of docker-compose could be used safely in a CI/CD environments and the need for this file will disappear.
## Windows container files
All `docker-compose-windows*.yml` files have a 1:1 relationship with the same file without the `-windows` in its name. Those files are used to run Windows Containers instead of Linux Containers.
* `docker-compose-windows.yml`: Contains the definitions of all containers that are needed to run eShopOnContainers using windows containers (equivalent to `docker-compose.yml`).
* `docker-compose-windows.override.yml`: Contains the base configuration for all windows containers
**Note** We plan **to remove** the `docker-compose-windows.override.yml` file, because it is **exactly the same** as the `docker-compose.override.yml`. The reason of its existence is historical, but is no longer needed. You can use `docker-compose.override.yml` instead.
* `docker-compose-windows.prod.yml` is the equivalent of `docker-compose.prod.yml` for containers windows. As happens with `docker-compose-windows.override.yml` this file will be deleted in a near future, so you should use `docker-compose.prod.yml` instead.
## "External container" files
These files were intended to provide a fast way to start only "infrastructure" containers (SQL Server, Redis, etc). *This files are deprecated and will be deleted in a near future**:
* `docker-compose-external.override.yml`
* `docker-compose-external.yml`
If you want to start only certain containers use `docker-compose -f ... -f ... up container1 contaner2 containerN` as specified in [compose doc](https://docs.docker.com/compose/reference/up/)

+ 19
- 0
readme/readme.md View File

@ -0,0 +1,19 @@
# Documentation index
This file contains links to the documentation of the project.
* **Wiki**: The wiki contains detailed step-by-step information about how to set up the project. Read it at: [https://github.com/dotnet-architecture/eShopOnContainers/wiki](https://github.com/dotnet-architecture/eShopOnContainers/wiki)
## Documentation included in files
* [Branch Guide](../branch-guide.md): List of branches used and their purpose.
* [vsts-docs folder](../vsts-docs/readme.md): Information about how to setup a CI/CD procedure using VSTS
* [Kubernetes](../k8s/readme.md): Information about how to deploy eShopOnContainers in a kubernetes cluster, and how to setup a CI/CD for k8s using VSTS
* [deploy](../deploy/readme.md): Information about how deploy Azure resources using the Azure CLI 2.0.
* [.env file](./README.ENV.md): What is the `.env` file and how to use it to configure eShopOnContainers to use external resources (like Azure)
* [docker-compose files](./readme-docker-compose.md): What are all these `docker-compose-*.yml` files
## Docs folder
The `/docs` folder contains the pdfs versions of the books

+ 5
- 3
src/BuildingBlocks/EventBus/EventBusServiceBus/EventBusServiceBus.cs View File

@ -22,6 +22,7 @@
private readonly SubscriptionClient _subscriptionClient; private readonly SubscriptionClient _subscriptionClient;
private readonly ILifetimeScope _autofac; private readonly ILifetimeScope _autofac;
private readonly string AUTOFAC_SCOPE_NAME = "eshop_event_bus"; private readonly string AUTOFAC_SCOPE_NAME = "eshop_event_bus";
private const string INTEGRATION_EVENT_SUFIX = "IntegrationEvent";
public EventBusServiceBus(IServiceBusPersisterConnection serviceBusPersisterConnection, public EventBusServiceBus(IServiceBusPersisterConnection serviceBusPersisterConnection,
ILogger<EventBusServiceBus> logger, IEventBusSubscriptionsManager subsManager, string subscriptionClientName, ILogger<EventBusServiceBus> logger, IEventBusSubscriptionsManager subsManager, string subscriptionClientName,
@ -41,7 +42,7 @@
public void Publish(IntegrationEvent @event) public void Publish(IntegrationEvent @event)
{ {
var eventName = @event.GetType().Name;
var eventName = @event.GetType().Name.Replace(INTEGRATION_EVENT_SUFIX, "");
var jsonMessage = JsonConvert.SerializeObject(@event); var jsonMessage = JsonConvert.SerializeObject(@event);
var body = Encoding.UTF8.GetBytes(jsonMessage); var body = Encoding.UTF8.GetBytes(jsonMessage);
@ -69,7 +70,8 @@
where T : IntegrationEvent where T : IntegrationEvent
where TH : IIntegrationEventHandler<T> where TH : IIntegrationEventHandler<T>
{ {
var eventName = typeof(T).Name;
var eventName = typeof(T).Name.Replace(INTEGRATION_EVENT_SUFIX, "");
var containsKey = _subsManager.HasSubscriptionsForEvent<T>(); var containsKey = _subsManager.HasSubscriptionsForEvent<T>();
if (!containsKey) if (!containsKey)
{ {
@ -94,7 +96,7 @@
where T : IntegrationEvent where T : IntegrationEvent
where TH : IIntegrationEventHandler<T> where TH : IIntegrationEventHandler<T>
{ {
var eventName = typeof(T).Name;
var eventName = typeof(T).Name.Replace(INTEGRATION_EVENT_SUFIX, "");
try try
{ {


+ 5
- 5
src/BuildingBlocks/Resilience/Resilience.Http/StandardHttpClient.cs View File

@ -40,10 +40,10 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.Resilience.Http
throw new ArgumentException("Value must be either post or put.", nameof(method)); throw new ArgumentException("Value must be either post or put.", nameof(method));
} }
// a new StringContent must be created for each retry
// a new StringContent must be created for each retry
// as it is disposed after each call // as it is disposed after each call
var requestMessage = new HttpRequestMessage(HttpMethod.Post, uri);
var requestMessage = new HttpRequestMessage(method, uri);
requestMessage.Content = new StringContent(JsonConvert.SerializeObject(item), System.Text.Encoding.UTF8, "application/json"); requestMessage.Content = new StringContent(JsonConvert.SerializeObject(item), System.Text.Encoding.UTF8, "application/json");
@ -59,7 +59,7 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.Resilience.Http
var response = await _client.SendAsync(requestMessage); var response = await _client.SendAsync(requestMessage);
// raise exception if HttpResponseCode 500
// raise exception if HttpResponseCode 500
// needed for circuit breaker to track fails // needed for circuit breaker to track fails
if (response.StatusCode == HttpStatusCode.InternalServerError) if (response.StatusCode == HttpStatusCode.InternalServerError)
@ -73,12 +73,12 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.Resilience.Http
public async Task<HttpResponseMessage> PostAsync<T>(string uri, T item, string authorizationToken = null, string requestId = null, string authorizationMethod = "Bearer") public async Task<HttpResponseMessage> PostAsync<T>(string uri, T item, string authorizationToken = null, string requestId = null, string authorizationMethod = "Bearer")
{ {
return await DoPostPutAsync(HttpMethod.Post, uri, item, authorizationToken, requestId, authorizationToken);
return await DoPostPutAsync(HttpMethod.Post, uri, item, authorizationToken, requestId, authorizationMethod);
} }
public async Task<HttpResponseMessage> PutAsync<T>(string uri, T item, string authorizationToken = null, string requestId = null, string authorizationMethod = "Bearer") public async Task<HttpResponseMessage> PutAsync<T>(string uri, T item, string authorizationToken = null, string requestId = null, string authorizationMethod = "Bearer")
{ {
return await DoPostPutAsync(HttpMethod.Put, uri, item, authorizationToken, requestId, authorizationToken);
return await DoPostPutAsync(HttpMethod.Put, uri, item, authorizationToken, requestId, authorizationMethod);
} }
public async Task<HttpResponseMessage> DeleteAsync(string uri, string authorizationToken = null, string requestId = null, string authorizationMethod = "Bearer") public async Task<HttpResponseMessage> DeleteAsync(string uri, string authorizationToken = null, string requestId = null, string authorizationMethod = "Bearer")
{ {


+ 1
- 6
src/Mobile/eShopOnContainers/eShopOnContainers.Core/App.xaml View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8" ?>
<?xml version="1.0" encoding="utf-8" ?>
<Application xmlns="http://xamarin.com/schemas/2014/forms" <Application xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:light="clr-namespace:Xamarin.Forms.Themes;assembly=Xamarin.Forms.Theme.Light" xmlns:light="clr-namespace:Xamarin.Forms.Themes;assembly=Xamarin.Forms.Theme.Light"
@ -101,17 +101,12 @@
<!-- CONVERTERS --> <!-- CONVERTERS -->
<converters:CountToBoolConverter x:Key="CountToBoolConverter" /> <converters:CountToBoolConverter x:Key="CountToBoolConverter" />
<converters:DatetimeConverter x:Key="DatetimeConverter" /> <converters:DatetimeConverter x:Key="DatetimeConverter" />
<converters:FirstValidationErrorConverter x:Key="FirstValidationErrorConverter" />
<converters:ImageConverter x:Key="ImageConverter" /> <converters:ImageConverter x:Key="ImageConverter" />
<converters:ItemTappedEventArgsConverter x:Key="ItemTappedEventArgsConverter" /> <converters:ItemTappedEventArgsConverter x:Key="ItemTappedEventArgsConverter" />
<converters:InverseCountToBoolConverter x:Key="InverseCountToBoolConverter" /> <converters:InverseCountToBoolConverter x:Key="InverseCountToBoolConverter" />
<converters:InverseBoolConverter x:Key="InverseBoolConverter" /> <converters:InverseBoolConverter x:Key="InverseBoolConverter" />
<converters:ItemsToHeightConverter x:Key="ItemsToHeightConverter" /> <converters:ItemsToHeightConverter x:Key="ItemsToHeightConverter" />
<converters:ToUpperConverter x:Key="ToUpperConverter" /> <converters:ToUpperConverter x:Key="ToUpperConverter" />
<converters:WebNavigatingEventArgsConverter x:Key="WebNavigatingEventArgsConverter" />
<converters:WebNavigatedEventArgsConverter x:Key="WebNavigatedEventArgsConverter" />
<converters:StringNullOrEmptyBoolConverter x:Key="StringNullOrEmptyBoolConverter" />
<converters:DoubleConverter x:Key="DoubleConverter" />
<!-- STYLES --> <!-- STYLES -->
<Style x:Key="ValidationErrorLabelStyle" <Style x:Key="ValidationErrorLabelStyle"


+ 23
- 0
src/Mobile/eShopOnContainers/eShopOnContainers.Core/Helpers/RandomNumberGenerator.cs View File

@ -0,0 +1,23 @@
using System.Text;
namespace eShopOnContainers.Core.Helpers
{
internal static class RandomNumberGenerator
{
public static string CreateUniqueId(int length = 64)
{
var bytes = PCLCrypto.WinRTCrypto.CryptographicBuffer.GenerateRandom(length);
return ByteArrayToString(bytes);
}
private static string ByteArrayToString(byte[] array)
{
var hex = new StringBuilder(array.Length * 2);
foreach (byte b in array)
{
hex.AppendFormat("{0:x2}", b);
}
return hex.ToString();
}
}
}

+ 4
- 4
src/Mobile/eShopOnContainers/eShopOnContainers.Core/Helpers/ServicesHelper.cs View File

@ -78,7 +78,7 @@ namespace eShopOnContainers.Core.Helpers
} }
} }
public static void FixCatalogItemPictureUri(IEnumerable<CampaignItem> campaignItems)
public static void FixCampaignItemPictureUri(IEnumerable<CampaignItem> campaignItems)
{ {
if (campaignItems == null) if (campaignItems == null)
{ {
@ -90,9 +90,9 @@ namespace eShopOnContainers.Core.Helpers
if (!ViewModelLocator.UseMockService if (!ViewModelLocator.UseMockService
&& Settings.UrlBase != GlobalSetting.DefaultEndpoint) && Settings.UrlBase != GlobalSetting.DefaultEndpoint)
{ {
foreach (var catalogItem in campaignItems)
foreach (var campaignItem in campaignItems)
{ {
MatchCollection serverResult = IpRegex.Matches(catalogItem.PictureUri);
MatchCollection serverResult = IpRegex.Matches(campaignItem.PictureUri);
MatchCollection localResult = IpRegex.Matches(Settings.UrlBase); MatchCollection localResult = IpRegex.Matches(Settings.UrlBase);
if (serverResult.Count != -1 && localResult.Count != -1) if (serverResult.Count != -1 && localResult.Count != -1)
@ -100,7 +100,7 @@ namespace eShopOnContainers.Core.Helpers
var serviceIp = serverResult[0].Value; var serviceIp = serverResult[0].Value;
var localIp = localResult[0].Value; var localIp = localResult[0].Value;
catalogItem.PictureUri = catalogItem.PictureUri.Replace(serviceIp, localIp);
campaignItem.PictureUri = campaignItem.PictureUri.Replace(serviceIp, localIp);
} }
} }
} }


+ 2
- 2
src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Common/Common.cs View File

@ -8,7 +8,7 @@
public static string MockCatalogItemId04 = "4"; public static string MockCatalogItemId04 = "4";
public static string MockCatalogItemId05 = "5"; public static string MockCatalogItemId05 = "5";
public static int MockCampaignd01 = 1;
public static int MockCampaignd02 = 2;
public static int MockCampaignId01 = 1;
public static int MockCampaignId02 = 2;
} }
} }

+ 21
- 3
src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Identity/IdentityService.cs View File

@ -1,16 +1,22 @@
using IdentityModel.Client;
using System;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Net; using System.Net;
using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using eShopOnContainers.Core.Services.RequestProvider; using eShopOnContainers.Core.Services.RequestProvider;
using eShopOnContainers.Core.Models.Token; using eShopOnContainers.Core.Models.Token;
using eShopOnContainers.Core.Helpers;
using IdentityModel;
using IdentityModel.Client;
using PCLCrypto;
using static PCLCrypto.WinRTCrypto;
namespace eShopOnContainers.Core.Services.Identity namespace eShopOnContainers.Core.Services.Identity
{ {
public class IdentityService : IIdentityService public class IdentityService : IIdentityService
{ {
private readonly IRequestProvider _requestProvider; private readonly IRequestProvider _requestProvider;
private string _codeVerifier;
public IdentityService(IRequestProvider requestProvider) public IdentityService(IRequestProvider requestProvider)
{ {
@ -30,6 +36,8 @@ namespace eShopOnContainers.Core.Services.Identity
dic.Add("scope", "openid profile basket orders locations marketing offline_access"); dic.Add("scope", "openid profile basket orders locations marketing offline_access");
dic.Add("redirect_uri", GlobalSetting.Instance.IdentityCallback); dic.Add("redirect_uri", GlobalSetting.Instance.IdentityCallback);
dic.Add("nonce", Guid.NewGuid().ToString("N")); dic.Add("nonce", Guid.NewGuid().ToString("N"));
dic.Add("code_challenge", CreateCodeChallenge());
dic.Add("code_challenge_method", "S256");
// Add CSRF token to protect against cross-site request forgery attacks. // Add CSRF token to protect against cross-site request forgery attacks.
var currentCSRFToken = Guid.NewGuid().ToString("N"); var currentCSRFToken = Guid.NewGuid().ToString("N");
@ -54,9 +62,19 @@ namespace eShopOnContainers.Core.Services.Identity
public async Task<UserToken> GetTokenAsync(string code) public async Task<UserToken> GetTokenAsync(string code)
{ {
string data = string.Format("grant_type=authorization_code&code={0}&redirect_uri={1}", code, WebUtility.UrlEncode(GlobalSetting.Instance.IdentityCallback));
string data = string.Format("grant_type=authorization_code&code={0}&redirect_uri={1}&code_verifier={2}", code, WebUtility.UrlEncode(GlobalSetting.Instance.IdentityCallback), _codeVerifier);
var token = await _requestProvider.PostAsync<UserToken>(GlobalSetting.Instance.TokenEndpoint, data, GlobalSetting.Instance.ClientId, GlobalSetting.Instance.ClientSecret); var token = await _requestProvider.PostAsync<UserToken>(GlobalSetting.Instance.TokenEndpoint, data, GlobalSetting.Instance.ClientId, GlobalSetting.Instance.ClientSecret);
return token; return token;
} }
private string CreateCodeChallenge()
{
_codeVerifier = RandomNumberGenerator.CreateUniqueId();
var sha256 = HashAlgorithmProvider.OpenAlgorithm(HashAlgorithm.Sha256);
var challengeBuffer = sha256.HashData(CryptographicBuffer.CreateFromByteArray(Encoding.UTF8.GetBytes(_codeVerifier)));
byte[] challengeBytes;
CryptographicBuffer.CopyToByteArray(challengeBuffer, out challengeBytes);
return Base64Url.Encode(challengeBytes);
}
} }
} }

+ 2
- 2
src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Marketing/CampaignMockService.cs View File

@ -13,7 +13,7 @@
{ {
new CampaignItem new CampaignItem
{ {
Id = Common.Common.MockCampaignd01,
Id = Common.Common.MockCampaignId01,
PictureUri = Device.RuntimePlatform != Device.Windows PictureUri = Device.RuntimePlatform != Device.Windows
? "fake_campaign_01.png" ? "fake_campaign_01.png"
: "Assets/fake_campaign_01.png", : "Assets/fake_campaign_01.png",
@ -25,7 +25,7 @@
new CampaignItem new CampaignItem
{ {
Id = Common.Common.MockCampaignd02,
Id = Common.Common.MockCampaignId02,
PictureUri = Device.RuntimePlatform != Device.Windows PictureUri = Device.RuntimePlatform != Device.Windows
? "fake_campaign_02.png" ? "fake_campaign_02.png"
: "Assets/fake_campaign_02.png", : "Assets/fake_campaign_02.png",


+ 1
- 1
src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Marketing/CampaignService.cs View File

@ -30,7 +30,7 @@
if (campaign?.Data != null) if (campaign?.Data != null)
{ {
ServicesHelper.FixCatalogItemPictureUri(campaign?.Data);
ServicesHelper.FixCampaignItemPictureUri(campaign?.Data);
return campaign?.Data.ToObservableCollection(); return campaign?.Data.ToObservableCollection();
} }


+ 7
- 7
src/Mobile/eShopOnContainers/eShopOnContainers.Core/ViewModels/SettingsViewModel.cs View File

@ -281,13 +281,13 @@ namespace eShopOnContainers.Core.ViewModels
if (!UseFakeLocation) if (!UseFakeLocation)
{ {
TitleUseFakeLocation = "Use Real Location"; TitleUseFakeLocation = "Use Real Location";
DescriptionUseFakeLocation = "When enabling the use of real location, the app will attempt to use real location from the device.";
DescriptionUseFakeLocation = "When enabling location, the app will attempt to use the location from the device.";
} }
else else
{ {
TitleUseFakeLocation = "Use Fake Location"; TitleUseFakeLocation = "Use Fake Location";
DescriptionUseFakeLocation = "Fake Location are added for marketing campaign testing.";
DescriptionUseFakeLocation = "Fake Location data is added for marketing campaign testing.";
} }
} }
@ -295,13 +295,13 @@ namespace eShopOnContainers.Core.ViewModels
{ {
if (!AllowGpsLocation) if (!AllowGpsLocation)
{ {
TitleAllowGpsLocation = "GPS location Denied";
DescriptionAllowGpsLocation = "When denying the use of device gps you won't get the location campaigns through your real location.";
TitleAllowGpsLocation = "GPS Location Disabled";
DescriptionAllowGpsLocation = "When disabling location, you won't receive location campaigns based upon your location.";
} }
else else
{ {
TitleAllowGpsLocation = "GPS location Allowed";
DescriptionAllowGpsLocation = "When allowing the use of device gps you will get the location campaigns through your real location.";
TitleAllowGpsLocation = "GPS Location Enabled";
DescriptionAllowGpsLocation = "When enabling location, you'll receive location campaigns based upon your location.";
} }
} }
@ -344,7 +344,7 @@ namespace eShopOnContainers.Core.ViewModels
if (!locator.IsGeolocationEnabled) if (!locator.IsGeolocationEnabled)
{ {
_allowGpsLocation = false; _allowGpsLocation = false;
GpsWarningMessage = "Enable your GPS system in your device";
GpsWarningMessage = "Enable the GPS sensor on your device";
} }
else else
{ {


+ 3
- 0
src/Mobile/eShopOnContainers/eShopOnContainers.Core/Views/CampaignDetailsView.xaml View File

@ -2,11 +2,14 @@
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="eShopOnContainers.Core.Views.CampaignDetailsView" x:Class="eShopOnContainers.Core.Views.CampaignDetailsView"
xmlns:converters="clr-namespace:eShopOnContainers.Core.Converters;assembly=eShopOnContainers.Core"
xmlns:viewModelBase="clr-namespace:eShopOnContainers.Core.ViewModels.Base;assembly=eShopOnContainers.Core" xmlns:viewModelBase="clr-namespace:eShopOnContainers.Core.ViewModels.Base;assembly=eShopOnContainers.Core"
viewModelBase:ViewModelLocator.AutoWireViewModel="true" viewModelBase:ViewModelLocator.AutoWireViewModel="true"
Title="Campaign Details"> Title="Campaign Details">
<ContentPage.Resources> <ContentPage.Resources>
<ResourceDictionary> <ResourceDictionary>
<converters:StringNullOrEmptyBoolConverter x:Key="StringNullOrEmptyBoolConverter" />
<Style x:Key="CampaignTitleStyle" <Style x:Key="CampaignTitleStyle"
TargetType="{x:Type Label}"> TargetType="{x:Type Label}">
<Setter Property="FontFamily" <Setter Property="FontFamily"


+ 1
- 1
src/Mobile/eShopOnContainers/eShopOnContainers.Core/Views/CampaignView.xaml View File

@ -8,7 +8,7 @@
xmlns:triggers="clr-namespace:eShopOnContainers.Core.Triggers;assembly=eShopOnContainers.Core" xmlns:triggers="clr-namespace:eShopOnContainers.Core.Triggers;assembly=eShopOnContainers.Core"
xmlns:behaviors="clr-namespace:eShopOnContainers.Core.Behaviors;assembly=eShopOnContainers.Core" xmlns:behaviors="clr-namespace:eShopOnContainers.Core.Behaviors;assembly=eShopOnContainers.Core"
viewModelBase:ViewModelLocator.AutoWireViewModel="true" viewModelBase:ViewModelLocator.AutoWireViewModel="true"
Title="Catalog">
Title="Campaigns">
<ContentPage.Resources> <ContentPage.Resources>
<ResourceDictionary> <ResourceDictionary>


+ 5
- 1
src/Mobile/eShopOnContainers/eShopOnContainers.Core/Views/LoginView.xaml View File

@ -4,6 +4,7 @@
x:Class="eShopOnContainers.Core.Views.LoginView" x:Class="eShopOnContainers.Core.Views.LoginView"
xmlns:viewModelBase="clr-namespace:eShopOnContainers.Core.ViewModels.Base;assembly=eShopOnContainers.Core" xmlns:viewModelBase="clr-namespace:eShopOnContainers.Core.ViewModels.Base;assembly=eShopOnContainers.Core"
xmlns:animations="clr-namespace:eShopOnContainers.Core.Animations;assembly=eShopOnContainers.Core" xmlns:animations="clr-namespace:eShopOnContainers.Core.Animations;assembly=eShopOnContainers.Core"
xmlns:converters="clr-namespace:eShopOnContainers.Core.Converters;assembly=eShopOnContainers.Core"
xmlns:triggers="clr-namespace:eShopOnContainers.Core.Triggers;assembly=eShopOnContainers.Core" xmlns:triggers="clr-namespace:eShopOnContainers.Core.Triggers;assembly=eShopOnContainers.Core"
xmlns:behaviors="clr-namespace:eShopOnContainers.Core.Behaviors;assembly=eShopOnContainers.Core" xmlns:behaviors="clr-namespace:eShopOnContainers.Core.Behaviors;assembly=eShopOnContainers.Core"
viewModelBase:ViewModelLocator.AutoWireViewModel="true"> viewModelBase:ViewModelLocator.AutoWireViewModel="true">
@ -15,7 +16,10 @@
</ContentPage.Title> </ContentPage.Title>
<ContentPage.Resources> <ContentPage.Resources>
<ResourceDictionary> <ResourceDictionary>
<converters:FirstValidationErrorConverter x:Key="FirstValidationErrorConverter" />
<converters:WebNavigatingEventArgsConverter x:Key="WebNavigatingEventArgsConverter" />
<converters:WebNavigatedEventArgsConverter x:Key="WebNavigatedEventArgsConverter" />
<Style x:Key="TitleLabelStyle" <Style x:Key="TitleLabelStyle"
TargetType="{x:Type Label}"> TargetType="{x:Type Label}">
<Setter Property="FontFamily" <Setter Property="FontFamily"


+ 4
- 2
src/Mobile/eShopOnContainers/eShopOnContainers.Core/Views/SettingsView.xaml View File

@ -3,14 +3,16 @@
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="eShopOnContainers.Core.Views.SettingsView" x:Class="eShopOnContainers.Core.Views.SettingsView"
xmlns:viewModelBase="clr-namespace:eShopOnContainers.Core.ViewModels.Base;assembly=eShopOnContainers.Core" xmlns:viewModelBase="clr-namespace:eShopOnContainers.Core.ViewModels.Base;assembly=eShopOnContainers.Core"
xmlns:controls="clr-namespace:eShopOnContainers.Core.Controls;assembly=eShopOnContainers.Core"
xmlns:controls="clr-namespace:eShopOnContainers.Core.Controls;assembly=eShopOnContainers.Core"
xmlns:converters="clr-namespace:eShopOnContainers.Core.Converters;assembly=eShopOnContainers.Core"
xmlns:animations="clr-namespace:eShopOnContainers.Core.Animations;assembly=eShopOnContainers.Core" xmlns:animations="clr-namespace:eShopOnContainers.Core.Animations;assembly=eShopOnContainers.Core"
xmlns:triggers="clr-namespace:eShopOnContainers.Core.Triggers;assembly=eShopOnContainers.Core" xmlns:triggers="clr-namespace:eShopOnContainers.Core.Triggers;assembly=eShopOnContainers.Core"
viewModelBase:ViewModelLocator.AutoWireViewModel="true" viewModelBase:ViewModelLocator.AutoWireViewModel="true"
Title="Settings"> Title="Settings">
<ContentPage.Resources> <ContentPage.Resources>
<ResourceDictionary> <ResourceDictionary>
<converters:DoubleConverter x:Key="DoubleConverter" />
<Style x:Key="SettingsStackLayoutStyle" TargetType="{x:Type StackLayout}"> <Style x:Key="SettingsStackLayoutStyle" TargetType="{x:Type StackLayout}">
<Setter Property="Margin" <Setter Property="Margin"
Value="6" /> Value="6" />


+ 1
- 0
src/Mobile/eShopOnContainers/eShopOnContainers.Core/eShopOnContainers.Core.csproj View File

@ -64,6 +64,7 @@
<Compile Include="Extensions\ObservableExtension.cs" /> <Compile Include="Extensions\ObservableExtension.cs" />
<Compile Include="GlobalSettings.cs" /> <Compile Include="GlobalSettings.cs" />
<Compile Include="Helpers\EasingHelper.cs" /> <Compile Include="Helpers\EasingHelper.cs" />
<Compile Include="Helpers\RandomNumberGenerator.cs" />
<Compile Include="Helpers\ServicesHelper.cs" /> <Compile Include="Helpers\ServicesHelper.cs" />
<Compile Include="Helpers\Settings.cs" /> <Compile Include="Helpers\Settings.cs" />
<Compile Include="Models\Basket\BasketCheckout.cs" /> <Compile Include="Models\Basket\BasketCheckout.cs" />


+ 1
- 0
src/Mobile/eShopOnContainers/eShopOnContainers.Core/project.json View File

@ -8,6 +8,7 @@
"Microsoft.Net.Http": "2.2.29", "Microsoft.Net.Http": "2.2.29",
"modernhttpclient": "2.4.2", "modernhttpclient": "2.4.2",
"Newtonsoft.Json": "9.0.1", "Newtonsoft.Json": "9.0.1",
"PCLCrypto": "2.0.147",
"SlideOverKit": "2.1.4", "SlideOverKit": "2.1.4",
"Splat": "1.6.2", "Splat": "1.6.2",
"System.ComponentModel.Annotations": "4.3.0", "System.ComponentModel.Annotations": "4.3.0",


+ 18
- 0
src/Mobile/eShopOnContainers/eShopOnContainers.Droid/eShopOnContainers.Droid.csproj View File

@ -100,6 +100,21 @@
<HintPath>..\..\..\..\packages\modernhttpclient.2.4.2\lib\MonoAndroid\OkHttp.dll</HintPath> <HintPath>..\..\..\..\packages\modernhttpclient.2.4.2\lib\MonoAndroid\OkHttp.dll</HintPath>
<Private>True</Private> <Private>True</Private>
</Reference> </Reference>
<Reference Include="PCLCrypto, Version=2.0.0.0, Culture=neutral, PublicKeyToken=d4421c8a4786956c, processorArchitecture=MSIL">
<HintPath>..\..\..\..\packages\PCLCrypto.2.0.147\lib\MonoAndroid23\PCLCrypto.dll</HintPath>
</Reference>
<Reference Include="PInvoke.BCrypt, Version=0.3.0.0, Culture=neutral, PublicKeyToken=9e300f9f87f04a7a, processorArchitecture=MSIL">
<HintPath>..\..\..\..\packages\PInvoke.BCrypt.0.3.2\lib\portable-net45+win+wpa81+MonoAndroid10+xamarinios10+MonoTouch10\PInvoke.BCrypt.dll</HintPath>
</Reference>
<Reference Include="PInvoke.Kernel32, Version=0.3.0.0, Culture=neutral, PublicKeyToken=9e300f9f87f04a7a, processorArchitecture=MSIL">
<HintPath>..\..\..\..\packages\PInvoke.Kernel32.0.3.2\lib\portable-net45+win+wpa81+MonoAndroid10+xamarinios10+MonoTouch10\PInvoke.Kernel32.dll</HintPath>
</Reference>
<Reference Include="PInvoke.NCrypt, Version=0.3.0.0, Culture=neutral, PublicKeyToken=9e300f9f87f04a7a, processorArchitecture=MSIL">
<HintPath>..\..\..\..\packages\PInvoke.NCrypt.0.3.2\lib\portable-net45+win+wpa81+MonoAndroid10+xamarinios10+MonoTouch10\PInvoke.NCrypt.dll</HintPath>
</Reference>
<Reference Include="PInvoke.Windows.Core, Version=0.3.0.0, Culture=neutral, PublicKeyToken=9e300f9f87f04a7a, processorArchitecture=MSIL">
<HintPath>..\..\..\..\packages\PInvoke.Windows.Core.0.3.2\lib\portable-net45+win+wpa81+MonoAndroid10+xamarinios10+MonoTouch10\PInvoke.Windows.Core.dll</HintPath>
</Reference>
<Reference Include="Plugin.CurrentActivity, Version=1.0.1.0, Culture=neutral, processorArchitecture=MSIL"> <Reference Include="Plugin.CurrentActivity, Version=1.0.1.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\..\..\..\packages\Plugin.CurrentActivity.1.0.1\lib\MonoAndroid10\Plugin.CurrentActivity.dll</HintPath> <HintPath>..\..\..\..\packages\Plugin.CurrentActivity.1.0.1\lib\MonoAndroid10\Plugin.CurrentActivity.dll</HintPath>
</Reference> </Reference>
@ -149,6 +164,9 @@
<Reference Include="System.ObjectModel" /> <Reference Include="System.ObjectModel" />
<Reference Include="System.Xml.Linq" /> <Reference Include="System.Xml.Linq" />
<Reference Include="System.Xml" /> <Reference Include="System.Xml" />
<Reference Include="Validation, Version=2.2.0.0, Culture=neutral, PublicKeyToken=2fc06f0d701809a7, processorArchitecture=MSIL">
<HintPath>..\..\..\..\packages\Validation.2.2.8\lib\dotnet\Validation.dll</HintPath>
</Reference>
<Reference Include="Xamarin.Android.Support.Animated.Vector.Drawable, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL"> <Reference Include="Xamarin.Android.Support.Animated.Vector.Drawable, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\..\..\..\packages\Xamarin.Android.Support.Animated.Vector.Drawable.23.3.0\lib\MonoAndroid403\Xamarin.Android.Support.Animated.Vector.Drawable.dll</HintPath> <HintPath>..\..\..\..\packages\Xamarin.Android.Support.Animated.Vector.Drawable.23.3.0\lib\MonoAndroid403\Xamarin.Android.Support.Animated.Vector.Drawable.dll</HintPath>
<Private>True</Private> <Private>True</Private>


+ 6
- 0
src/Mobile/eShopOnContainers/eShopOnContainers.Droid/packages.config View File

@ -14,6 +14,11 @@
<package id="modernhttpclient" version="2.4.2" targetFramework="monoandroid70" /> <package id="modernhttpclient" version="2.4.2" targetFramework="monoandroid70" />
<package id="NETStandard.Library" version="1.6.0" targetFramework="monoandroid60" /> <package id="NETStandard.Library" version="1.6.0" targetFramework="monoandroid60" />
<package id="Newtonsoft.Json" version="9.0.1" targetFramework="monoandroid60" /> <package id="Newtonsoft.Json" version="9.0.1" targetFramework="monoandroid60" />
<package id="PCLCrypto" version="2.0.147" targetFramework="monoandroid60" />
<package id="PInvoke.BCrypt" version="0.3.2" targetFramework="monoandroid60" />
<package id="PInvoke.Kernel32" version="0.3.2" targetFramework="monoandroid60" />
<package id="PInvoke.NCrypt" version="0.3.2" targetFramework="monoandroid60" />
<package id="PInvoke.Windows.Core" version="0.3.2" targetFramework="monoandroid60" />
<package id="Plugin.CurrentActivity" version="1.0.1" targetFramework="monoandroid60" /> <package id="Plugin.CurrentActivity" version="1.0.1" targetFramework="monoandroid60" />
<package id="Plugin.Permissions" version="1.1.7" targetFramework="monoandroid60" /> <package id="Plugin.Permissions" version="1.1.7" targetFramework="monoandroid60" />
<package id="SlideOverKit" version="2.1.4" targetFramework="monoandroid70" /> <package id="SlideOverKit" version="2.1.4" targetFramework="monoandroid70" />
@ -63,6 +68,7 @@
<package id="System.Threading.Timer" version="4.0.1" targetFramework="monoandroid60" /> <package id="System.Threading.Timer" version="4.0.1" targetFramework="monoandroid60" />
<package id="System.Xml.ReaderWriter" version="4.0.11" targetFramework="monoandroid70" /> <package id="System.Xml.ReaderWriter" version="4.0.11" targetFramework="monoandroid70" />
<package id="System.Xml.XDocument" version="4.0.11" targetFramework="monoandroid70" /> <package id="System.Xml.XDocument" version="4.0.11" targetFramework="monoandroid70" />
<package id="Validation" version="2.2.8" targetFramework="monoandroid60" />
<package id="Xam.Plugin.Geolocator" version="3.0.4" targetFramework="monoandroid60" /> <package id="Xam.Plugin.Geolocator" version="3.0.4" targetFramework="monoandroid60" />
<package id="Xam.Plugins.Settings" version="2.6.0.12-beta" targetFramework="monoandroid70" /> <package id="Xam.Plugins.Settings" version="2.6.0.12-beta" targetFramework="monoandroid70" />
<package id="Xamarin.Android.Support.Animated.Vector.Drawable" version="23.3.0" targetFramework="monoandroid70" /> <package id="Xamarin.Android.Support.Animated.Vector.Drawable" version="23.3.0" targetFramework="monoandroid70" />


+ 2
- 0
src/Mobile/eShopOnContainers/eShopOnContainers.TestRunner.Droid/Resources/Resource.Designer.cs View File

@ -64,6 +64,8 @@ namespace eShopOnContainers.TestRunner.Droid
global::AndroidHUD.Resource.Styleable.ProgressWheel_ahTextColor = global::eShopOnContainers.TestRunner.Droid.Resource.Styleable.ProgressWheel_ahTextColor; global::AndroidHUD.Resource.Styleable.ProgressWheel_ahTextColor = global::eShopOnContainers.TestRunner.Droid.Resource.Styleable.ProgressWheel_ahTextColor;
global::AndroidHUD.Resource.Styleable.ProgressWheel_ahTextSize = global::eShopOnContainers.TestRunner.Droid.Resource.Styleable.ProgressWheel_ahTextSize; global::AndroidHUD.Resource.Styleable.ProgressWheel_ahTextSize = global::eShopOnContainers.TestRunner.Droid.Resource.Styleable.ProgressWheel_ahTextSize;
global::ModernHttpClient.Resource.String.library_name = global::eShopOnContainers.TestRunner.Droid.Resource.String.library_name; global::ModernHttpClient.Resource.String.library_name = global::eShopOnContainers.TestRunner.Droid.Resource.String.library_name;
global::PCLCrypto.Resource.String.ApplicationName = global::eShopOnContainers.TestRunner.Droid.Resource.String.ApplicationName;
global::PCLCrypto.Resource.String.Hello = global::eShopOnContainers.TestRunner.Droid.Resource.String.Hello;
global::Splat.Resource.String.library_name = global::eShopOnContainers.TestRunner.Droid.Resource.String.library_name; global::Splat.Resource.String.library_name = global::eShopOnContainers.TestRunner.Droid.Resource.String.library_name;
global::Xamarin.Forms.Platform.Android.Resource.Attribute.actionBarSize = global::eShopOnContainers.TestRunner.Droid.Resource.Attribute.actionBarSize; global::Xamarin.Forms.Platform.Android.Resource.Attribute.actionBarSize = global::eShopOnContainers.TestRunner.Droid.Resource.Attribute.actionBarSize;
} }


+ 18
- 0
src/Mobile/eShopOnContainers/eShopOnContainers.TestRunner.Droid/eShopOnContainers.TestRunner.Droid.csproj View File

@ -51,6 +51,21 @@
</Reference> </Reference>
<Reference Include="Mono.Android" /> <Reference Include="Mono.Android" />
<Reference Include="mscorlib" /> <Reference Include="mscorlib" />
<Reference Include="PCLCrypto, Version=2.0.0.0, Culture=neutral, PublicKeyToken=d4421c8a4786956c, processorArchitecture=MSIL">
<HintPath>..\..\..\..\packages\PCLCrypto.2.0.147\lib\MonoAndroid23\PCLCrypto.dll</HintPath>
</Reference>
<Reference Include="PInvoke.BCrypt, Version=0.3.0.0, Culture=neutral, PublicKeyToken=9e300f9f87f04a7a, processorArchitecture=MSIL">
<HintPath>..\..\..\..\packages\PInvoke.BCrypt.0.3.2\lib\portable-net45+win+wpa81+MonoAndroid10+xamarinios10+MonoTouch10\PInvoke.BCrypt.dll</HintPath>
</Reference>
<Reference Include="PInvoke.Kernel32, Version=0.3.0.0, Culture=neutral, PublicKeyToken=9e300f9f87f04a7a, processorArchitecture=MSIL">
<HintPath>..\..\..\..\packages\PInvoke.Kernel32.0.3.2\lib\portable-net45+win+wpa81+MonoAndroid10+xamarinios10+MonoTouch10\PInvoke.Kernel32.dll</HintPath>
</Reference>
<Reference Include="PInvoke.NCrypt, Version=0.3.0.0, Culture=neutral, PublicKeyToken=9e300f9f87f04a7a, processorArchitecture=MSIL">
<HintPath>..\..\..\..\packages\PInvoke.NCrypt.0.3.2\lib\portable-net45+win+wpa81+MonoAndroid10+xamarinios10+MonoTouch10\PInvoke.NCrypt.dll</HintPath>
</Reference>
<Reference Include="PInvoke.Windows.Core, Version=0.3.0.0, Culture=neutral, PublicKeyToken=9e300f9f87f04a7a, processorArchitecture=MSIL">
<HintPath>..\..\..\..\packages\PInvoke.Windows.Core.0.3.2\lib\portable-net45+win+wpa81+MonoAndroid10+xamarinios10+MonoTouch10\PInvoke.Windows.Core.dll</HintPath>
</Reference>
<Reference Include="Plugin.CurrentActivity, Version=1.0.1.0, Culture=neutral, processorArchitecture=MSIL"> <Reference Include="Plugin.CurrentActivity, Version=1.0.1.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\..\..\..\packages\Plugin.CurrentActivity.1.0.1\lib\MonoAndroid10\Plugin.CurrentActivity.dll</HintPath> <HintPath>..\..\..\..\packages\Plugin.CurrentActivity.1.0.1\lib\MonoAndroid10\Plugin.CurrentActivity.dll</HintPath>
</Reference> </Reference>
@ -76,6 +91,9 @@
</Reference> </Reference>
<Reference Include="System.Xml.Linq" /> <Reference Include="System.Xml.Linq" />
<Reference Include="System.Xml" /> <Reference Include="System.Xml" />
<Reference Include="Validation, Version=2.2.0.0, Culture=neutral, PublicKeyToken=2fc06f0d701809a7, processorArchitecture=MSIL">
<HintPath>..\..\..\..\packages\Validation.2.2.8\lib\dotnet\Validation.dll</HintPath>
</Reference>
<Reference Include="Xamarin.Android.Support.Animated.Vector.Drawable, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL"> <Reference Include="Xamarin.Android.Support.Animated.Vector.Drawable, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\..\..\..\packages\Xamarin.Android.Support.Animated.Vector.Drawable.23.3.0\lib\MonoAndroid403\Xamarin.Android.Support.Animated.Vector.Drawable.dll</HintPath> <HintPath>..\..\..\..\packages\Xamarin.Android.Support.Animated.Vector.Drawable.23.3.0\lib\MonoAndroid403\Xamarin.Android.Support.Animated.Vector.Drawable.dll</HintPath>
<Private>True</Private> <Private>True</Private>


+ 6
- 0
src/Mobile/eShopOnContainers/eShopOnContainers.TestRunner.Droid/packages.config View File

@ -13,6 +13,11 @@
<package id="modernhttpclient" version="2.4.2" targetFramework="monoandroid60" /> <package id="modernhttpclient" version="2.4.2" targetFramework="monoandroid60" />
<package id="NETStandard.Library" version="1.6.0" targetFramework="monoandroid60" /> <package id="NETStandard.Library" version="1.6.0" targetFramework="monoandroid60" />
<package id="Newtonsoft.Json" version="9.0.1" targetFramework="monoandroid60" /> <package id="Newtonsoft.Json" version="9.0.1" targetFramework="monoandroid60" />
<package id="PCLCrypto" version="2.0.147" targetFramework="monoandroid60" />
<package id="PInvoke.BCrypt" version="0.3.2" targetFramework="monoandroid60" />
<package id="PInvoke.Kernel32" version="0.3.2" targetFramework="monoandroid60" />
<package id="PInvoke.NCrypt" version="0.3.2" targetFramework="monoandroid60" />
<package id="PInvoke.Windows.Core" version="0.3.2" targetFramework="monoandroid60" />
<package id="Plugin.CurrentActivity" version="1.0.1" targetFramework="monoandroid60" /> <package id="Plugin.CurrentActivity" version="1.0.1" targetFramework="monoandroid60" />
<package id="Plugin.Permissions" version="1.1.7" targetFramework="monoandroid60" /> <package id="Plugin.Permissions" version="1.1.7" targetFramework="monoandroid60" />
<package id="SlideOverKit" version="2.1.4" targetFramework="monoandroid60" /> <package id="SlideOverKit" version="2.1.4" targetFramework="monoandroid60" />
@ -60,6 +65,7 @@
<package id="System.Threading.Timer" version="4.0.1" targetFramework="monoandroid60" /> <package id="System.Threading.Timer" version="4.0.1" targetFramework="monoandroid60" />
<package id="System.Xml.ReaderWriter" version="4.0.11" targetFramework="monoandroid60" /> <package id="System.Xml.ReaderWriter" version="4.0.11" targetFramework="monoandroid60" />
<package id="System.Xml.XDocument" version="4.0.11" targetFramework="monoandroid60" /> <package id="System.Xml.XDocument" version="4.0.11" targetFramework="monoandroid60" />
<package id="Validation" version="2.2.8" targetFramework="monoandroid60" />
<package id="Xam.Plugin.Geolocator" version="3.0.4" targetFramework="monoandroid60" /> <package id="Xam.Plugin.Geolocator" version="3.0.4" targetFramework="monoandroid60" />
<package id="Xam.Plugins.Settings" version="2.6.0.12-beta" targetFramework="monoandroid60" /> <package id="Xam.Plugins.Settings" version="2.6.0.12-beta" targetFramework="monoandroid60" />
<package id="Xamarin.Android.Support.Animated.Vector.Drawable" version="23.3.0" targetFramework="monoandroid70" /> <package id="Xamarin.Android.Support.Animated.Vector.Drawable" version="23.3.0" targetFramework="monoandroid70" />


+ 22
- 2
src/Mobile/eShopOnContainers/eShopOnContainers.TestRunner.iOS/eShopOnContainers.TestRunner.iOS.csproj View File

@ -24,7 +24,8 @@
<MtouchArch>x86_64</MtouchArch> <MtouchArch>x86_64</MtouchArch>
<MtouchLink>None</MtouchLink> <MtouchLink>None</MtouchLink>
<MtouchDebug>True</MtouchDebug> <MtouchDebug>True</MtouchDebug>
<MtouchSdkVersion></MtouchSdkVersion>
<MtouchSdkVersion>
</MtouchSdkVersion>
<MtouchProfiling>False</MtouchProfiling> <MtouchProfiling>False</MtouchProfiling>
<MtouchFastDev>False</MtouchFastDev> <MtouchFastDev>False</MtouchFastDev>
<MtouchUseLlvm>False</MtouchUseLlvm> <MtouchUseLlvm>False</MtouchUseLlvm>
@ -58,7 +59,8 @@
<CodesignEntitlements>Entitlements.plist</CodesignEntitlements> <CodesignEntitlements>Entitlements.plist</CodesignEntitlements>
<CodesignKey>iPhone Developer</CodesignKey> <CodesignKey>iPhone Developer</CodesignKey>
<MtouchDebug>true</MtouchDebug> <MtouchDebug>true</MtouchDebug>
<MtouchSdkVersion></MtouchSdkVersion>
<MtouchSdkVersion>
</MtouchSdkVersion>
<MtouchLink>None</MtouchLink> <MtouchLink>None</MtouchLink>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|iPhone' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|iPhone' ">
@ -107,6 +109,21 @@
<None Include="packages.config" /> <None Include="packages.config" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Reference Include="PCLCrypto, Version=2.0.0.0, Culture=neutral, PublicKeyToken=d4421c8a4786956c, processorArchitecture=MSIL">
<HintPath>..\..\..\..\packages\PCLCrypto.2.0.147\lib\xamarinios10\PCLCrypto.dll</HintPath>
</Reference>
<Reference Include="PInvoke.BCrypt, Version=0.3.0.0, Culture=neutral, PublicKeyToken=9e300f9f87f04a7a, processorArchitecture=MSIL">
<HintPath>..\..\..\..\packages\PInvoke.BCrypt.0.3.2\lib\portable-net45+win+wpa81+MonoAndroid10+xamarinios10+MonoTouch10\PInvoke.BCrypt.dll</HintPath>
</Reference>
<Reference Include="PInvoke.Kernel32, Version=0.3.0.0, Culture=neutral, PublicKeyToken=9e300f9f87f04a7a, processorArchitecture=MSIL">
<HintPath>..\..\..\..\packages\PInvoke.Kernel32.0.3.2\lib\portable-net45+win+wpa81+MonoAndroid10+xamarinios10+MonoTouch10\PInvoke.Kernel32.dll</HintPath>
</Reference>
<Reference Include="PInvoke.NCrypt, Version=0.3.0.0, Culture=neutral, PublicKeyToken=9e300f9f87f04a7a, processorArchitecture=MSIL">
<HintPath>..\..\..\..\packages\PInvoke.NCrypt.0.3.2\lib\portable-net45+win+wpa81+MonoAndroid10+xamarinios10+MonoTouch10\PInvoke.NCrypt.dll</HintPath>
</Reference>
<Reference Include="PInvoke.Windows.Core, Version=0.3.0.0, Culture=neutral, PublicKeyToken=9e300f9f87f04a7a, processorArchitecture=MSIL">
<HintPath>..\..\..\..\packages\PInvoke.Windows.Core.0.3.2\lib\portable-net45+win+wpa81+MonoAndroid10+xamarinios10+MonoTouch10\PInvoke.Windows.Core.dll</HintPath>
</Reference>
<Reference Include="System" /> <Reference Include="System" />
<Reference Include="System.Net.Http.Extensions, Version=2.2.29.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> <Reference Include="System.Net.Http.Extensions, Version=2.2.29.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\..\..\..\packages\Microsoft.Net.Http.2.2.29\lib\Xamarin.iOS10\System.Net.Http.Extensions.dll</HintPath> <HintPath>..\..\..\..\packages\Microsoft.Net.Http.2.2.29\lib\Xamarin.iOS10\System.Net.Http.Extensions.dll</HintPath>
@ -116,6 +133,9 @@
</Reference> </Reference>
<Reference Include="System.Xml" /> <Reference Include="System.Xml" />
<Reference Include="System.Core" /> <Reference Include="System.Core" />
<Reference Include="Validation, Version=2.2.0.0, Culture=neutral, PublicKeyToken=2fc06f0d701809a7, processorArchitecture=MSIL">
<HintPath>..\..\..\..\packages\Validation.2.2.8\lib\dotnet\Validation.dll</HintPath>
</Reference>
<Reference Include="Xamarin.Forms.Core, Version=2.0.0.0, Culture=neutral, processorArchitecture=MSIL"> <Reference Include="Xamarin.Forms.Core, Version=2.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\..\..\..\packages\Xamarin.Forms.2.3.4.231\lib\Xamarin.iOS10\Xamarin.Forms.Core.dll</HintPath> <HintPath>..\..\..\..\packages\Xamarin.Forms.2.3.4.231\lib\Xamarin.iOS10\Xamarin.Forms.Core.dll</HintPath>
</Reference> </Reference>


+ 6
- 0
src/Mobile/eShopOnContainers/eShopOnContainers.TestRunner.iOS/packages.config View File

@ -12,6 +12,11 @@
<package id="modernhttpclient" version="2.4.2" targetFramework="xamarinios10" /> <package id="modernhttpclient" version="2.4.2" targetFramework="xamarinios10" />
<package id="NETStandard.Library" version="1.6.0" targetFramework="xamarinios10" /> <package id="NETStandard.Library" version="1.6.0" targetFramework="xamarinios10" />
<package id="Newtonsoft.Json" version="9.0.1" targetFramework="xamarinios10" /> <package id="Newtonsoft.Json" version="9.0.1" targetFramework="xamarinios10" />
<package id="PCLCrypto" version="2.0.147" targetFramework="xamarinios10" />
<package id="PInvoke.BCrypt" version="0.3.2" targetFramework="xamarinios10" />
<package id="PInvoke.Kernel32" version="0.3.2" targetFramework="xamarinios10" />
<package id="PInvoke.NCrypt" version="0.3.2" targetFramework="xamarinios10" />
<package id="PInvoke.Windows.Core" version="0.3.2" targetFramework="xamarinios10" />
<package id="SlideOverKit" version="2.1.4" targetFramework="xamarinios10" /> <package id="SlideOverKit" version="2.1.4" targetFramework="xamarinios10" />
<package id="Splat" version="1.6.2" targetFramework="xamarinios10" /> <package id="Splat" version="1.6.2" targetFramework="xamarinios10" />
<package id="System.AppContext" version="4.1.0" targetFramework="xamarinios10" /> <package id="System.AppContext" version="4.1.0" targetFramework="xamarinios10" />
@ -57,6 +62,7 @@
<package id="System.Threading.Timer" version="4.0.1" targetFramework="xamarinios10" /> <package id="System.Threading.Timer" version="4.0.1" targetFramework="xamarinios10" />
<package id="System.Xml.ReaderWriter" version="4.0.11" targetFramework="xamarinios10" /> <package id="System.Xml.ReaderWriter" version="4.0.11" targetFramework="xamarinios10" />
<package id="System.Xml.XDocument" version="4.0.11" targetFramework="xamarinios10" /> <package id="System.Xml.XDocument" version="4.0.11" targetFramework="xamarinios10" />
<package id="Validation" version="2.2.8" targetFramework="xamarinios10" />
<package id="WebP.Touch" version="1.0.3" targetFramework="xamarinios10" /> <package id="WebP.Touch" version="1.0.3" targetFramework="xamarinios10" />
<package id="Xam.Plugin.Geolocator" version="3.0.4" targetFramework="xamarinios10" /> <package id="Xam.Plugin.Geolocator" version="3.0.4" targetFramework="xamarinios10" />
<package id="Xam.Plugins.Settings" version="2.6.0.12-beta" targetFramework="xamarinios10" /> <package id="Xam.Plugins.Settings" version="2.6.0.12-beta" targetFramework="xamarinios10" />


+ 1
- 0
src/Mobile/eShopOnContainers/eShopOnContainers.Windows/project.json View File

@ -4,6 +4,7 @@
"IdentityModel": "1.3.1", "IdentityModel": "1.3.1",
"Microsoft.NETCore.UniversalWindowsPlatform": "5.3.3", "Microsoft.NETCore.UniversalWindowsPlatform": "5.3.3",
"Newtonsoft.Json": "9.0.1", "Newtonsoft.Json": "9.0.1",
"PCLCrypto": "2.0.147",
"SlideOverKit": "2.1.4", "SlideOverKit": "2.1.4",
"Xam.Plugin.Geolocator": "3.0.4", "Xam.Plugin.Geolocator": "3.0.4",
"Xam.Plugins.Settings": "2.6.0.12-beta", "Xam.Plugins.Settings": "2.6.0.12-beta",


+ 20
- 1
src/Mobile/eShopOnContainers/eShopOnContainers.iOS/eShopOnContainers.iOS.csproj View File

@ -27,7 +27,8 @@
<MtouchArch>i386, x86_64</MtouchArch> <MtouchArch>i386, x86_64</MtouchArch>
<MtouchLink>None</MtouchLink> <MtouchLink>None</MtouchLink>
<MtouchDebug>True</MtouchDebug> <MtouchDebug>True</MtouchDebug>
<MtouchSdkVersion></MtouchSdkVersion>
<MtouchSdkVersion>
</MtouchSdkVersion>
<MtouchProfiling>False</MtouchProfiling> <MtouchProfiling>False</MtouchProfiling>
<MtouchFastDev>False</MtouchFastDev> <MtouchFastDev>False</MtouchFastDev>
<MtouchUseLlvm>False</MtouchUseLlvm> <MtouchUseLlvm>False</MtouchUseLlvm>
@ -166,6 +167,21 @@
<HintPath>..\..\..\..\packages\Newtonsoft.Json.9.0.1\lib\portable-net45+wp80+win8+wpa81\Newtonsoft.Json.dll</HintPath> <HintPath>..\..\..\..\packages\Newtonsoft.Json.9.0.1\lib\portable-net45+wp80+win8+wpa81\Newtonsoft.Json.dll</HintPath>
<Private>True</Private> <Private>True</Private>
</Reference> </Reference>
<Reference Include="PCLCrypto, Version=2.0.0.0, Culture=neutral, PublicKeyToken=d4421c8a4786956c, processorArchitecture=MSIL">
<HintPath>..\..\..\..\packages\PCLCrypto.2.0.147\lib\xamarinios10\PCLCrypto.dll</HintPath>
</Reference>
<Reference Include="PInvoke.BCrypt, Version=0.3.0.0, Culture=neutral, PublicKeyToken=9e300f9f87f04a7a, processorArchitecture=MSIL">
<HintPath>..\..\..\..\packages\PInvoke.BCrypt.0.3.2\lib\portable-net45+win+wpa81+MonoAndroid10+xamarinios10+MonoTouch10\PInvoke.BCrypt.dll</HintPath>
</Reference>
<Reference Include="PInvoke.Kernel32, Version=0.3.0.0, Culture=neutral, PublicKeyToken=9e300f9f87f04a7a, processorArchitecture=MSIL">
<HintPath>..\..\..\..\packages\PInvoke.Kernel32.0.3.2\lib\portable-net45+win+wpa81+MonoAndroid10+xamarinios10+MonoTouch10\PInvoke.Kernel32.dll</HintPath>
</Reference>
<Reference Include="PInvoke.NCrypt, Version=0.3.0.0, Culture=neutral, PublicKeyToken=9e300f9f87f04a7a, processorArchitecture=MSIL">
<HintPath>..\..\..\..\packages\PInvoke.NCrypt.0.3.2\lib\portable-net45+win+wpa81+MonoAndroid10+xamarinios10+MonoTouch10\PInvoke.NCrypt.dll</HintPath>
</Reference>
<Reference Include="PInvoke.Windows.Core, Version=0.3.0.0, Culture=neutral, PublicKeyToken=9e300f9f87f04a7a, processorArchitecture=MSIL">
<HintPath>..\..\..\..\packages\PInvoke.Windows.Core.0.3.2\lib\portable-net45+win+wpa81+MonoAndroid10+xamarinios10+MonoTouch10\PInvoke.Windows.Core.dll</HintPath>
</Reference>
<Reference Include="Plugin.Settings, Version=2.6.0.12, Culture=neutral, processorArchitecture=MSIL"> <Reference Include="Plugin.Settings, Version=2.6.0.12, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\..\..\..\packages\Xam.Plugins.Settings.2.6.0.12-beta\lib\Xamarin.iOS10\Plugin.Settings.dll</HintPath> <HintPath>..\..\..\..\packages\Xam.Plugins.Settings.2.6.0.12-beta\lib\Xamarin.iOS10\Plugin.Settings.dll</HintPath>
<Private>True</Private> <Private>True</Private>
@ -197,6 +213,9 @@
</Reference> </Reference>
<Reference Include="System.Xml" /> <Reference Include="System.Xml" />
<Reference Include="System.Core" /> <Reference Include="System.Core" />
<Reference Include="Validation, Version=2.2.0.0, Culture=neutral, PublicKeyToken=2fc06f0d701809a7, processorArchitecture=MSIL">
<HintPath>..\..\..\..\packages\Validation.2.2.8\lib\dotnet\Validation.dll</HintPath>
</Reference>
<Reference Include="WebP.Touch, Version=1.0.6230.37678, Culture=neutral, processorArchitecture=MSIL"> <Reference Include="WebP.Touch, Version=1.0.6230.37678, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\..\..\..\packages\WebP.Touch.1.0.3\lib\Xamarin.iOS10\WebP.Touch.dll</HintPath> <HintPath>..\..\..\..\packages\WebP.Touch.1.0.3\lib\Xamarin.iOS10\WebP.Touch.dll</HintPath>
</Reference> </Reference>


+ 6
- 0
src/Mobile/eShopOnContainers/eShopOnContainers.iOS/packages.config View File

@ -12,6 +12,11 @@
<package id="modernhttpclient" version="2.4.2" targetFramework="xamarinios10" /> <package id="modernhttpclient" version="2.4.2" targetFramework="xamarinios10" />
<package id="NETStandard.Library" version="1.6.0" targetFramework="xamarinios10" /> <package id="NETStandard.Library" version="1.6.0" targetFramework="xamarinios10" />
<package id="Newtonsoft.Json" version="9.0.1" targetFramework="xamarinios10" /> <package id="Newtonsoft.Json" version="9.0.1" targetFramework="xamarinios10" />
<package id="PCLCrypto" version="2.0.147" targetFramework="xamarinios10" />
<package id="PInvoke.BCrypt" version="0.3.2" targetFramework="xamarinios10" />
<package id="PInvoke.Kernel32" version="0.3.2" targetFramework="xamarinios10" />
<package id="PInvoke.NCrypt" version="0.3.2" targetFramework="xamarinios10" />
<package id="PInvoke.Windows.Core" version="0.3.2" targetFramework="xamarinios10" />
<package id="SlideOverKit" version="2.1.4" targetFramework="xamarinios10" /> <package id="SlideOverKit" version="2.1.4" targetFramework="xamarinios10" />
<package id="Splat" version="1.6.2" targetFramework="xamarinios10" /> <package id="Splat" version="1.6.2" targetFramework="xamarinios10" />
<package id="System.AppContext" version="4.1.0" targetFramework="xamarinios10" /> <package id="System.AppContext" version="4.1.0" targetFramework="xamarinios10" />
@ -57,6 +62,7 @@
<package id="System.Threading.Timer" version="4.0.1" targetFramework="xamarinios10" /> <package id="System.Threading.Timer" version="4.0.1" targetFramework="xamarinios10" />
<package id="System.Xml.ReaderWriter" version="4.0.11" targetFramework="xamarinios10" /> <package id="System.Xml.ReaderWriter" version="4.0.11" targetFramework="xamarinios10" />
<package id="System.Xml.XDocument" version="4.0.11" targetFramework="xamarinios10" /> <package id="System.Xml.XDocument" version="4.0.11" targetFramework="xamarinios10" />
<package id="Validation" version="2.2.8" targetFramework="xamarinios10" />
<package id="WebP.Touch" version="1.0.3" targetFramework="xamarinios10" /> <package id="WebP.Touch" version="1.0.3" targetFramework="xamarinios10" />
<package id="Xam.Plugin.Geolocator" version="3.0.4" targetFramework="xamarinios10" /> <package id="Xam.Plugin.Geolocator" version="3.0.4" targetFramework="xamarinios10" />
<package id="Xam.Plugins.Settings" version="2.6.0.12-beta" targetFramework="xamarinios10" /> <package id="Xam.Plugins.Settings" version="2.6.0.12-beta" targetFramework="xamarinios10" />


BIN
src/Services/Catalog/Catalog.API/Setup/Catalogitems.zip → src/Services/Catalog/Catalog.API/Setup/CatalogItems.zip View File


+ 8
- 0
src/Services/GracePeriod/GracePeriodManager/Dockerfile.nanowin View File

@ -0,0 +1,8 @@
FROM microsoft/dotnet:1.1-runtime-nanoserver
SHELL ["powershell"]
ARG source
WORKDIR /app
RUN set-itemproperty -path 'HKLM:\SYSTEM\CurrentControlSet\Services\Dnscache\Parameters' -Name ServerPriorityTimeLimit -Value 0 -Type DWord
EXPOSE 80
COPY ${source:-obj/Docker/publish} .
ENTRYPOINT ["dotnet", "Basket.API.dll"]

+ 1
- 0
src/Services/Identity/Identity.API/Configuration/Config.cs View File

@ -67,6 +67,7 @@ namespace Identity.API.Configuration
}, },
RedirectUris = { clientsUrl["Xamarin"] }, RedirectUris = { clientsUrl["Xamarin"] },
RequireConsent = false, RequireConsent = false,
RequirePkce = true,
PostLogoutRedirectUris = { $"{clientsUrl["Xamarin"]}/Account/Redirecting" }, PostLogoutRedirectUris = { $"{clientsUrl["Xamarin"]}/Account/Redirecting" },
AllowedCorsOrigins = { "http://eshopxamarin" }, AllowedCorsOrigins = { "http://eshopxamarin" },
AllowedScopes = new List<string> AllowedScopes = new List<string>


+ 8
- 0
src/Services/Location/Locations.API/Dockerfile.nanowin View File

@ -0,0 +1,8 @@
FROM microsoft/dotnet:1.1-runtime-nanoserver
SHELL ["powershell"]
ARG source
WORKDIR /app
RUN set-itemproperty -path 'HKLM:\SYSTEM\CurrentControlSet\Services\Dnscache\Parameters' -Name ServerPriorityTimeLimit -Value 0 -Type DWord
EXPOSE 80
COPY ${source:-obj/Docker/publish} .
ENTRYPOINT ["dotnet", "Basket.API.dll"]

+ 8
- 0
src/Services/Marketing/Marketing.API/Dockerfile.nanowin View File

@ -0,0 +1,8 @@
FROM microsoft/dotnet:1.1-runtime-nanoserver
SHELL ["powershell"]
ARG source
WORKDIR /app
RUN set-itemproperty -path 'HKLM:\SYSTEM\CurrentControlSet\Services\Dnscache\Parameters' -Name ServerPriorityTimeLimit -Value 0 -Type DWord
EXPOSE 80
COPY ${source:-obj/Docker/publish} .
ENTRYPOINT ["dotnet", "Basket.API.dll"]

+ 23
- 0
src/Services/Ordering/Ordering.API/Application/Behaviors/LoggingBehavior.cs View File

@ -0,0 +1,23 @@
using MediatR;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Ordering.API.Infrastructure.Behaviors
{
public class LoggingBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>
{
private readonly ILogger<LoggingBehavior<TRequest, TResponse>> _logger;
public LoggingBehavior(ILogger<LoggingBehavior<TRequest, TResponse>> logger) => _logger = logger;
public async Task<TResponse> Handle(TRequest request, RequestHandlerDelegate<TResponse> next)
{
_logger.LogInformation($"Handling {typeof(TRequest).Name}");
var response = await next();
_logger.LogInformation($"Handled {typeof(TResponse).Name}");
return response;
}
}
}

src/Services/Ordering/Ordering.API/Application/Decorators/ValidatorDecorator.cs → src/Services/Ordering/Ordering.API/Application/Behaviors/ValidatorBehavior.cs View File

@ -1,33 +1,23 @@
using FluentValidation; using FluentValidation;
using MediatR; using MediatR;
using Microsoft.Extensions.Logging;
using Ordering.Domain.Exceptions; using Ordering.Domain.Exceptions;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace Ordering.API.Application.Decorators
namespace Ordering.API.Infrastructure.Behaviors
{ {
public class ValidatorDecorator<TRequest, TResponse>
: IAsyncRequestHandler<TRequest, TResponse>
where TRequest : IRequest<TResponse>
public class ValidatorBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>
{ {
private readonly IAsyncRequestHandler<TRequest, TResponse> _inner;
private readonly IValidator<TRequest>[] _validators; private readonly IValidator<TRequest>[] _validators;
public ValidatorBehavior(IValidator<TRequest>[] validators) => _validators = validators;
public ValidatorDecorator(
IAsyncRequestHandler<TRequest, TResponse> inner,
IValidator<TRequest>[] validators)
{
_inner = inner;
_validators = validators;
}
public async Task<TResponse> Handle(TRequest message)
public async Task<TResponse> Handle(TRequest request, RequestHandlerDelegate<TResponse> next)
{ {
var failures = _validators var failures = _validators
.Select(v => v.Validate(message))
.Select(v => v.Validate(request))
.SelectMany(result => result.Errors) .SelectMany(result => result.Errors)
.Where(error => error != null) .Where(error => error != null)
.ToList(); .ToList();
@ -37,9 +27,8 @@ namespace Ordering.API.Application.Decorators
throw new OrderingDomainException( throw new OrderingDomainException(
$"Command Validation Errors for type {typeof(TRequest).Name}", new ValidationException("Validation exception", failures)); $"Command Validation Errors for type {typeof(TRequest).Name}", new ValidationException("Validation exception", failures));
} }
var response = await _inner.Handle(message);
var response = await next();
return response; return response;
} }
} }

+ 0
- 34
src/Services/Ordering/Ordering.API/Application/Decorators/LogDecorator.cs View File

@ -1,34 +0,0 @@
namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.Decorators
{
using Extensions.Logging;
using MediatR;
using System.Threading.Tasks;
public class LogDecorator<TRequest, TResponse>
: IAsyncRequestHandler<TRequest, TResponse>
where TRequest : IRequest<TResponse>
{
private readonly IAsyncRequestHandler<TRequest, TResponse> _inner;
private readonly ILogger<LogDecorator<TRequest, TResponse>> _logger;
public LogDecorator(
IAsyncRequestHandler<TRequest, TResponse> inner,
ILogger<LogDecorator<TRequest, TResponse>> logger)
{
_inner = inner;
_logger = logger;
}
public async Task<TResponse> Handle(TRequest message)
{
_logger.LogInformation($"Executing command {_inner.GetType().FullName}");
var response = await _inner.Handle(message);
_logger.LogInformation($"Command executed successfully {_inner.GetType().FullName}");
return response;
}
}
}

+ 10
- 15
src/Services/Ordering/Ordering.API/Infrastructure/AutofacModules/MediatorModule.cs View File

@ -3,11 +3,9 @@ using Autofac.Core;
using FluentValidation; using FluentValidation;
using MediatR; using MediatR;
using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands; using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands;
using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Decorators;
using Ordering.API.Application.Decorators;
using Ordering.API.Application.DomainEventHandlers.OrderStartedEvent; using Ordering.API.Application.DomainEventHandlers.OrderStartedEvent;
using Ordering.API.Application.Validations; using Ordering.API.Application.Validations;
using Ordering.Domain.Events;
using Ordering.API.Infrastructure.Behaviors;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
@ -33,7 +31,7 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.API.Infrastructure.Autof
.Where(i => i.IsClosedTypeOf(typeof(IAsyncNotificationHandler<>))) .Where(i => i.IsClosedTypeOf(typeof(IAsyncNotificationHandler<>)))
.Select(i => new KeyedService("IAsyncNotificationHandler", i))) .Select(i => new KeyedService("IAsyncNotificationHandler", i)))
.AsImplementedInterfaces(); .AsImplementedInterfaces();
builder builder
.RegisterAssemblyTypes(typeof(CreateOrderCommandValidator).GetTypeInfo().Assembly) .RegisterAssemblyTypes(typeof(CreateOrderCommandValidator).GetTypeInfo().Assembly)
@ -45,25 +43,22 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.API.Infrastructure.Autof
{ {
var componentContext = context.Resolve<IComponentContext>(); var componentContext = context.Resolve<IComponentContext>();
return t => { object o; return componentContext.TryResolve(t, out o) ? o : null; }; return t => { object o; return componentContext.TryResolve(t, out o) ? o : null; };
});
});
builder.Register<MultiInstanceFactory>(context => builder.Register<MultiInstanceFactory>(context =>
{ {
var componentContext = context.Resolve<IComponentContext>(); var componentContext = context.Resolve<IComponentContext>();
return t => (IEnumerable<object>)componentContext.Resolve(typeof(IEnumerable<>).MakeGenericType(t));
return t =>
{
var resolved = (IEnumerable<object>)componentContext.Resolve(typeof(IEnumerable<>).MakeGenericType(t));
return resolved;
};
}); });
builder.RegisterGenericDecorator(typeof(LogDecorator<,>),
typeof(IAsyncRequestHandler<,>),
"IAsyncRequestHandler")
.Keyed("handlerDecorator", typeof(IAsyncRequestHandler<,>));
builder.RegisterGeneric(typeof(LoggingBehavior<,>)).As(typeof(IPipelineBehavior<,>));
builder.RegisterGeneric(typeof(ValidatorBehavior<,>)).As(typeof(IPipelineBehavior<,>));
builder.RegisterGenericDecorator(typeof(ValidatorDecorator<,>),
typeof(IAsyncRequestHandler<,>),
fromKey: "handlerDecorator");
} }
} }
} }

+ 8
- 0
src/Services/Payment/Payment.API/Dockerfile.nanowin View File

@ -0,0 +1,8 @@
FROM microsoft/dotnet:1.1-runtime-nanoserver
SHELL ["powershell"]
ARG source
WORKDIR /app
RUN set-itemproperty -path 'HKLM:\SYSTEM\CurrentControlSet\Services\Dnscache\Parameters' -Name ServerPriorityTimeLimit -Value 0 -Type DWord
EXPOSE 80
COPY ${source:-obj/Docker/publish} .
ENTRYPOINT ["dotnet", "Basket.API.dll"]

+ 2
- 0
src/Web/WebMVC/WebMVC.csproj View File

@ -22,9 +22,11 @@
<ItemGroup> <ItemGroup>
<Content Include="Setup\images.zip"> <Content Include="Setup\images.zip">
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory> <CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content> </Content>
<Content Include="Setup\override.css"> <Content Include="Setup\override.css">
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory> <CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content> </Content>
</ItemGroup> </ItemGroup>


+ 11322
- 3390
src/Web/WebSPA/package-lock.json
File diff suppressed because it is too large
View File


+ 3
- 3
src/Web/WebSPA/package.json View File

@ -46,12 +46,12 @@
"zone.js": "^0.8.4" "zone.js": "^0.8.4"
}, },
"devDependencies": { "devDependencies": {
"@angular/cli": "1.0.0",
"@angular/cli": "^1.3.0",
"@angular/compiler-cli": "^4.0.0", "@angular/compiler-cli": "^4.0.0",
"@types/jasmine": "2.5.38",
"@types/node": "~6.0.60",
"@types/core-js": "0.9.34", "@types/core-js": "0.9.34",
"@types/hammerjs": "2.0.33", "@types/hammerjs": "2.0.33",
"@types/jasmine": "2.5.38",
"@types/node": "~6.0.60",
"@types/protractor": "1.5.20", "@types/protractor": "1.5.20",
"@types/selenium-webdriver": "2.44.26", "@types/selenium-webdriver": "2.44.26",
"codelyzer": "~2.0.0", "codelyzer": "~2.0.0",


+ 8
- 0
src/Web/WebStatus/Dockerfile.nanowin View File

@ -0,0 +1,8 @@
FROM microsoft/dotnet:1.1-runtime-nanoserver
SHELL ["powershell"]
ARG source
WORKDIR /app
RUN set-itemproperty -path 'HKLM:\SYSTEM\CurrentControlSet\Services\Dnscache\Parameters' -Name ServerPriorityTimeLimit -Value 0 -Type DWord
EXPOSE 80
COPY ${source:-obj/Docker/publish} .
ENTRYPOINT ["dotnet", "WebMVC.dll"]

+ 0
- 5
src/Web/WebStatus/Views/Shared/_Layout.cshtml View File

@ -39,8 +39,6 @@
<div class="navbar-collapse collapse"> <div class="navbar-collapse collapse">
<ul class="nav navbar-nav"> <ul class="nav navbar-nav">
<li><a asp-area="" asp-controller="Home" asp-action="Index">Home</a></li> <li><a asp-area="" asp-controller="Home" asp-action="Index">Home</a></li>
<li><a asp-area="" asp-controller="Home" asp-action="About">About</a></li>
<li><a asp-area="" asp-controller="Home" asp-action="Contact">Contact</a></li>
</ul> </ul>
</div> </div>
</div> </div>
@ -72,9 +70,6 @@
crossorigin="anonymous" crossorigin="anonymous"
integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa"> integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa">
</script> </script>
<script src="~/js/site.min.js" asp-append-version="true"></script>
</environment> </environment>
@RenderSection("Scripts", required: false)
</body> </body>
</html> </html>

+ 0
- 18
src/Web/WebStatus/Views/Shared/_ValidationScriptsPartial.cshtml View File

@ -1,18 +0,0 @@
<environment names="Development">
<script src="~/lib/jquery-validation/dist/jquery.validate.js"></script>
<script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js"></script>
</environment>
<environment names="Staging,Production">
<script src="https://ajax.aspnetcdn.com/ajax/jquery.validate/1.14.0/jquery.validate.min.js"
asp-fallback-src="~/lib/jquery-validation/dist/jquery.validate.min.js"
asp-fallback-test="window.jQuery && window.jQuery.validator"
crossorigin="anonymous"
integrity="sha384-Fnqn3nxp3506LP/7Y3j/25BlWeA3PXTyT1l78LjECcPaKCV12TsZP7yyMxOe/G/k">
</script>
<script src="https://ajax.aspnetcdn.com/ajax/jquery.validation.unobtrusive/3.2.6/jquery.validate.unobtrusive.min.js"
asp-fallback-src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js"
asp-fallback-test="window.jQuery && window.jQuery.validator && window.jQuery.validator.unobtrusive"
crossorigin="anonymous"
integrity="sha384-JrXK+k53HACyavUKOsL+NkmSesD2P+73eDMrbTtTk0h4RmOF8hF8apPlkp26JlyH">
</script>
</environment>

+ 1
- 3
src/Web/WebStatus/bower.json View File

@ -3,8 +3,6 @@
"private": true, "private": true,
"dependencies": { "dependencies": {
"bootstrap": "3.3.7", "bootstrap": "3.3.7",
"jquery": "2.2.0",
"jquery-validation": "1.14.0",
"jquery-validation-unobtrusive": "3.2.6"
"jquery": "2.2.0"
} }
} }

+ 0
- 1
src/Web/WebStatus/wwwroot/images/banner1.svg
File diff suppressed because it is too large
View File


+ 0
- 1
src/Web/WebStatus/wwwroot/images/banner2.svg
File diff suppressed because it is too large
View File


+ 0
- 1
src/Web/WebStatus/wwwroot/images/banner3.svg
File diff suppressed because it is too large
View File


+ 0
- 1
src/Web/WebStatus/wwwroot/images/banner4.svg
File diff suppressed because it is too large
View File


+ 0
- 1
src/Web/WebStatus/wwwroot/js/site.js View File

@ -1 +0,0 @@
// Write your Javascript code.

+ 0
- 0
src/Web/WebStatus/wwwroot/js/site.min.js View File


+ 0
- 44
src/Web/WebStatus/wwwroot/lib/jquery-validation-unobtrusive/.bower.json View File

@ -1,44 +0,0 @@
{
"name": "jquery-validation-unobtrusive",
"version": "3.2.6",
"homepage": "https://github.com/aspnet/jquery-validation-unobtrusive",
"description": "Add-on to jQuery Validation to enable unobtrusive validation options in data-* attributes.",
"main": [
"jquery.validate.unobtrusive.js"
],
"ignore": [
"**/.*",
"*.json",
"*.md",
"*.txt",
"gulpfile.js"
],
"keywords": [
"jquery",
"asp.net",
"mvc",
"validation",
"unobtrusive"
],
"authors": [
"Microsoft"
],
"license": "http://www.microsoft.com/web/webpi/eula/net_library_eula_enu.htm",
"repository": {
"type": "git",
"url": "git://github.com/aspnet/jquery-validation-unobtrusive.git"
},
"dependencies": {
"jquery-validation": ">=1.8",
"jquery": ">=1.8"
},
"_release": "3.2.6",
"_resolution": {
"type": "version",
"tag": "v3.2.6",
"commit": "13386cd1b5947d8a5d23a12b531ce3960be1eba7"
},
"_source": "git://github.com/aspnet/jquery-validation-unobtrusive.git",
"_target": "3.2.6",
"_originalSource": "jquery-validation-unobtrusive"
}

+ 0
- 416
src/Web/WebStatus/wwwroot/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js View File

@ -1,416 +0,0 @@
/*!
** Unobtrusive validation support library for jQuery and jQuery Validate
** Copyright (C) Microsoft Corporation. All rights reserved.
*/
/*jslint white: true, browser: true, onevar: true, undef: true, nomen: true, eqeqeq: true, plusplus: true, bitwise: true, regexp: true, newcap: true, immed: true, strict: false */
/*global document: false, jQuery: false */
(function ($) {
var $jQval = $.validator,
adapters,
data_validation = "unobtrusiveValidation";
function setValidationValues(options, ruleName, value) {
options.rules[ruleName] = value;
if (options.message) {
options.messages[ruleName] = options.message;
}
}
function splitAndTrim(value) {
return value.replace(/^\s+|\s+$/g, "").split(/\s*,\s*/g);
}
function escapeAttributeValue(value) {
// As mentioned on http://api.jquery.com/category/selectors/
return value.replace(/([!"#$%&'()*+,./:;<=>?@\[\\\]^`{|}~])/g, "\\$1");
}
function getModelPrefix(fieldName) {
return fieldName.substr(0, fieldName.lastIndexOf(".") + 1);
}
function appendModelPrefix(value, prefix) {
if (value.indexOf("*.") === 0) {
value = value.replace("*.", prefix);
}
return value;
}
function onError(error, inputElement) { // 'this' is the form element
var container = $(this).find("[data-valmsg-for='" + escapeAttributeValue(inputElement[0].name) + "']"),
replaceAttrValue = container.attr("data-valmsg-replace"),
replace = replaceAttrValue ? $.parseJSON(replaceAttrValue) !== false : null;
container.removeClass("field-validation-valid").addClass("field-validation-error");
error.data("unobtrusiveContainer", container);
if (replace) {
container.empty();
error.removeClass("input-validation-error").appendTo(container);
}
else {
error.hide();
}
}
function onErrors(event, validator) { // 'this' is the form element
var container = $(this).find("[data-valmsg-summary=true]"),
list = container.find("ul");
if (list && list.length && validator.errorList.length) {
list.empty();
container.addClass("validation-summary-errors").removeClass("validation-summary-valid");
$.each(validator.errorList, function () {
$("<li />").html(this.message).appendTo(list);
});
}
}
function onSuccess(error) { // 'this' is the form element
var container = error.data("unobtrusiveContainer");
if (container) {
var replaceAttrValue = container.attr("data-valmsg-replace"),
replace = replaceAttrValue ? $.parseJSON(replaceAttrValue) : null;
container.addClass("field-validation-valid").removeClass("field-validation-error");
error.removeData("unobtrusiveContainer");
if (replace) {
container.empty();
}
}
}
function onReset(event) { // 'this' is the form element
var $form = $(this),
key = '__jquery_unobtrusive_validation_form_reset';
if ($form.data(key)) {
return;
}
// Set a flag that indicates we're currently resetting the form.
$form.data(key, true);
try {
$form.data("validator").resetForm();
} finally {
$form.removeData(key);
}
$form.find(".validation-summary-errors")
.addClass("validation-summary-valid")
.removeClass("validation-summary-errors");
$form.find(".field-validation-error")
.addClass("field-validation-valid")
.removeClass("field-validation-error")
.removeData("unobtrusiveContainer")
.find(">*") // If we were using valmsg-replace, get the underlying error
.removeData("unobtrusiveContainer");
}
function validationInfo(form) {
var $form = $(form),
result = $form.data(data_validation),
onResetProxy = $.proxy(onReset, form),
defaultOptions = $jQval.unobtrusive.options || {},
execInContext = function (name, args) {
var func = defaultOptions[name];
func && $.isFunction(func) && func.apply(form, args);
}
if (!result) {
result = {
options: { // options structure passed to jQuery Validate's validate() method
errorClass: defaultOptions.errorClass || "input-validation-error",
errorElement: defaultOptions.errorElement || "span",
errorPlacement: function () {
onError.apply(form, arguments);
execInContext("errorPlacement", arguments);
},
invalidHandler: function () {
onErrors.apply(form, arguments);
execInContext("invalidHandler", arguments);
},
messages: {},
rules: {},
success: function () {
onSuccess.apply(form, arguments);
execInContext("success", arguments);
}
},
attachValidation: function () {
$form
.off("reset." + data_validation, onResetProxy)
.on("reset." + data_validation, onResetProxy)
.validate(this.options);
},
validate: function () { // a validation function that is called by unobtrusive Ajax
$form.validate();
return $form.valid();
}
};
$form.data(data_validation, result);
}
return result;
}
$jQval.unobtrusive = {
adapters: [],
parseElement: function (element, skipAttach) {
/// <summary>
/// Parses a single HTML element for unobtrusive validation attributes.
/// </summary>
/// <param name="element" domElement="true">The HTML element to be parsed.</param>
/// <param name="skipAttach" type="Boolean">[Optional] true to skip attaching the
/// validation to the form. If parsing just this single element, you should specify true.
/// If parsing several elements, you should specify false, and manually attach the validation
/// to the form when you are finished. The default is false.</param>
var $element = $(element),
form = $element.parents("form")[0],
valInfo, rules, messages;
if (!form) { // Cannot do client-side validation without a form
return;
}
valInfo = validationInfo(form);
valInfo.options.rules[element.name] = rules = {};
valInfo.options.messages[element.name] = messages = {};
$.each(this.adapters, function () {
var prefix = "data-val-" + this.name,
message = $element.attr(prefix),
paramValues = {};
if (message !== undefined) { // Compare against undefined, because an empty message is legal (and falsy)
prefix += "-";
$.each(this.params, function () {
paramValues[this] = $element.attr(prefix + this);
});
this.adapt({
element: element,
form: form,
message: message,
params: paramValues,
rules: rules,
messages: messages
});
}
});
$.extend(rules, { "__dummy__": true });
if (!skipAttach) {
valInfo.attachValidation();
}
},
parse: function (selector) {
/// <summary>
/// Parses all the HTML elements in the specified selector. It looks for input elements decorated
/// with the [data-val=true] attribute value and enables validation according to the data-val-*
/// attribute values.
/// </summary>
/// <param name="selector" type="String">Any valid jQuery selector.</param>
// $forms includes all forms in selector's DOM hierarchy (parent, children and self) that have at least one
// element with data-val=true
var $selector = $(selector),
$forms = $selector.parents()
.addBack()
.filter("form")
.add($selector.find("form"))
.has("[data-val=true]");
$selector.find("[data-val=true]").each(function () {
$jQval.unobtrusive.parseElement(this, true);
});
$forms.each(function () {
var info = validationInfo(this);
if (info) {
info.attachValidation();
}
});
}
};
adapters = $jQval.unobtrusive.adapters;
adapters.add = function (adapterName, params, fn) {
/// <summary>Adds a new adapter to convert unobtrusive HTML into a jQuery Validate validation.</summary>
/// <param name="adapterName" type="String">The name of the adapter to be added. This matches the name used
/// in the data-val-nnnn HTML attribute (where nnnn is the adapter name).</param>
/// <param name="params" type="Array" optional="true">[Optional] An array of parameter names (strings) that will
/// be extracted from the data-val-nnnn-mmmm HTML attributes (where nnnn is the adapter name, and
/// mmmm is the parameter name).</param>
/// <param name="fn" type="Function">The function to call, which adapts the values from the HTML
/// attributes into jQuery Validate rules and/or messages.</param>
/// <returns type="jQuery.validator.unobtrusive.adapters" />
if (!fn) { // Called with no params, just a function
fn = params;
params = [];
}
this.push({ name: adapterName, params: params, adapt: fn });
return this;
};
adapters.addBool = function (adapterName, ruleName) {
/// <summary>Adds a new adapter to convert unobtrusive HTML into a jQuery Validate validation, where
/// the jQuery Validate validation rule has no parameter values.</summary>
/// <param name="adapterName" type="String">The name of the adapter to be added. This matches the name used
/// in the data-val-nnnn HTML attribute (where nnnn is the adapter name).</param>
/// <param name="ruleName" type="String" optional="true">[Optional] The name of the jQuery Validate rule. If not provided, the value
/// of adapterName will be used instead.</param>
/// <returns type="jQuery.validator.unobtrusive.adapters" />
return this.add(adapterName, function (options) {
setValidationValues(options, ruleName || adapterName, true);
});
};
adapters.addMinMax = function (adapterName, minRuleName, maxRuleName, minMaxRuleName, minAttribute, maxAttribute) {
/// <summary>Adds a new adapter to convert unobtrusive HTML into a jQuery Validate validation, where
/// the jQuery Validate validation has three potential rules (one for min-only, one for max-only, and
/// one for min-and-max). The HTML parameters are expected to be named -min and -max.</summary>
/// <param name="adapterName" type="String">The name of the adapter to be added. This matches the name used
/// in the data-val-nnnn HTML attribute (where nnnn is the adapter name).</param>
/// <param name="minRuleName" type="String">The name of the jQuery Validate rule to be used when you only
/// have a minimum value.</param>
/// <param name="maxRuleName" type="String">The name of the jQuery Validate rule to be used when you only
/// have a maximum value.</param>
/// <param name="minMaxRuleName" type="String">The name of the jQuery Validate rule to be used when you
/// have both a minimum and maximum value.</param>
/// <param name="minAttribute" type="String" optional="true">[Optional] The name of the HTML attribute that
/// contains the minimum value. The default is "min".</param>
/// <param name="maxAttribute" type="String" optional="true">[Optional] The name of the HTML attribute that
/// contains the maximum value. The default is "max".</param>
/// <returns type="jQuery.validator.unobtrusive.adapters" />
return this.add(adapterName, [minAttribute || "min", maxAttribute || "max"], function (options) {
var min = options.params.min,
max = options.params.max;
if (min && max) {
setValidationValues(options, minMaxRuleName, [min, max]);
}
else if (min) {
setValidationValues(options, minRuleName, min);
}
else if (max) {
setValidationValues(options, maxRuleName, max);
}
});
};
adapters.addSingleVal = function (adapterName, attribute, ruleName) {
/// <summary>Adds a new adapter to convert unobtrusive HTML into a jQuery Validate validation, where
/// the jQuery Validate validation rule has a single value.</summary>
/// <param name="adapterName" type="String">The name of the adapter to be added. This matches the name used
/// in the data-val-nnnn HTML attribute(where nnnn is the adapter name).</param>
/// <param name="attribute" type="String">[Optional] The name of the HTML attribute that contains the value.
/// The default is "val".</param>
/// <param name="ruleName" type="String" optional="true">[Optional] The name of the jQuery Validate rule. If not provided, the value
/// of adapterName will be used instead.</param>
/// <returns type="jQuery.validator.unobtrusive.adapters" />
return this.add(adapterName, [attribute || "val"], function (options) {
setValidationValues(options, ruleName || adapterName, options.params[attribute]);
});
};
$jQval.addMethod("__dummy__", function (value, element, params) {
return true;
});
$jQval.addMethod("regex", function (value, element, params) {
var match;
if (this.optional(element)) {
return true;
}
match = new RegExp(params).exec(value);
return (match && (match.index === 0) && (match[0].length === value.length));
});
$jQval.addMethod("nonalphamin", function (value, element, nonalphamin) {
var match;
if (nonalphamin) {
match = value.match(/\W/g);
match = match && match.length >= nonalphamin;
}
return match;
});
if ($jQval.methods.extension) {
adapters.addSingleVal("accept", "mimtype");
adapters.addSingleVal("extension", "extension");
} else {
// for backward compatibility, when the 'extension' validation method does not exist, such as with versions
// of JQuery Validation plugin prior to 1.10, we should use the 'accept' method for
// validating the extension, and ignore mime-type validations as they are not supported.
adapters.addSingleVal("extension", "extension", "accept");
}
adapters.addSingleVal("regex", "pattern");
adapters.addBool("creditcard").addBool("date").addBool("digits").addBool("email").addBool("number").addBool("url");
adapters.addMinMax("length", "minlength", "maxlength", "rangelength").addMinMax("range", "min", "max", "range");
adapters.addMinMax("minlength", "minlength").addMinMax("maxlength", "minlength", "maxlength");
adapters.add("equalto", ["other"], function (options) {
var prefix = getModelPrefix(options.element.name),
other = options.params.other,
fullOtherName = appendModelPrefix(other, prefix),
element = $(options.form).find(":input").filter("[name='" + escapeAttributeValue(fullOtherName) + "']")[0];
setValidationValues(options, "equalTo", element);
});
adapters.add("required", function (options) {
// jQuery Validate equates "required" with "mandatory" for checkbox elements
if (options.element.tagName.toUpperCase() !== "INPUT" || options.element.type.toUpperCase() !== "CHECKBOX") {
setValidationValues(options, "required", true);
}
});
adapters.add("remote", ["url", "type", "additionalfields"], function (options) {
var value = {
url: options.params.url,
type: options.params.type || "GET",
data: {}
},
prefix = getModelPrefix(options.element.name);
$.each(splitAndTrim(options.params.additionalfields || options.element.name), function (i, fieldName) {
var paramName = appendModelPrefix(fieldName, prefix);
value.data[paramName] = function () {
var field = $(options.form).find(":input").filter("[name='" + escapeAttributeValue(paramName) + "']");
// For checkboxes and radio buttons, only pick up values from checked fields.
if (field.is(":checkbox")) {
return field.filter(":checked").val() || field.filter(":hidden").val() || '';
}
else if (field.is(":radio")) {
return field.filter(":checked").val() || '';
}
return field.val();
};
});
setValidationValues(options, "remote", value);
});
adapters.add("password", ["min", "nonalphamin", "regex"], function (options) {
if (options.params.min) {
setValidationValues(options, "minlength", options.params.min);
}
if (options.params.nonalphamin) {
setValidationValues(options, "nonalphamin", options.params.nonalphamin);
}
if (options.params.regex) {
setValidationValues(options, "regex", options.params.regex);
}
});
$(function () {
$jQval.unobtrusive.parse(document);
});
}(jQuery));

+ 0
- 5
src/Web/WebStatus/wwwroot/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js
File diff suppressed because it is too large
View File


+ 0
- 40
src/Web/WebStatus/wwwroot/lib/jquery-validation/.bower.json View File

@ -1,40 +0,0 @@
{
"name": "jquery-validation",
"homepage": "http://jqueryvalidation.org/",
"repository": {
"type": "git",
"url": "git://github.com/jzaefferer/jquery-validation.git"
},
"authors": [
"Jörn Zaefferer <joern.zaefferer@gmail.com>"
],
"description": "Form validation made easy",
"main": "dist/jquery.validate.js",
"keywords": [
"forms",
"validation",
"validate"
],
"license": "MIT",
"ignore": [
"**/.*",
"node_modules",
"bower_components",
"test",
"demo",
"lib"
],
"dependencies": {
"jquery": ">= 1.7.2"
},
"version": "1.14.0",
"_release": "1.14.0",
"_resolution": {
"type": "version",
"tag": "1.14.0",
"commit": "c1343fb9823392aa9acbe1c3ffd337b8c92fed48"
},
"_source": "git://github.com/jzaefferer/jquery-validation.git",
"_target": ">=1.8",
"_originalSource": "jquery-validation"
}

+ 0
- 22
src/Web/WebStatus/wwwroot/lib/jquery-validation/LICENSE.md View File

@ -1,22 +0,0 @@
The MIT License (MIT)
=====================
Copyright Jörn Zaefferer
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

+ 0
- 998
src/Web/WebStatus/wwwroot/lib/jquery-validation/dist/additional-methods.js View File

@ -1,998 +0,0 @@
/*!
* jQuery Validation Plugin v1.14.0
*
* http://jqueryvalidation.org/
*
* Copyright (c) 2015 Jörn Zaefferer
* Released under the MIT license
*/
(function( factory ) {
if ( typeof define === "function" && define.amd ) {
define( ["jquery", "./jquery.validate"], factory );
} else {
factory( jQuery );
}
}(function( $ ) {
(function() {
function stripHtml(value) {
// remove html tags and space chars
return value.replace(/<.[^<>]*?>/g, " ").replace(/&nbsp;|&#160;/gi, " ")
// remove punctuation
.replace(/[.(),;:!?%#$'\"_+=\/\-“”’]*/g, "");
}
$.validator.addMethod("maxWords", function(value, element, params) {
return this.optional(element) || stripHtml(value).match(/\b\w+\b/g).length <= params;
}, $.validator.format("Please enter {0} words or less."));
$.validator.addMethod("minWords", function(value, element, params) {
return this.optional(element) || stripHtml(value).match(/\b\w+\b/g).length >= params;
}, $.validator.format("Please enter at least {0} words."));
$.validator.addMethod("rangeWords", function(value, element, params) {
var valueStripped = stripHtml(value),
regex = /\b\w+\b/g;
return this.optional(element) || valueStripped.match(regex).length >= params[0] && valueStripped.match(regex).length <= params[1];
}, $.validator.format("Please enter between {0} and {1} words."));
}());
// Accept a value from a file input based on a required mimetype
$.validator.addMethod("accept", function(value, element, param) {
// Split mime on commas in case we have multiple types we can accept
var typeParam = typeof param === "string" ? param.replace(/\s/g, "").replace(/,/g, "|") : "image/*",
optionalValue = this.optional(element),
i, file;
// Element is optional
if (optionalValue) {
return optionalValue;
}
if ($(element).attr("type") === "file") {
// If we are using a wildcard, make it regex friendly
typeParam = typeParam.replace(/\*/g, ".*");
// Check if the element has a FileList before checking each file
if (element.files && element.files.length) {
for (i = 0; i < element.files.length; i++) {
file = element.files[i];
// Grab the mimetype from the loaded file, verify it matches
if (!file.type.match(new RegExp( "\\.?(" + typeParam + ")$", "i"))) {
return false;
}
}
}
}
// Either return true because we've validated each file, or because the
// browser does not support element.files and the FileList feature
return true;
}, $.validator.format("Please enter a value with a valid mimetype."));
$.validator.addMethod("alphanumeric", function(value, element) {
return this.optional(element) || /^\w+$/i.test(value);
}, "Letters, numbers, and underscores only please");
/*
* Dutch bank account numbers (not 'giro' numbers) have 9 digits
* and pass the '11 check'.
* We accept the notation with spaces, as that is common.
* acceptable: 123456789 or 12 34 56 789
*/
$.validator.addMethod("bankaccountNL", function(value, element) {
if (this.optional(element)) {
return true;
}
if (!(/^[0-9]{9}|([0-9]{2} ){3}[0-9]{3}$/.test(value))) {
return false;
}
// now '11 check'
var account = value.replace(/ /g, ""), // remove spaces
sum = 0,
len = account.length,
pos, factor, digit;
for ( pos = 0; pos < len; pos++ ) {
factor = len - pos;
digit = account.substring(pos, pos + 1);
sum = sum + factor * digit;
}
return sum % 11 === 0;
}, "Please specify a valid bank account number");
$.validator.addMethod("bankorgiroaccountNL", function(value, element) {
return this.optional(element) ||
($.validator.methods.bankaccountNL.call(this, value, element)) ||
($.validator.methods.giroaccountNL.call(this, value, element));
}, "Please specify a valid bank or giro account number");
/**
* BIC is the business identifier code (ISO 9362). This BIC check is not a guarantee for authenticity.
*
* BIC pattern: BBBBCCLLbbb (8 or 11 characters long; bbb is optional)
*
* BIC definition in detail:
* - First 4 characters - bank code (only letters)
* - Next 2 characters - ISO 3166-1 alpha-2 country code (only letters)
* - Next 2 characters - location code (letters and digits)
* a. shall not start with '0' or '1'
* b. second character must be a letter ('O' is not allowed) or one of the following digits ('0' for test (therefore not allowed), '1' for passive participant and '2' for active participant)
* - Last 3 characters - branch code, optional (shall not start with 'X' except in case of 'XXX' for primary office) (letters and digits)
*/
$.validator.addMethod("bic", function(value, element) {
return this.optional( element ) || /^([A-Z]{6}[A-Z2-9][A-NP-Z1-2])(X{3}|[A-WY-Z0-9][A-Z0-9]{2})?$/.test( value );
}, "Please specify a valid BIC code");
/*
* Código de identificación fiscal ( CIF ) is the tax identification code for Spanish legal entities
* Further rules can be found in Spanish on http://es.wikipedia.org/wiki/C%C3%B3digo_de_identificaci%C3%B3n_fiscal
*/
$.validator.addMethod( "cifES", function( value ) {
"use strict";
var num = [],
controlDigit, sum, i, count, tmp, secondDigit;
value = value.toUpperCase();
// Quick format test
if ( !value.match( "((^[A-Z]{1}[0-9]{7}[A-Z0-9]{1}$|^[T]{1}[A-Z0-9]{8}$)|^[0-9]{8}[A-Z]{1}$)" ) ) {
return false;
}
for ( i = 0; i < 9; i++ ) {
num[ i ] = parseInt( value.charAt( i ), 10 );
}
// Algorithm for checking CIF codes
sum = num[ 2 ] + num[ 4 ] + num[ 6 ];
for ( count = 1; count < 8; count += 2 ) {
tmp = ( 2 * num[ count ] ).toString();
secondDigit = tmp.charAt( 1 );
sum += parseInt( tmp.charAt( 0 ), 10 ) + ( secondDigit === "" ? 0 : parseInt( secondDigit, 10 ) );
}
/* The first (position 1) is a letter following the following criteria:
* A. Corporations
* B. LLCs
* C. General partnerships
* D. Companies limited partnerships
* E. Communities of goods
* F. Cooperative Societies
* G. Associations
* H. Communities of homeowners in horizontal property regime
* J. Civil Societies
* K. Old format
* L. Old format
* M. Old format
* N. Nonresident entities
* P. Local authorities
* Q. Autonomous bodies, state or not, and the like, and congregations and religious institutions
* R. Congregations and religious institutions (since 2008 ORDER EHA/451/2008)
* S. Organs of State Administration and regions
* V. Agrarian Transformation
* W. Permanent establishments of non-resident in Spain
*/
if ( /^[ABCDEFGHJNPQRSUVW]{1}/.test( value ) ) {
sum += "";
controlDigit = 10 - parseInt( sum.charAt( sum.length - 1 ), 10 );
value += controlDigit;
return ( num[ 8 ].toString() === String.fromCharCode( 64 + controlDigit ) || num[ 8 ].toString() === value.charAt( value.length - 1 ) );
}
return false;
}, "Please specify a valid CIF number." );
/*
* Brazillian CPF number (Cadastrado de Pessoas Físicas) is the equivalent of a Brazilian tax registration number.
* CPF numbers have 11 digits in total: 9 numbers followed by 2 check numbers that are being used for validation.
*/
$.validator.addMethod("cpfBR", function(value) {
// Removing special characters from value
value = value.replace(/([~!@#$%^&*()_+=`{}\[\]\-|\\:;'<>,.\/? ])+/g, "");
// Checking value to have 11 digits only
if (value.length !== 11) {
return false;
}
var sum = 0,
firstCN, secondCN, checkResult, i;
firstCN = parseInt(value.substring(9, 10), 10);
secondCN = parseInt(value.substring(10, 11), 10);
checkResult = function(sum, cn) {
var result = (sum * 10) % 11;
if ((result === 10) || (result === 11)) {result = 0;}
return (result === cn);
};
// Checking for dump data
if (value === "" ||
value === "00000000000" ||
value === "11111111111" ||
value === "22222222222" ||
value === "33333333333" ||
value === "44444444444" ||
value === "55555555555" ||
value === "66666666666" ||
value === "77777777777" ||
value === "88888888888" ||
value === "99999999999"
) {
return false;
}
// Step 1 - using first Check Number:
for ( i = 1; i <= 9; i++ ) {
sum = sum + parseInt(value.substring(i - 1, i), 10) * (11 - i);
}
// If first Check Number (CN) is valid, move to Step 2 - using second Check Number:
if ( checkResult(sum, firstCN) ) {
sum = 0;
for ( i = 1; i <= 10; i++ ) {
sum = sum + parseInt(value.substring(i - 1, i), 10) * (12 - i);
}
return checkResult(sum, secondCN);
}
return false;
}, "Please specify a valid CPF number");
/* NOTICE: Modified version of Castle.Components.Validator.CreditCardValidator
* Redistributed under the the Apache License 2.0 at http://www.apache.org/licenses/LICENSE-2.0
* Valid Types: mastercard, visa, amex, dinersclub, enroute, discover, jcb, unknown, all (overrides all other settings)
*/
$.validator.addMethod("creditcardtypes", function(value, element, param) {
if (/[^0-9\-]+/.test(value)) {
return false;
}
value = value.replace(/\D/g, "");
var validTypes = 0x0000;
if (param.mastercard) {
validTypes |= 0x0001;
}
if (param.visa) {
validTypes |= 0x0002;
}
if (param.amex) {
validTypes |= 0x0004;
}
if (param.dinersclub) {
validTypes |= 0x0008;
}
if (param.enroute) {
validTypes |= 0x0010;
}
if (param.discover) {
validTypes |= 0x0020;
}
if (param.jcb) {
validTypes |= 0x0040;
}
if (param.unknown) {
validTypes |= 0x0080;
}
if (param.all) {
validTypes = 0x0001 | 0x0002 | 0x0004 | 0x0008 | 0x0010 | 0x0020 | 0x0040 | 0x0080;
}
if (validTypes & 0x0001 && /^(5[12345])/.test(value)) { //mastercard
return value.length === 16;
}
if (validTypes & 0x0002 && /^(4)/.test(value)) { //visa
return value.length === 16;
}
if (validTypes & 0x0004 && /^(3[47])/.test(value)) { //amex
return value.length === 15;
}
if (validTypes & 0x0008 && /^(3(0[012345]|[68]))/.test(value)) { //dinersclub
return value.length === 14;
}
if (validTypes & 0x0010 && /^(2(014|149))/.test(value)) { //enroute
return value.length === 15;
}
if (validTypes & 0x0020 && /^(6011)/.test(value)) { //discover
return value.length === 16;
}
if (validTypes & 0x0040 && /^(3)/.test(value)) { //jcb
return value.length === 16;
}
if (validTypes & 0x0040 && /^(2131|1800)/.test(value)) { //jcb
return value.length === 15;
}
if (validTypes & 0x0080) { //unknown
return true;
}
return false;
}, "Please enter a valid credit card number.");
/**
* Validates currencies with any given symbols by @jameslouiz
* Symbols can be optional or required. Symbols required by default
*
* Usage examples:
* currency: ["£", false] - Use false for soft currency validation
* currency: ["$", false]
* currency: ["RM", false] - also works with text based symbols such as "RM" - Malaysia Ringgit etc
*
* <input class="currencyInput" name="currencyInput">
*
* Soft symbol checking
* currencyInput: {
* currency: ["$", false]
* }
*
* Strict symbol checking (default)
* currencyInput: {
* currency: "$"
* //OR
* currency: ["$", true]
* }
*
* Multiple Symbols
* currencyInput: {
* currency: "$,£,¢"
* }
*/
$.validator.addMethod("currency", function(value, element, param) {
var isParamString = typeof param === "string",
symbol = isParamString ? param : param[0],
soft = isParamString ? true : param[1],
regex;
symbol = symbol.replace(/,/g, "");
symbol = soft ? symbol + "]" : symbol + "]?";
regex = "^[" + symbol + "([1-9]{1}[0-9]{0,2}(\\,[0-9]{3})*(\\.[0-9]{0,2})?|[1-9]{1}[0-9]{0,}(\\.[0-9]{0,2})?|0(\\.[0-9]{0,2})?|(\\.[0-9]{1,2})?)$";
regex = new RegExp(regex);
return this.optional(element) || regex.test(value);
}, "Please specify a valid currency");
$.validator.addMethod("dateFA", function(value, element) {
return this.optional(element) || /^[1-4]\d{3}\/((0?[1-6]\/((3[0-1])|([1-2][0-9])|(0?[1-9])))|((1[0-2]|(0?[7-9]))\/(30|([1-2][0-9])|(0?[1-9]))))$/.test(value);
}, $.validator.messages.date);
/**
* Return true, if the value is a valid date, also making this formal check dd/mm/yyyy.
*
* @example $.validator.methods.date("01/01/1900")
* @result true
*
* @example $.validator.methods.date("01/13/1990")
* @result false
*
* @example $.validator.methods.date("01.01.1900")
* @result false
*
* @example <input name="pippo" class="{dateITA:true}" />
* @desc Declares an optional input element whose value must be a valid date.
*
* @name $.validator.methods.dateITA
* @type Boolean
* @cat Plugins/Validate/Methods
*/
$.validator.addMethod("dateITA", function(value, element) {
var check = false,
re = /^\d{1,2}\/\d{1,2}\/\d{4}$/,
adata, gg, mm, aaaa, xdata;
if ( re.test(value)) {
adata = value.split("/");
gg = parseInt(adata[0], 10);
mm = parseInt(adata[1], 10);
aaaa = parseInt(adata[2], 10);
xdata = new Date(Date.UTC(aaaa, mm - 1, gg, 12, 0, 0, 0));
if ( ( xdata.getUTCFullYear() === aaaa ) && ( xdata.getUTCMonth () === mm - 1 ) && ( xdata.getUTCDate() === gg ) ) {
check = true;
} else {
check = false;
}
} else {
check = false;
}
return this.optional(element) || check;
}, $.validator.messages.date);
$.validator.addMethod("dateNL", function(value, element) {
return this.optional(element) || /^(0?[1-9]|[12]\d|3[01])[\.\/\-](0?[1-9]|1[012])[\.\/\-]([12]\d)?(\d\d)$/.test(value);
}, $.validator.messages.date);
// Older "accept" file extension method. Old docs: http://docs.jquery.com/Plugins/Validation/Methods/accept
$.validator.addMethod("extension", function(value, element, param) {
param = typeof param === "string" ? param.replace(/,/g, "|") : "png|jpe?g|gif";
return this.optional(element) || value.match(new RegExp("\\.(" + param + ")$", "i"));
}, $.validator.format("Please enter a value with a valid extension."));
/**
* Dutch giro account numbers (not bank numbers) have max 7 digits
*/
$.validator.addMethod("giroaccountNL", function(value, element) {
return this.optional(element) || /^[0-9]{1,7}$/.test(value);
}, "Please specify a valid giro account number");
/**
* IBAN is the international bank account number.
* It has a country - specific format, that is checked here too
*/
$.validator.addMethod("iban", function(value, element) {
// some quick simple tests to prevent needless work
if (this.optional(element)) {
return true;
}
// remove spaces and to upper case
var iban = value.replace(/ /g, "").toUpperCase(),
ibancheckdigits = "",
leadingZeroes = true,
cRest = "",
cOperator = "",
countrycode, ibancheck, charAt, cChar, bbanpattern, bbancountrypatterns, ibanregexp, i, p;
// check the country code and find the country specific format
countrycode = iban.substring(0, 2);
bbancountrypatterns = {
"AL": "\\d{8}[\\dA-Z]{16}",
"AD": "\\d{8}[\\dA-Z]{12}",
"AT": "\\d{16}",
"AZ": "[\\dA-Z]{4}\\d{20}",
"BE": "\\d{12}",
"BH": "[A-Z]{4}[\\dA-Z]{14}",
"BA": "\\d{16}",
"BR": "\\d{23}[A-Z][\\dA-Z]",
"BG": "[A-Z]{4}\\d{6}[\\dA-Z]{8}",
"CR": "\\d{17}",
"HR": "\\d{17}",
"CY": "\\d{8}[\\dA-Z]{16}",
"CZ": "\\d{20}",
"DK": "\\d{14}",
"DO": "[A-Z]{4}\\d{20}",
"EE": "\\d{16}",
"FO": "\\d{14}",
"FI": "\\d{14}",
"FR": "\\d{10}[\\dA-Z]{11}\\d{2}",
"GE": "[\\dA-Z]{2}\\d{16}",
"DE": "\\d{18}",
"GI": "[A-Z]{4}[\\dA-Z]{15}",
"GR": "\\d{7}[\\dA-Z]{16}",
"GL": "\\d{14}",
"GT": "[\\dA-Z]{4}[\\dA-Z]{20}",
"HU": "\\d{24}",
"IS": "\\d{22}",
"IE": "[\\dA-Z]{4}\\d{14}",
"IL": "\\d{19}",
"IT": "[A-Z]\\d{10}[\\dA-Z]{12}",
"KZ": "\\d{3}[\\dA-Z]{13}",
"KW": "[A-Z]{4}[\\dA-Z]{22}",
"LV": "[A-Z]{4}[\\dA-Z]{13}",
"LB": "\\d{4}[\\dA-Z]{20}",
"LI": "\\d{5}[\\dA-Z]{12}",
"LT": "\\d{16}",
"LU": "\\d{3}[\\dA-Z]{13}",
"MK": "\\d{3}[\\dA-Z]{10}\\d{2}",
"MT": "[A-Z]{4}\\d{5}[\\dA-Z]{18}",
"MR": "\\d{23}",
"MU": "[A-Z]{4}\\d{19}[A-Z]{3}",
"MC": "\\d{10}[\\dA-Z]{11}\\d{2}",
"MD": "[\\dA-Z]{2}\\d{18}",
"ME": "\\d{18}",
"NL": "[A-Z]{4}\\d{10}",
"NO": "\\d{11}",
"PK": "[\\dA-Z]{4}\\d{16}",
"PS": "[\\dA-Z]{4}\\d{21}",
"PL": "\\d{24}",
"PT": "\\d{21}",
"RO": "[A-Z]{4}[\\dA-Z]{16}",
"SM": "[A-Z]\\d{10}[\\dA-Z]{12}",
"SA": "\\d{2}[\\dA-Z]{18}",
"RS": "\\d{18}",
"SK": "\\d{20}",
"SI": "\\d{15}",
"ES": "\\d{20}",
"SE": "\\d{20}",
"CH": "\\d{5}[\\dA-Z]{12}",
"TN": "\\d{20}",
"TR": "\\d{5}[\\dA-Z]{17}",
"AE": "\\d{3}\\d{16}",
"GB": "[A-Z]{4}\\d{14}",
"VG": "[\\dA-Z]{4}\\d{16}"
};
bbanpattern = bbancountrypatterns[countrycode];
// As new countries will start using IBAN in the
// future, we only check if the countrycode is known.
// This prevents false negatives, while almost all
// false positives introduced by this, will be caught
// by the checksum validation below anyway.
// Strict checking should return FALSE for unknown
// countries.
if (typeof bbanpattern !== "undefined") {
ibanregexp = new RegExp("^[A-Z]{2}\\d{2}" + bbanpattern + "$", "");
if (!(ibanregexp.test(iban))) {
return false; // invalid country specific format
}
}
// now check the checksum, first convert to digits
ibancheck = iban.substring(4, iban.length) + iban.substring(0, 4);
for (i = 0; i < ibancheck.length; i++) {
charAt = ibancheck.charAt(i);
if (charAt !== "0") {
leadingZeroes = false;
}
if (!leadingZeroes) {
ibancheckdigits += "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ".indexOf(charAt);
}
}
// calculate the result of: ibancheckdigits % 97
for (p = 0; p < ibancheckdigits.length; p++) {
cChar = ibancheckdigits.charAt(p);
cOperator = "" + cRest + "" + cChar;
cRest = cOperator % 97;
}
return cRest === 1;
}, "Please specify a valid IBAN");
$.validator.addMethod("integer", function(value, element) {
return this.optional(element) || /^-?\d+$/.test(value);
}, "A positive or negative non-decimal number please");
$.validator.addMethod("ipv4", function(value, element) {
return this.optional(element) || /^(25[0-5]|2[0-4]\d|[01]?\d\d?)\.(25[0-5]|2[0-4]\d|[01]?\d\d?)\.(25[0-5]|2[0-4]\d|[01]?\d\d?)\.(25[0-5]|2[0-4]\d|[01]?\d\d?)$/i.test(value);
}, "Please enter a valid IP v4 address.");
$.validator.addMethod("ipv6", function(value, element) {
return this.optional(element) || /^((([0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}:[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){5}:([0-9A-Fa-f]{1,4}:)?[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){4}:([0-9A-Fa-f]{1,4}:){0,2}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){3}:([0-9A-Fa-f]{1,4}:){0,3}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){2}:([0-9A-Fa-f]{1,4}:){0,4}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|(([0-9A-Fa-f]{1,4}:){0,5}:((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|(::([0-9A-Fa-f]{1,4}:){0,5}((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|([0-9A-Fa-f]{1,4}::([0-9A-Fa-f]{1,4}:){0,5}[0-9A-Fa-f]{1,4})|(::([0-9A-Fa-f]{1,4}:){0,6}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){1,7}:))$/i.test(value);
}, "Please enter a valid IP v6 address.");
$.validator.addMethod("lettersonly", function(value, element) {
return this.optional(element) || /^[a-z]+$/i.test(value);
}, "Letters only please");
$.validator.addMethod("letterswithbasicpunc", function(value, element) {
return this.optional(element) || /^[a-z\-.,()'"\s]+$/i.test(value);
}, "Letters or punctuation only please");
$.validator.addMethod("mobileNL", function(value, element) {
return this.optional(element) || /^((\+|00(\s|\s?\-\s?)?)31(\s|\s?\-\s?)?(\(0\)[\-\s]?)?|0)6((\s|\s?\-\s?)?[0-9]){8}$/.test(value);
}, "Please specify a valid mobile number");
/* For UK phone functions, do the following server side processing:
* Compare original input with this RegEx pattern:
* ^\(?(?:(?:00\)?[\s\-]?\(?|\+)(44)\)?[\s\-]?\(?(?:0\)?[\s\-]?\(?)?|0)([1-9]\d{1,4}\)?[\s\d\-]+)$
* Extract $1 and set $prefix to '+44<space>' if $1 is '44', otherwise set $prefix to '0'
* Extract $2 and remove hyphens, spaces and parentheses. Phone number is combined $prefix and $2.
* A number of very detailed GB telephone number RegEx patterns can also be found at:
* http://www.aa-asterisk.org.uk/index.php/Regular_Expressions_for_Validating_and_Formatting_GB_Telephone_Numbers
*/
$.validator.addMethod("mobileUK", function(phone_number, element) {
phone_number = phone_number.replace(/\(|\)|\s+|-/g, "");
return this.optional(element) || phone_number.length > 9 &&
phone_number.match(/^(?:(?:(?:00\s?|\+)44\s?|0)7(?:[1345789]\d{2}|624)\s?\d{3}\s?\d{3})$/);
}, "Please specify a valid mobile number");
/*
* The número de identidad de extranjero ( NIE )is a code used to identify the non-nationals in Spain
*/
$.validator.addMethod( "nieES", function( value ) {
"use strict";
value = value.toUpperCase();
// Basic format test
if ( !value.match( "((^[A-Z]{1}[0-9]{7}[A-Z0-9]{1}$|^[T]{1}[A-Z0-9]{8}$)|^[0-9]{8}[A-Z]{1}$)" ) ) {
return false;
}
// Test NIE
//T
if ( /^[T]{1}/.test( value ) ) {
return ( value[ 8 ] === /^[T]{1}[A-Z0-9]{8}$/.test( value ) );
}
//XYZ
if ( /^[XYZ]{1}/.test( value ) ) {
return (
value[ 8 ] === "TRWAGMYFPDXBNJZSQVHLCKE".charAt(
value.replace( "X", "0" )
.replace( "Y", "1" )
.replace( "Z", "2" )
.substring( 0, 8 ) % 23
)
);
}
return false;
}, "Please specify a valid NIE number." );
/*
* The Número de Identificación Fiscal ( NIF ) is the way tax identification used in Spain for individuals
*/
$.validator.addMethod( "nifES", function( value ) {
"use strict";
value = value.toUpperCase();
// Basic format test
if ( !value.match("((^[A-Z]{1}[0-9]{7}[A-Z0-9]{1}$|^[T]{1}[A-Z0-9]{8}$)|^[0-9]{8}[A-Z]{1}$)") ) {
return false;
}
// Test NIF
if ( /^[0-9]{8}[A-Z]{1}$/.test( value ) ) {
return ( "TRWAGMYFPDXBNJZSQVHLCKE".charAt( value.substring( 8, 0 ) % 23 ) === value.charAt( 8 ) );
}
// Test specials NIF (starts with K, L or M)
if ( /^[KLM]{1}/.test( value ) ) {
return ( value[ 8 ] === String.fromCharCode( 64 ) );
}
return false;
}, "Please specify a valid NIF number." );
jQuery.validator.addMethod( "notEqualTo", function( value, element, param ) {
return this.optional(element) || !$.validator.methods.equalTo.call( this, value, element, param );
}, "Please enter a different value, values must not be the same." );
$.validator.addMethod("nowhitespace", function(value, element) {
return this.optional(element) || /^\S+$/i.test(value);
}, "No white space please");
/**
* Return true if the field value matches the given format RegExp
*
* @example $.validator.methods.pattern("AR1004",element,/^AR\d{4}$/)
* @result true
*
* @example $.validator.methods.pattern("BR1004",element,/^AR\d{4}$/)
* @result false
*
* @name $.validator.methods.pattern
* @type Boolean
* @cat Plugins/Validate/Methods
*/
$.validator.addMethod("pattern", function(value, element, param) {
if (this.optional(element)) {
return true;
}
if (typeof param === "string") {
param = new RegExp("^(?:" + param + ")$");
}
return param.test(value);
}, "Invalid format.");
/**
* Dutch phone numbers have 10 digits (or 11 and start with +31).
*/
$.validator.addMethod("phoneNL", function(value, element) {
return this.optional(element) || /^((\+|00(\s|\s?\-\s?)?)31(\s|\s?\-\s?)?(\(0\)[\-\s]?)?|0)[1-9]((\s|\s?\-\s?)?[0-9]){8}$/.test(value);
}, "Please specify a valid phone number.");
/* For UK phone functions, do the following server side processing:
* Compare original input with this RegEx pattern:
* ^\(?(?:(?:00\)?[\s\-]?\(?|\+)(44)\)?[\s\-]?\(?(?:0\)?[\s\-]?\(?)?|0)([1-9]\d{1,4}\)?[\s\d\-]+)$
* Extract $1 and set $prefix to '+44<space>' if $1 is '44', otherwise set $prefix to '0'
* Extract $2 and remove hyphens, spaces and parentheses. Phone number is combined $prefix and $2.
* A number of very detailed GB telephone number RegEx patterns can also be found at:
* http://www.aa-asterisk.org.uk/index.php/Regular_Expressions_for_Validating_and_Formatting_GB_Telephone_Numbers
*/
$.validator.addMethod("phoneUK", function(phone_number, element) {
phone_number = phone_number.replace(/\(|\)|\s+|-/g, "");
return this.optional(element) || phone_number.length > 9 &&
phone_number.match(/^(?:(?:(?:00\s?|\+)44\s?)|(?:\(?0))(?:\d{2}\)?\s?\d{4}\s?\d{4}|\d{3}\)?\s?\d{3}\s?\d{3,4}|\d{4}\)?\s?(?:\d{5}|\d{3}\s?\d{3})|\d{5}\)?\s?\d{4,5})$/);
}, "Please specify a valid phone number");
/**
* matches US phone number format
*
* where the area code may not start with 1 and the prefix may not start with 1
* allows '-' or ' ' as a separator and allows parens around area code
* some people may want to put a '1' in front of their number
*
* 1(212)-999-2345 or
* 212 999 2344 or
* 212-999-0983
*
* but not
* 111-123-5434
* and not
* 212 123 4567
*/
$.validator.addMethod("phoneUS", function(phone_number, element) {
phone_number = phone_number.replace(/\s+/g, "");
return this.optional(element) || phone_number.length > 9 &&
phone_number.match(/^(\+?1-?)?(\([2-9]([02-9]\d|1[02-9])\)|[2-9]([02-9]\d|1[02-9]))-?[2-9]([02-9]\d|1[02-9])-?\d{4}$/);
}, "Please specify a valid phone number");
/* For UK phone functions, do the following server side processing:
* Compare original input with this RegEx pattern:
* ^\(?(?:(?:00\)?[\s\-]?\(?|\+)(44)\)?[\s\-]?\(?(?:0\)?[\s\-]?\(?)?|0)([1-9]\d{1,4}\)?[\s\d\-]+)$
* Extract $1 and set $prefix to '+44<space>' if $1 is '44', otherwise set $prefix to '0'
* Extract $2 and remove hyphens, spaces and parentheses. Phone number is combined $prefix and $2.
* A number of very detailed GB telephone number RegEx patterns can also be found at:
* http://www.aa-asterisk.org.uk/index.php/Regular_Expressions_for_Validating_and_Formatting_GB_Telephone_Numbers
*/
//Matches UK landline + mobile, accepting only 01-3 for landline or 07 for mobile to exclude many premium numbers
$.validator.addMethod("phonesUK", function(phone_number, element) {
phone_number = phone_number.replace(/\(|\)|\s+|-/g, "");
return this.optional(element) || phone_number.length > 9 &&
phone_number.match(/^(?:(?:(?:00\s?|\+)44\s?|0)(?:1\d{8,9}|[23]\d{9}|7(?:[1345789]\d{8}|624\d{6})))$/);
}, "Please specify a valid uk phone number");
/**
* Matches a valid Canadian Postal Code
*
* @example jQuery.validator.methods.postalCodeCA( "H0H 0H0", element )
* @result true
*
* @example jQuery.validator.methods.postalCodeCA( "H0H0H0", element )
* @result false
*
* @name jQuery.validator.methods.postalCodeCA
* @type Boolean
* @cat Plugins/Validate/Methods
*/
$.validator.addMethod( "postalCodeCA", function( value, element ) {
return this.optional( element ) || /^[ABCEGHJKLMNPRSTVXY]\d[A-Z] \d[A-Z]\d$/.test( value );
}, "Please specify a valid postal code" );
/*
* Valida CEPs do brasileiros:
*
* Formatos aceitos:
* 99999-999
* 99.999-999
* 99999999
*/
$.validator.addMethod("postalcodeBR", function(cep_value, element) {
return this.optional(element) || /^\d{2}.\d{3}-\d{3}?$|^\d{5}-?\d{3}?$/.test( cep_value );
}, "Informe um CEP válido.");
/* Matches Italian postcode (CAP) */
$.validator.addMethod("postalcodeIT", function(value, element) {
return this.optional(element) || /^\d{5}$/.test(value);
}, "Please specify a valid postal code");
$.validator.addMethod("postalcodeNL", function(value, element) {
return this.optional(element) || /^[1-9][0-9]{3}\s?[a-zA-Z]{2}$/.test(value);
}, "Please specify a valid postal code");
// Matches UK postcode. Does not match to UK Channel Islands that have their own postcodes (non standard UK)
$.validator.addMethod("postcodeUK", function(value, element) {
return this.optional(element) || /^((([A-PR-UWYZ][0-9])|([A-PR-UWYZ][0-9][0-9])|([A-PR-UWYZ][A-HK-Y][0-9])|([A-PR-UWYZ][A-HK-Y][0-9][0-9])|([A-PR-UWYZ][0-9][A-HJKSTUW])|([A-PR-UWYZ][A-HK-Y][0-9][ABEHMNPRVWXY]))\s?([0-9][ABD-HJLNP-UW-Z]{2})|(GIR)\s?(0AA))$/i.test(value);
}, "Please specify a valid UK postcode");
/*
* Lets you say "at least X inputs that match selector Y must be filled."
*
* The end result is that neither of these inputs:
*
* <input class="productinfo" name="partnumber">
* <input class="productinfo" name="description">
*
* ...will validate unless at least one of them is filled.
*
* partnumber: {require_from_group: [1,".productinfo"]},
* description: {require_from_group: [1,".productinfo"]}
*
* options[0]: number of fields that must be filled in the group
* options[1]: CSS selector that defines the group of conditionally required fields
*/
$.validator.addMethod("require_from_group", function(value, element, options) {
var $fields = $(options[1], element.form),
$fieldsFirst = $fields.eq(0),
validator = $fieldsFirst.data("valid_req_grp") ? $fieldsFirst.data("valid_req_grp") : $.extend({}, this),
isValid = $fields.filter(function() {
return validator.elementValue(this);
}).length >= options[0];
// Store the cloned validator for future validation
$fieldsFirst.data("valid_req_grp", validator);
// If element isn't being validated, run each require_from_group field's validation rules
if (!$(element).data("being_validated")) {
$fields.data("being_validated", true);
$fields.each(function() {
validator.element(this);
});
$fields.data("being_validated", false);
}
return isValid;
}, $.validator.format("Please fill at least {0} of these fields."));
/*
* Lets you say "either at least X inputs that match selector Y must be filled,
* OR they must all be skipped (left blank)."
*
* The end result, is that none of these inputs:
*
* <input class="productinfo" name="partnumber">
* <input class="productinfo" name="description">
* <input class="productinfo" name="color">
*
* ...will validate unless either at least two of them are filled,
* OR none of them are.
*
* partnumber: {skip_or_fill_minimum: [2,".productinfo"]},
* description: {skip_or_fill_minimum: [2,".productinfo"]},
* color: {skip_or_fill_minimum: [2,".productinfo"]}
*
* options[0]: number of fields that must be filled in the group
* options[1]: CSS selector that defines the group of conditionally required fields
*
*/
$.validator.addMethod("skip_or_fill_minimum", function(value, element, options) {
var $fields = $(options[1], element.form),
$fieldsFirst = $fields.eq(0),
validator = $fieldsFirst.data("valid_skip") ? $fieldsFirst.data("valid_skip") : $.extend({}, this),
numberFilled = $fields.filter(function() {
return validator.elementValue(this);
}).length,
isValid = numberFilled === 0 || numberFilled >= options[0];
// Store the cloned validator for future validation
$fieldsFirst.data("valid_skip", validator);
// If element isn't being validated, run each skip_or_fill_minimum field's validation rules
if (!$(element).data("being_validated")) {
$fields.data("being_validated", true);
$fields.each(function() {
validator.element(this);
});
$fields.data("being_validated", false);
}
return isValid;
}, $.validator.format("Please either skip these fields or fill at least {0} of them."));
/* Validates US States and/or Territories by @jdforsythe
* Can be case insensitive or require capitalization - default is case insensitive
* Can include US Territories or not - default does not
* Can include US Military postal abbreviations (AA, AE, AP) - default does not
*
* Note: "States" always includes DC (District of Colombia)
*
* Usage examples:
*
* This is the default - case insensitive, no territories, no military zones
* stateInput: {
* caseSensitive: false,
* includeTerritories: false,
* includeMilitary: false
* }
*
* Only allow capital letters, no territories, no military zones
* stateInput: {
* caseSensitive: false
* }
*
* Case insensitive, include territories but not military zones
* stateInput: {
* includeTerritories: true
* }
*
* Only allow capital letters, include territories and military zones
* stateInput: {
* caseSensitive: true,
* includeTerritories: true,
* includeMilitary: true
* }
*
*
*
*/
$.validator.addMethod("stateUS", function(value, element, options) {
var isDefault = typeof options === "undefined",
caseSensitive = ( isDefault || typeof options.caseSensitive === "undefined" ) ? false : options.caseSensitive,
includeTerritories = ( isDefault || typeof options.includeTerritories === "undefined" ) ? false : options.includeTerritories,
includeMilitary = ( isDefault || typeof options.includeMilitary === "undefined" ) ? false : options.includeMilitary,
regex;
if (!includeTerritories && !includeMilitary) {
regex = "^(A[KLRZ]|C[AOT]|D[CE]|FL|GA|HI|I[ADLN]|K[SY]|LA|M[ADEINOST]|N[CDEHJMVY]|O[HKR]|PA|RI|S[CD]|T[NX]|UT|V[AT]|W[AIVY])$";
} else if (includeTerritories && includeMilitary) {
regex = "^(A[AEKLPRSZ]|C[AOT]|D[CE]|FL|G[AU]|HI|I[ADLN]|K[SY]|LA|M[ADEINOPST]|N[CDEHJMVY]|O[HKR]|P[AR]|RI|S[CD]|T[NX]|UT|V[AIT]|W[AIVY])$";
} else if (includeTerritories) {
regex = "^(A[KLRSZ]|C[AOT]|D[CE]|FL|G[AU]|HI|I[ADLN]|K[SY]|LA|M[ADEINOPST]|N[CDEHJMVY]|O[HKR]|P[AR]|RI|S[CD]|T[NX]|UT|V[AIT]|W[AIVY])$";
} else {
regex = "^(A[AEKLPRZ]|C[AOT]|D[CE]|FL|GA|HI|I[ADLN]|K[SY]|LA|M[ADEINOST]|N[CDEHJMVY]|O[HKR]|PA|RI|S[CD]|T[NX]|UT|V[AT]|W[AIVY])$";
}
regex = caseSensitive ? new RegExp(regex) : new RegExp(regex, "i");
return this.optional(element) || regex.test(value);
},
"Please specify a valid state");
// TODO check if value starts with <, otherwise don't try stripping anything
$.validator.addMethod("strippedminlength", function(value, element, param) {
return $(value).text().length >= param;
}, $.validator.format("Please enter at least {0} characters"));
$.validator.addMethod("time", function(value, element) {
return this.optional(element) || /^([01]\d|2[0-3]|[0-9])(:[0-5]\d){1,2}$/.test(value);
}, "Please enter a valid time, between 00:00 and 23:59");
$.validator.addMethod("time12h", function(value, element) {
return this.optional(element) || /^((0?[1-9]|1[012])(:[0-5]\d){1,2}(\ ?[AP]M))$/i.test(value);
}, "Please enter a valid time in 12-hour am/pm format");
// same as url, but TLD is optional
$.validator.addMethod("url2", function(value, element) {
return this.optional(element) || /^(https?|ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)*(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test(value);
}, $.validator.messages.url);
/**
* Return true, if the value is a valid vehicle identification number (VIN).
*
* Works with all kind of text inputs.
*
* @example <input type="text" size="20" name="VehicleID" class="{required:true,vinUS:true}" />
* @desc Declares a required input element whose value must be a valid vehicle identification number.
*
* @name $.validator.methods.vinUS
* @type Boolean
* @cat Plugins/Validate/Methods
*/
$.validator.addMethod("vinUS", function(v) {
if (v.length !== 17) {
return false;
}
var LL = [ "A", "B", "C", "D", "E", "F", "G", "H", "J", "K", "L", "M", "N", "P", "R", "S", "T", "U", "V", "W", "X", "Y", "Z" ],
VL = [ 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 7, 9, 2, 3, 4, 5, 6, 7, 8, 9 ],
FL = [ 8, 7, 6, 5, 4, 3, 2, 10, 0, 9, 8, 7, 6, 5, 4, 3, 2 ],
rs = 0,
i, n, d, f, cd, cdv;
for (i = 0; i < 17; i++) {
f = FL[i];
d = v.slice(i, i + 1);
if (i === 8) {
cdv = d;
}
if (!isNaN(d)) {
d *= f;
} else {
for (n = 0; n < LL.length; n++) {
if (d.toUpperCase() === LL[n]) {
d = VL[n];
d *= f;
if (isNaN(cdv) && n === 8) {
cdv = LL[n];
}
break;
}
}
}
rs += d;
}
cd = rs % 11;
if (cd === 10) {
cd = "X";
}
if (cd === cdv) {
return true;
}
return false;
}, "The specified vehicle identification number (VIN) is invalid.");
$.validator.addMethod("zipcodeUS", function(value, element) {
return this.optional(element) || /^\d{5}(-\d{4})?$/.test(value);
}, "The specified US ZIP Code is invalid");
$.validator.addMethod("ziprange", function(value, element) {
return this.optional(element) || /^90[2-5]\d\{2\}-\d{4}$/.test(value);
}, "Your ZIP-code must be in the range 902xx-xxxx to 905xx-xxxx");
}));

+ 0
- 4
src/Web/WebStatus/wwwroot/lib/jquery-validation/dist/additional-methods.min.js
File diff suppressed because it is too large
View File


+ 0
- 1398
src/Web/WebStatus/wwwroot/lib/jquery-validation/dist/jquery.validate.js
File diff suppressed because it is too large
View File


+ 0
- 4
src/Web/WebStatus/wwwroot/lib/jquery-validation/dist/jquery.validate.min.js
File diff suppressed because it is too large
View File


BIN
azure-docs/builds/images/android-build-step1.png → vsts-docs/builds/images/android-build-step1.png View File


BIN
azure-docs/builds/images/android-build-step2.png → vsts-docs/builds/images/android-build-step2.png View File


BIN
azure-docs/builds/images/android-build-step3.png → vsts-docs/builds/images/android-build-step3.png View File


BIN
azure-docs/builds/images/android-build-step4.png → vsts-docs/builds/images/android-build-step4.png View File


BIN
azure-docs/builds/images/android-build-step5.png → vsts-docs/builds/images/android-build-step5.png View File


BIN
azure-docs/builds/images/android-build.png → vsts-docs/builds/images/android-build.png View File


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

Loading…
Cancel
Save