diff --git a/eShopOnContainers-ServicesAndWebApps.sln b/eShopOnContainers-ServicesAndWebApps.sln
index a01ca8a37..e633cf2ed 100644
--- a/eShopOnContainers-ServicesAndWebApps.sln
+++ b/eShopOnContainers-ServicesAndWebApps.sln
@@ -1,7 +1,7 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
-VisualStudioVersion = 15.0.26730.8
+VisualStudioVersion = 15.0.26730.12
MinimumVisualStudioVersion = 10.0.40219.1
Project("{E53339B2-1760-4266-BCC7-CA923CBCF16C}") = "docker-compose", "docker-compose.dcproj", "{FEA0C318-FFED-4D39-8781-265718CA43DD}"
EndProject
@@ -99,6 +99,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Health
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LoadTest", "test\Services\LoadTest\LoadTest.csproj", "{969E793C-C413-490E-9C9D-B2B46DA5AF32}"
EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "WebHost", "WebHost", "{1815B651-941C-466B-AE33-D1D7EEB8F77F}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WebHost.Customization", "src\BuildingBlocks\WebHostCustomization\WebHost.Customization\WebHost.Customization.csproj", "{15F4B3AA-89B6-4A0D-9051-414305974781}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Ad-Hoc|Any CPU = Ad-Hoc|Any CPU
@@ -1361,6 +1365,54 @@ Global
{969E793C-C413-490E-9C9D-B2B46DA5AF32}.Release|x64.Build.0 = Release|Any CPU
{969E793C-C413-490E-9C9D-B2B46DA5AF32}.Release|x86.ActiveCfg = Release|Any CPU
{969E793C-C413-490E-9C9D-B2B46DA5AF32}.Release|x86.Build.0 = Release|Any CPU
+ {15F4B3AA-89B6-4A0D-9051-414305974781}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
+ {15F4B3AA-89B6-4A0D-9051-414305974781}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
+ {15F4B3AA-89B6-4A0D-9051-414305974781}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU
+ {15F4B3AA-89B6-4A0D-9051-414305974781}.Ad-Hoc|ARM.Build.0 = Debug|Any CPU
+ {15F4B3AA-89B6-4A0D-9051-414305974781}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
+ {15F4B3AA-89B6-4A0D-9051-414305974781}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
+ {15F4B3AA-89B6-4A0D-9051-414305974781}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {15F4B3AA-89B6-4A0D-9051-414305974781}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {15F4B3AA-89B6-4A0D-9051-414305974781}.Ad-Hoc|x64.ActiveCfg = Debug|Any CPU
+ {15F4B3AA-89B6-4A0D-9051-414305974781}.Ad-Hoc|x64.Build.0 = Debug|Any CPU
+ {15F4B3AA-89B6-4A0D-9051-414305974781}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU
+ {15F4B3AA-89B6-4A0D-9051-414305974781}.Ad-Hoc|x86.Build.0 = Debug|Any CPU
+ {15F4B3AA-89B6-4A0D-9051-414305974781}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
+ {15F4B3AA-89B6-4A0D-9051-414305974781}.AppStore|Any CPU.Build.0 = Debug|Any CPU
+ {15F4B3AA-89B6-4A0D-9051-414305974781}.AppStore|ARM.ActiveCfg = Debug|Any CPU
+ {15F4B3AA-89B6-4A0D-9051-414305974781}.AppStore|ARM.Build.0 = Debug|Any CPU
+ {15F4B3AA-89B6-4A0D-9051-414305974781}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
+ {15F4B3AA-89B6-4A0D-9051-414305974781}.AppStore|iPhone.Build.0 = Debug|Any CPU
+ {15F4B3AA-89B6-4A0D-9051-414305974781}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {15F4B3AA-89B6-4A0D-9051-414305974781}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {15F4B3AA-89B6-4A0D-9051-414305974781}.AppStore|x64.ActiveCfg = Debug|Any CPU
+ {15F4B3AA-89B6-4A0D-9051-414305974781}.AppStore|x64.Build.0 = Debug|Any CPU
+ {15F4B3AA-89B6-4A0D-9051-414305974781}.AppStore|x86.ActiveCfg = Debug|Any CPU
+ {15F4B3AA-89B6-4A0D-9051-414305974781}.AppStore|x86.Build.0 = Debug|Any CPU
+ {15F4B3AA-89B6-4A0D-9051-414305974781}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {15F4B3AA-89B6-4A0D-9051-414305974781}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {15F4B3AA-89B6-4A0D-9051-414305974781}.Debug|ARM.ActiveCfg = Debug|Any CPU
+ {15F4B3AA-89B6-4A0D-9051-414305974781}.Debug|ARM.Build.0 = Debug|Any CPU
+ {15F4B3AA-89B6-4A0D-9051-414305974781}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+ {15F4B3AA-89B6-4A0D-9051-414305974781}.Debug|iPhone.Build.0 = Debug|Any CPU
+ {15F4B3AA-89B6-4A0D-9051-414305974781}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {15F4B3AA-89B6-4A0D-9051-414305974781}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {15F4B3AA-89B6-4A0D-9051-414305974781}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {15F4B3AA-89B6-4A0D-9051-414305974781}.Debug|x64.Build.0 = Debug|Any CPU
+ {15F4B3AA-89B6-4A0D-9051-414305974781}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {15F4B3AA-89B6-4A0D-9051-414305974781}.Debug|x86.Build.0 = Debug|Any CPU
+ {15F4B3AA-89B6-4A0D-9051-414305974781}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {15F4B3AA-89B6-4A0D-9051-414305974781}.Release|Any CPU.Build.0 = Release|Any CPU
+ {15F4B3AA-89B6-4A0D-9051-414305974781}.Release|ARM.ActiveCfg = Release|Any CPU
+ {15F4B3AA-89B6-4A0D-9051-414305974781}.Release|ARM.Build.0 = Release|Any CPU
+ {15F4B3AA-89B6-4A0D-9051-414305974781}.Release|iPhone.ActiveCfg = Release|Any CPU
+ {15F4B3AA-89B6-4A0D-9051-414305974781}.Release|iPhone.Build.0 = Release|Any CPU
+ {15F4B3AA-89B6-4A0D-9051-414305974781}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+ {15F4B3AA-89B6-4A0D-9051-414305974781}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+ {15F4B3AA-89B6-4A0D-9051-414305974781}.Release|x64.ActiveCfg = Release|Any CPU
+ {15F4B3AA-89B6-4A0D-9051-414305974781}.Release|x64.Build.0 = Release|Any CPU
+ {15F4B3AA-89B6-4A0D-9051-414305974781}.Release|x86.ActiveCfg = Release|Any CPU
+ {15F4B3AA-89B6-4A0D-9051-414305974781}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -1408,6 +1460,8 @@ Global
{69AF10D3-AA76-4FF7-B187-EC7E8CC5F5B8} = {807BB76E-B2BB-47A2-A57B-3D1B20FF5E7F}
{768C887F-C229-4B94-ACD8-0C7F65686524} = {A81ECBC2-6B00-4DCD-8388-469174033379}
{969E793C-C413-490E-9C9D-B2B46DA5AF32} = {EF0337F2-ED00-4643-89FD-EE10863F1870}
+ {1815B651-941C-466B-AE33-D1D7EEB8F77F} = {DB0EFB20-B024-4E5E-A75C-52143C131D25}
+ {15F4B3AA-89B6-4A0D-9051-414305974781} = {1815B651-941C-466B-AE33-D1D7EEB8F77F}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {25728519-5F0F-4973-8A64-0A81EB4EA8D9}
diff --git a/eShopOnContainers.sln b/eShopOnContainers.sln
index ae44be741..11d105423 100644
--- a/eShopOnContainers.sln
+++ b/eShopOnContainers.sln
@@ -1,7 +1,7 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
-VisualStudioVersion = 15.0.26730.8
+VisualStudioVersion = 15.0.26730.15
MinimumVisualStudioVersion = 10.0.40219.1
Project("{E53339B2-1760-4266-BCC7-CA923CBCF16C}") = "docker-compose", "docker-compose.dcproj", "{FEA0C318-FFED-4D39-8781-265718CA43DD}"
ProjectSection(ProjectDependencies) = postProject
@@ -60,7 +60,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WebSPA", "src\Web\WebSPA\We
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Mobile Apps", "Mobile Apps", "{B7B1D395-4E06-4036-BE86-C216756B9367}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "eShopOnContainers.UnitTests", "src\Mobile\eShopOnContainers\eShopOnContainers.UnitTests\eShopOnContainers.UnitTests.csproj", "{F7B6A162-BC4D-4924-B16A-713F9B0344E7}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "eShopOnContainers.UnitTests", "src\Mobile\eShopOnContainers\eShopOnContainers.UnitTests\eShopOnContainers.UnitTests.csproj", "{F7B6A162-BC4D-4924-B16A-713F9B0344E7}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "eShopOnContainers.TestRunner.Droid", "src\Mobile\eShopOnContainers\eShopOnContainers.TestRunner.Droid\eShopOnContainers.TestRunner.Droid.csproj", "{A289A7F0-ACD8-42AE-87B6-AB1AFD310BF1}"
EndProject
@@ -76,7 +76,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IntegrationTests", "test\Se
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "eShopOnContainers.UITests", "src\Mobile\eShopOnContainers\eShopOnContainers.UITests\eShopOnContainers.UITests.csproj", "{E3B18084-842C-4B80-8E4A-A7E588EC3137}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "eShopOnContainers.Core", "src\Mobile\eShopOnContainers\eShopOnContainers.Core\eShopOnContainers.Core.csproj", "{67F9D3A8-F71E-4428-913F-C37AE82CDB24}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "eShopOnContainers.Core", "src\Mobile\eShopOnContainers\eShopOnContainers.Core\eShopOnContainers.Core.csproj", "{67F9D3A8-F71E-4428-913F-C37AE82CDB24}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnitTest", "test\Services\UnitTest\UnitTest.csproj", "{7796F5D8-31FC-45A4-B673-19DE5BA194CF}"
EndProject
@@ -126,12 +126,14 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EventBus.Tests", "src\Build
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
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "WebHost", "WebHost", "{3E51A82A-5DE1-482E-BA46-F4FF3138B41A}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WebHost.Customization", "src\BuildingBlocks\WebHostCustomization\WebHost.Customization\WebHost.Customization.csproj", "{BF6AF4F9-684A-4EB3-8CF2-230AA2A03F98}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Ad-Hoc|Any CPU = Ad-Hoc|Any CPU
@@ -1781,54 +1783,6 @@ Global
{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
@@ -1877,6 +1831,54 @@ Global
{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
+ {BF6AF4F9-684A-4EB3-8CF2-230AA2A03F98}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
+ {BF6AF4F9-684A-4EB3-8CF2-230AA2A03F98}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
+ {BF6AF4F9-684A-4EB3-8CF2-230AA2A03F98}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU
+ {BF6AF4F9-684A-4EB3-8CF2-230AA2A03F98}.Ad-Hoc|ARM.Build.0 = Debug|Any CPU
+ {BF6AF4F9-684A-4EB3-8CF2-230AA2A03F98}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
+ {BF6AF4F9-684A-4EB3-8CF2-230AA2A03F98}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
+ {BF6AF4F9-684A-4EB3-8CF2-230AA2A03F98}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {BF6AF4F9-684A-4EB3-8CF2-230AA2A03F98}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {BF6AF4F9-684A-4EB3-8CF2-230AA2A03F98}.Ad-Hoc|x64.ActiveCfg = Debug|Any CPU
+ {BF6AF4F9-684A-4EB3-8CF2-230AA2A03F98}.Ad-Hoc|x64.Build.0 = Debug|Any CPU
+ {BF6AF4F9-684A-4EB3-8CF2-230AA2A03F98}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU
+ {BF6AF4F9-684A-4EB3-8CF2-230AA2A03F98}.Ad-Hoc|x86.Build.0 = Debug|Any CPU
+ {BF6AF4F9-684A-4EB3-8CF2-230AA2A03F98}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
+ {BF6AF4F9-684A-4EB3-8CF2-230AA2A03F98}.AppStore|Any CPU.Build.0 = Debug|Any CPU
+ {BF6AF4F9-684A-4EB3-8CF2-230AA2A03F98}.AppStore|ARM.ActiveCfg = Debug|Any CPU
+ {BF6AF4F9-684A-4EB3-8CF2-230AA2A03F98}.AppStore|ARM.Build.0 = Debug|Any CPU
+ {BF6AF4F9-684A-4EB3-8CF2-230AA2A03F98}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
+ {BF6AF4F9-684A-4EB3-8CF2-230AA2A03F98}.AppStore|iPhone.Build.0 = Debug|Any CPU
+ {BF6AF4F9-684A-4EB3-8CF2-230AA2A03F98}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {BF6AF4F9-684A-4EB3-8CF2-230AA2A03F98}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {BF6AF4F9-684A-4EB3-8CF2-230AA2A03F98}.AppStore|x64.ActiveCfg = Debug|Any CPU
+ {BF6AF4F9-684A-4EB3-8CF2-230AA2A03F98}.AppStore|x64.Build.0 = Debug|Any CPU
+ {BF6AF4F9-684A-4EB3-8CF2-230AA2A03F98}.AppStore|x86.ActiveCfg = Debug|Any CPU
+ {BF6AF4F9-684A-4EB3-8CF2-230AA2A03F98}.AppStore|x86.Build.0 = Debug|Any CPU
+ {BF6AF4F9-684A-4EB3-8CF2-230AA2A03F98}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {BF6AF4F9-684A-4EB3-8CF2-230AA2A03F98}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {BF6AF4F9-684A-4EB3-8CF2-230AA2A03F98}.Debug|ARM.ActiveCfg = Debug|Any CPU
+ {BF6AF4F9-684A-4EB3-8CF2-230AA2A03F98}.Debug|ARM.Build.0 = Debug|Any CPU
+ {BF6AF4F9-684A-4EB3-8CF2-230AA2A03F98}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+ {BF6AF4F9-684A-4EB3-8CF2-230AA2A03F98}.Debug|iPhone.Build.0 = Debug|Any CPU
+ {BF6AF4F9-684A-4EB3-8CF2-230AA2A03F98}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {BF6AF4F9-684A-4EB3-8CF2-230AA2A03F98}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {BF6AF4F9-684A-4EB3-8CF2-230AA2A03F98}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {BF6AF4F9-684A-4EB3-8CF2-230AA2A03F98}.Debug|x64.Build.0 = Debug|Any CPU
+ {BF6AF4F9-684A-4EB3-8CF2-230AA2A03F98}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {BF6AF4F9-684A-4EB3-8CF2-230AA2A03F98}.Debug|x86.Build.0 = Debug|Any CPU
+ {BF6AF4F9-684A-4EB3-8CF2-230AA2A03F98}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {BF6AF4F9-684A-4EB3-8CF2-230AA2A03F98}.Release|Any CPU.Build.0 = Release|Any CPU
+ {BF6AF4F9-684A-4EB3-8CF2-230AA2A03F98}.Release|ARM.ActiveCfg = Release|Any CPU
+ {BF6AF4F9-684A-4EB3-8CF2-230AA2A03F98}.Release|ARM.Build.0 = Release|Any CPU
+ {BF6AF4F9-684A-4EB3-8CF2-230AA2A03F98}.Release|iPhone.ActiveCfg = Release|Any CPU
+ {BF6AF4F9-684A-4EB3-8CF2-230AA2A03F98}.Release|iPhone.Build.0 = Release|Any CPU
+ {BF6AF4F9-684A-4EB3-8CF2-230AA2A03F98}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+ {BF6AF4F9-684A-4EB3-8CF2-230AA2A03F98}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+ {BF6AF4F9-684A-4EB3-8CF2-230AA2A03F98}.Release|x64.ActiveCfg = Release|Any CPU
+ {BF6AF4F9-684A-4EB3-8CF2-230AA2A03F98}.Release|x64.Build.0 = Release|Any CPU
+ {BF6AF4F9-684A-4EB3-8CF2-230AA2A03F98}.Release|x86.ActiveCfg = Release|Any CPU
+ {BF6AF4F9-684A-4EB3-8CF2-230AA2A03F98}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -1934,8 +1936,12 @@ Global
{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}
+ {3E51A82A-5DE1-482E-BA46-F4FF3138B41A} = {1EF3AC0F-F27C-46DD-AC53-D762D2C11C45}
+ {BF6AF4F9-684A-4EB3-8CF2-230AA2A03F98} = {3E51A82A-5DE1-482E-BA46-F4FF3138B41A}
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {A6439048-F270-4A9E-A350-63C7BE2BB322}
EndGlobalSection
EndGlobal
diff --git a/img/sf/cloud-config-idsrv.PNG b/img/sf/cloud-config-idsrv.PNG
new file mode 100644
index 000000000..86fbe6637
Binary files /dev/null and b/img/sf/cloud-config-idsrv.PNG differ
diff --git a/img/sf/cloud-config-mvc.PNG b/img/sf/cloud-config-mvc.PNG
new file mode 100644
index 000000000..def121836
Binary files /dev/null and b/img/sf/cloud-config-mvc.PNG differ
diff --git a/img/sf/cloud-config-spa.PNG b/img/sf/cloud-config-spa.PNG
new file mode 100644
index 000000000..17809ea2d
Binary files /dev/null and b/img/sf/cloud-config-spa.PNG differ
diff --git a/img/sf/cloud-config.PNG b/img/sf/cloud-config.PNG
new file mode 100644
index 000000000..420b95e1c
Binary files /dev/null and b/img/sf/cloud-config.PNG differ
diff --git a/img/sf/explorer-apps-status.PNG b/img/sf/explorer-apps-status.PNG
new file mode 100644
index 000000000..f748cbaab
Binary files /dev/null and b/img/sf/explorer-apps-status.PNG differ
diff --git a/img/sf/explorer-deployment-status.PNG b/img/sf/explorer-deployment-status.PNG
new file mode 100644
index 000000000..2697a6374
Binary files /dev/null and b/img/sf/explorer-deployment-status.PNG differ
diff --git a/img/sf/publish-button.PNG b/img/sf/publish-button.PNG
new file mode 100644
index 000000000..8f84091bc
Binary files /dev/null and b/img/sf/publish-button.PNG differ
diff --git a/img/sf/publish-window.PNG b/img/sf/publish-window.PNG
new file mode 100644
index 000000000..4c27b8e29
Binary files /dev/null and b/img/sf/publish-window.PNG differ
diff --git a/img/sf/sf-directory.PNG b/img/sf/sf-directory.PNG
new file mode 100644
index 000000000..f6b518a5d
Binary files /dev/null and b/img/sf/sf-directory.PNG differ
diff --git a/src/BuildingBlocks/WebHostCustomization/WebHost.Customization/WebHost.Customization.csproj b/src/BuildingBlocks/WebHostCustomization/WebHost.Customization/WebHost.Customization.csproj
new file mode 100644
index 000000000..d9ddd56e9
--- /dev/null
+++ b/src/BuildingBlocks/WebHostCustomization/WebHost.Customization/WebHost.Customization.csproj
@@ -0,0 +1,11 @@
+
+
+
+ netcoreapp2.0
+
+
+
+
+
+
+
diff --git a/src/BuildingBlocks/WebHostCustomization/WebHost.Customization/WebHostExtensions.cs b/src/BuildingBlocks/WebHostCustomization/WebHost.Customization/WebHostExtensions.cs
new file mode 100644
index 000000000..ecaceeab0
--- /dev/null
+++ b/src/BuildingBlocks/WebHostCustomization/WebHost.Customization/WebHostExtensions.cs
@@ -0,0 +1,40 @@
+using Microsoft.EntityFrameworkCore;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Logging;
+using System;
+
+namespace Microsoft.AspNetCore.Hosting
+{
+ public static class IWebHostExtensions
+ {
+ public static IWebHost MigrateDbContext(this IWebHost webHost, Action seeder) where TContext : DbContext
+ {
+ using (var scope = webHost.Services.CreateScope())
+ {
+ var services = scope.ServiceProvider;
+
+ var logger = services.GetRequiredService>();
+
+ var context = services.GetService();
+
+ try
+ {
+ logger.LogInformation($"Migrating database associated with context {typeof(TContext).Name}");
+
+ context.Database
+ .Migrate();
+
+ seeder(context,services);
+
+ logger.LogInformation($"Migrated database associated with context {typeof(TContext).Name}");
+ }
+ catch (Exception ex)
+ {
+ logger.LogError(ex, $"An error occurred while migrating the database used on context {typeof(TContext).Name}");
+ }
+ }
+
+ return webHost;
+ }
+ }
+}
diff --git a/src/Services/Basket/Basket.API/Model/Basket.cs b/src/Services/Basket/Basket.API/Model/CustomerBasket.cs
similarity index 100%
rename from src/Services/Basket/Basket.API/Model/Basket.cs
rename to src/Services/Basket/Basket.API/Model/CustomerBasket.cs
diff --git a/src/Services/Catalog/Catalog.API/Catalog.API.csproj b/src/Services/Catalog/Catalog.API/Catalog.API.csproj
index de280179f..0d8c77efd 100644
--- a/src/Services/Catalog/Catalog.API/Catalog.API.csproj
+++ b/src/Services/Catalog/Catalog.API/Catalog.API.csproj
@@ -53,6 +53,7 @@
+
diff --git a/src/Services/Catalog/Catalog.API/Infrastructure/CatalogContext.cs b/src/Services/Catalog/Catalog.API/Infrastructure/CatalogContext.cs
index b0dd2a082..8cff66b08 100644
--- a/src/Services/Catalog/Catalog.API/Infrastructure/CatalogContext.cs
+++ b/src/Services/Catalog/Catalog.API/Infrastructure/CatalogContext.cs
@@ -3,6 +3,7 @@
using Microsoft.EntityFrameworkCore;
using EntityConfigurations;
using Model;
+ using Microsoft.EntityFrameworkCore.Design;
public class CatalogContext : DbContext
{
@@ -20,4 +21,16 @@
builder.ApplyConfiguration(new CatalogItemEntityTypeConfiguration());
}
}
+
+
+ public class CatalogContextDesignFactory : IDesignTimeDbContextFactory
+ {
+ public CatalogContext CreateDbContext(string[] args)
+ {
+ var optionsBuilder = new DbContextOptionsBuilder()
+ .UseSqlServer("Server=.;Initial Catalog=Microsoft.eShopOnContainers.Services.CatalogDb;Integrated Security=true");
+
+ return new CatalogContext(optionsBuilder.Options);
+ }
+ }
}
diff --git a/src/Services/Catalog/Catalog.API/Infrastructure/CatalogContextSeed.cs b/src/Services/Catalog/Catalog.API/Infrastructure/CatalogContextSeed.cs
index 6f71bd6cf..42ac7b740 100644
--- a/src/Services/Catalog/Catalog.API/Infrastructure/CatalogContextSeed.cs
+++ b/src/Services/Catalog/Catalog.API/Infrastructure/CatalogContextSeed.cs
@@ -1,15 +1,14 @@
namespace Microsoft.eShopOnContainers.Services.Catalog.API.Infrastructure
{
- using EntityFrameworkCore;
using Extensions.Logging;
using global::Catalog.API.Extensions;
- using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
- using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Model;
+ using Polly;
using System;
using System.Collections.Generic;
+ using System.Data.SqlClient;
using System.Globalization;
using System.IO;
using System.IO.Compression;
@@ -19,56 +18,48 @@
public class CatalogContextSeed
{
- public static async Task SeedAsync(IApplicationBuilder applicationBuilder, IHostingEnvironment env, ILoggerFactory loggerFactory, int? retry = 0)
+ public async Task SeedAsync(CatalogContext context,IHostingEnvironment env,IOptions settings,ILogger logger)
{
- var log = loggerFactory.CreateLogger("catalog seed");
+ var policy = CreatePolicy(logger, nameof(CatalogContextSeed));
- var context = (CatalogContext)applicationBuilder
- .ApplicationServices.GetService(typeof(CatalogContext));
-
- context.Database.Migrate();
-
- var settings = (CatalogSettings)applicationBuilder
- .ApplicationServices.GetRequiredService>().Value;
-
- var useCustomizationData = settings.UseCustomizationData;
- var contentRootPath = env.ContentRootPath;
- var picturePath = env.WebRootPath;
-
- if (!context.CatalogBrands.Any())
+ await policy.ExecuteAsync(async () =>
{
- context.CatalogBrands.AddRange(useCustomizationData
- ? GetCatalogBrandsFromFile(contentRootPath, log)
- : GetPreconfiguredCatalogBrands()
- );
+ var useCustomizationData = settings.Value.UseCustomizationData;
+ var contentRootPath = env.ContentRootPath;
+ var picturePath = env.WebRootPath;
- await context.SaveChangesAsync();
- }
+ if (!context.CatalogBrands.Any())
+ {
+ context.CatalogBrands.AddRange(useCustomizationData
+ ? GetCatalogBrandsFromFile(contentRootPath, logger)
+ : GetPreconfiguredCatalogBrands());
- if (!context.CatalogTypes.Any())
- {
- context.CatalogTypes.AddRange(useCustomizationData
- ? GetCatalogTypesFromFile(contentRootPath, log)
- : GetPreconfiguredCatalogTypes()
- );
+ await context.SaveChangesAsync();
+ }
- await context.SaveChangesAsync();
- }
+ if (!context.CatalogTypes.Any())
+ {
+ context.CatalogTypes.AddRange(useCustomizationData
+ ? GetCatalogTypesFromFile(contentRootPath, logger)
+ : GetPreconfiguredCatalogTypes());
- if (!context.CatalogItems.Any())
- {
- context.CatalogItems.AddRange(useCustomizationData
- ? GetCatalogItemsFromFile(contentRootPath, context, log)
- : GetPreconfiguredItems()
- );
+ await context.SaveChangesAsync();
+ }
- await context.SaveChangesAsync();
+ if (!context.CatalogItems.Any())
+ {
+ context.CatalogItems.AddRange(useCustomizationData
+ ? GetCatalogItemsFromFile(contentRootPath, context, logger)
+ : GetPreconfiguredItems());
- GetCatalogItemPictures(contentRootPath, picturePath);
- }
+ await context.SaveChangesAsync();
+
+ GetCatalogItemPictures(contentRootPath, picturePath);
+ }
+ });
}
- static IEnumerable GetCatalogBrandsFromFile(string contentRootPath, ILogger log)
+ private IEnumerable GetCatalogBrandsFromFile(string contentRootPath, ILogger logger)
{
string csvFileCatalogBrands = Path.Combine(contentRootPath, "Setup", "CatalogBrands.csv");
@@ -85,18 +76,18 @@
}
catch (Exception ex)
{
- log.LogError(ex.Message);
+ logger.LogError(ex.Message);
return GetPreconfiguredCatalogBrands();
}
return File.ReadAllLines(csvFileCatalogBrands)
.Skip(1) // skip header row
.SelectTry(x => CreateCatalogBrand(x))
- .OnCaughtException(ex => { log.LogError(ex.Message); return null; })
+ .OnCaughtException(ex => { logger.LogError(ex.Message); return null; })
.Where(x => x != null);
}
- static CatalogBrand CreateCatalogBrand(string brand)
+ private CatalogBrand CreateCatalogBrand(string brand)
{
brand = brand.Trim('"').Trim();
@@ -111,7 +102,7 @@
};
}
- static IEnumerable GetPreconfiguredCatalogBrands()
+ private IEnumerable GetPreconfiguredCatalogBrands()
{
return new List()
{
@@ -123,7 +114,7 @@
};
}
- static IEnumerable GetCatalogTypesFromFile(string contentRootPath, ILogger log)
+ private IEnumerable GetCatalogTypesFromFile(string contentRootPath, ILogger logger)
{
string csvFileCatalogTypes = Path.Combine(contentRootPath, "Setup", "CatalogTypes.csv");
@@ -140,18 +131,18 @@
}
catch (Exception ex)
{
- log.LogError(ex.Message);
+ logger.LogError(ex.Message);
return GetPreconfiguredCatalogTypes();
}
return File.ReadAllLines(csvFileCatalogTypes)
.Skip(1) // skip header row
.SelectTry(x => CreateCatalogType(x))
- .OnCaughtException(ex => { log.LogError(ex.Message); return null; })
+ .OnCaughtException(ex => { logger.LogError(ex.Message); return null; })
.Where(x => x != null);
}
- static CatalogType CreateCatalogType(string type)
+ private CatalogType CreateCatalogType(string type)
{
type = type.Trim('"').Trim();
@@ -166,7 +157,7 @@
};
}
- static IEnumerable GetPreconfiguredCatalogTypes()
+ private IEnumerable GetPreconfiguredCatalogTypes()
{
return new List()
{
@@ -177,7 +168,7 @@
};
}
- static IEnumerable GetCatalogItemsFromFile(string contentRootPath, CatalogContext context, ILogger log)
+ private IEnumerable GetCatalogItemsFromFile(string contentRootPath, CatalogContext context, ILogger logger)
{
string csvFileCatalogItems = Path.Combine(contentRootPath, "Setup", "CatalogItems.csv");
@@ -195,7 +186,7 @@
}
catch (Exception ex)
{
- log.LogError(ex.Message);
+ logger.LogError(ex.Message);
return GetPreconfiguredItems();
}
@@ -206,11 +197,11 @@
.Skip(1) // skip header row
.Select(row => Regex.Split(row, ",(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)") )
.SelectTry(column => CreateCatalogItem(column, csvheaders, catalogTypeIdLookup, catalogBrandIdLookup))
- .OnCaughtException(ex => { log.LogError(ex.Message); return null; })
+ .OnCaughtException(ex => { logger.LogError(ex.Message); return null; })
.Where(x => x != null);
}
- static CatalogItem CreateCatalogItem(string[] column, string[] headers, Dictionary catalogTypeIdLookup, Dictionary catalogBrandIdLookup)
+ private CatalogItem CreateCatalogItem(string[] column, string[] headers, Dictionary catalogTypeIdLookup, Dictionary catalogBrandIdLookup)
{
if (column.Count() != headers.Count())
{
@@ -316,7 +307,7 @@
return catalogItem;
}
- static IEnumerable GetPreconfiguredItems()
+ private IEnumerable GetPreconfiguredItems()
{
return new List()
{
@@ -335,7 +326,7 @@
};
}
- static string[] GetHeaders(string csvfile, string[] requiredHeaders, string[] optionalHeaders = null)
+ private string[] GetHeaders(string csvfile, string[] requiredHeaders, string[] optionalHeaders = null)
{
string[] csvheaders = File.ReadLines(csvfile).First().ToLowerInvariant().Split(',');
@@ -363,7 +354,7 @@
return csvheaders;
}
- static void GetCatalogItemPictures(string contentRootPath, string picturePath)
+ private void GetCatalogItemPictures(string contentRootPath, string picturePath)
{
DirectoryInfo directory = new DirectoryInfo(picturePath);
foreach (FileInfo file in directory.GetFiles())
@@ -374,7 +365,18 @@
string zipFileCatalogItemPictures = Path.Combine(contentRootPath, "Setup", "CatalogItems.zip");
ZipFile.ExtractToDirectory(zipFileCatalogItemPictures, picturePath);
}
- }
-
+ private Policy CreatePolicy( ILogger logger, string prefix,int retries = 3)
+ {
+ return Policy.Handle().
+ WaitAndRetryAsync(
+ retryCount: retries,
+ sleepDurationProvider: retry => TimeSpan.FromSeconds(5),
+ onRetry: (exception, timeSpan, retry, ctx) =>
+ {
+ logger.LogTrace($"[{prefix}] Exception {exception.GetType().Name} with message ${exception.Message} detected on attempt {retry} of {retries}");
+ }
+ );
+ }
+ }
}
diff --git a/src/Services/Catalog/Catalog.API/Program.cs b/src/Services/Catalog/Catalog.API/Program.cs
index 2de3600b9..1eeeeb5ec 100644
--- a/src/Services/Catalog/Catalog.API/Program.cs
+++ b/src/Services/Catalog/Catalog.API/Program.cs
@@ -1,15 +1,31 @@
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
+using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF;
+using Microsoft.eShopOnContainers.Services.Catalog.API.Infrastructure;
+using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Options;
using System.IO;
-
namespace Microsoft.eShopOnContainers.Services.Catalog.API
{
public class Program
{
public static void Main(string[] args)
{
- BuildWebHost(args).Run();
+ BuildWebHost(args)
+ .MigrateDbContext((context,services)=>
+ {
+ var env = services.GetService();
+ var settings = services.GetService>();
+ var logger = services.GetService>();
+
+ new CatalogContextSeed()
+ .SeedAsync(context,env,settings,logger)
+ .Wait();
+
+ })
+ .MigrateDbContext((_,__)=> { })
+ .Run();
}
public static IWebHost BuildWebHost(string[] args) =>
diff --git a/src/Services/Catalog/Catalog.API/Startup.cs b/src/Services/Catalog/Catalog.API/Startup.cs
index 21b9ae1c8..8bfa347d2 100644
--- a/src/Services/Catalog/Catalog.API/Startup.cs
+++ b/src/Services/Catalog/Catalog.API/Startup.cs
@@ -9,7 +9,6 @@
using Microsoft.Azure.ServiceBus;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Diagnostics;
- using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus;
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions;
using Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ;
@@ -24,15 +23,10 @@
using Microsoft.Extensions.HealthChecks;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
- using Microsoft.WindowsAzure.Storage;
- using Microsoft.WindowsAzure.Storage.Auth;
- using Polly;
using RabbitMQ.Client;
using System;
using System.Data.Common;
- using System.Data.SqlClient;
using System.Reflection;
- using System.Threading.Tasks;
public class Startup
{
@@ -85,6 +79,13 @@
//Check Client vs. Server evaluation: https://docs.microsoft.com/en-us/ef/core/querying/client-eval
});
+ services.AddDbContext(options =>
+ {
+ options.UseSqlServer(Configuration["ConnectionString"], opts =>
+ opts.MigrationsAssembly("Catalog.API"));
+ });
+
+
services.Configure(Configuration);
// Add framework services.
@@ -184,43 +185,7 @@
c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
});
- var context = (CatalogContext)app
- .ApplicationServices.GetService(typeof(CatalogContext));
-
- WaitForSqlAvailabilityAsync(context, loggerFactory, app, env).Wait();
-
ConfigureEventBus(app);
-
- var integrationEventLogContext = new IntegrationEventLogContext(
- new DbContextOptionsBuilder()
- .UseSqlServer(Configuration["ConnectionString"], b => b.MigrationsAssembly("Catalog.API"))
- .Options);
-
- integrationEventLogContext.Database.Migrate();
- }
-
- private async Task WaitForSqlAvailabilityAsync(CatalogContext ctx, ILoggerFactory loggerFactory, IApplicationBuilder app, IHostingEnvironment env, int retries = 0)
- {
- var logger = loggerFactory.CreateLogger(nameof(Startup));
- var policy = CreatePolicy(retries, logger, nameof(WaitForSqlAvailabilityAsync));
- await policy.ExecuteAsync(async () =>
- {
- await CatalogContextSeed.SeedAsync(app, env, loggerFactory);
- });
-
- }
-
- private Policy CreatePolicy(int retries, ILogger logger, string prefix)
- {
- return Policy.Handle().
- WaitAndRetryAsync(
- retryCount: retries,
- sleepDurationProvider: retry => TimeSpan.FromSeconds(5),
- onRetry: (exception, timeSpan, retry, ctx) =>
- {
- logger.LogTrace($"[{prefix}] Exception {exception.GetType().Name} with message ${exception.Message} detected on attempt {retry} of {retries}");
- }
- );
}
private void RegisterEventBus(IServiceCollection services)
diff --git a/src/Services/Identity/Identity.API/AppSettings.cs b/src/Services/Identity/Identity.API/AppSettings.cs
index 78d848d41..1f45763fe 100644
--- a/src/Services/Identity/Identity.API/AppSettings.cs
+++ b/src/Services/Identity/Identity.API/AppSettings.cs
@@ -1,13 +1,9 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading.Tasks;
-
-namespace eShopOnContainers.Identity
+namespace Microsoft.eShopOnContainers.Services.Identity.API
{
public class AppSettings
{
public string MvcClient { get; set; }
+
public bool UseCustomizationData { get; set; }
}
}
diff --git a/src/Services/Identity/Identity.API/Certificate/Certificate.cs b/src/Services/Identity/Identity.API/Certificate/Certificate.cs
index f779017fe..d20726d12 100644
--- a/src/Services/Identity/Identity.API/Certificate/Certificate.cs
+++ b/src/Services/Identity/Identity.API/Certificate/Certificate.cs
@@ -1,11 +1,8 @@
-// Copyright (c) Brock Allen & Dominick Baier. All rights reserved.
-// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.
-
-using System.IO;
+using System.IO;
using System.Reflection;
using System.Security.Cryptography.X509Certificates;
-namespace Identity.API.Certificate
+namespace Microsoft.eShopOnContainers.Services.Identity.API.Certificates
{
static class Certificate
{
diff --git a/src/Services/Identity/Identity.API/Configuration/Config.cs b/src/Services/Identity/Identity.API/Configuration/Config.cs
index 89d5c0dc7..969b86aa1 100644
--- a/src/Services/Identity/Identity.API/Configuration/Config.cs
+++ b/src/Services/Identity/Identity.API/Configuration/Config.cs
@@ -2,7 +2,7 @@
using IdentityServer4.Models;
using System.Collections.Generic;
-namespace Identity.API.Configuration
+namespace Microsoft.eShopOnContainers.Services.Identity.API.Configuration
{
public class Config
{
diff --git a/src/Services/Identity/Identity.API/Controllers/AccountController.cs b/src/Services/Identity/Identity.API/Controllers/AccountController.cs
index 02b50129f..79e9c247e 100644
--- a/src/Services/Identity/Identity.API/Controllers/AccountController.cs
+++ b/src/Services/Identity/Identity.API/Controllers/AccountController.cs
@@ -1,29 +1,23 @@
-// Copyright (c) Brock Allen & Dominick Baier. All rights reserved.
-// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.
-
-
-using IdentityModel;
-using IdentityServer4.Quickstart.UI.Models;
+using IdentityModel;
+using IdentityServer4;
+using IdentityServer4.Models;
using IdentityServer4.Services;
-using Microsoft.AspNetCore.Http.Authentication;
+using IdentityServer4.Stores;
+using Microsoft.AspNetCore.Authentication;
+using Microsoft.AspNetCore.Authorization;
+using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
+using Microsoft.eShopOnContainers.Services.Identity.API.Models;
+using Microsoft.eShopOnContainers.Services.Identity.API.Models.AccountViewModels;
+using Microsoft.eShopOnContainers.Services.Identity.API.Services;
+using Microsoft.Extensions.Logging;
using System;
-using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Text.Encodings.Web;
using System.Threading.Tasks;
-using IdentityServer4.Models;
-using IdentityServer4.Stores;
-using Identity.API.Services;
-using Identity.API.Models;
-using Microsoft.Extensions.Logging;
-using Microsoft.AspNetCore.Authorization;
-using Identity.API.Models.AccountViewModels;
-using Microsoft.AspNetCore.Identity;
-using Microsoft.AspNetCore.Authentication;
-namespace IdentityServer4.Quickstart.UI.Controllers
+namespace Microsoft.eShopOnContainers.Services.Identity.API.Controllers
{
///
/// This sample controller implements a typical login/logout/provision workflow for local and external accounts.
@@ -36,7 +30,7 @@ namespace IdentityServer4.Quickstart.UI.Controllers
private readonly ILoginService _loginService;
private readonly IIdentityServerInteractionService _interaction;
private readonly IClientStore _clientStore;
- private readonly ILogger _logger;
+ private readonly ILogger _logger;
private readonly UserManager _userManager;
public AccountController(
@@ -45,13 +39,13 @@ namespace IdentityServer4.Quickstart.UI.Controllers
ILoginService loginService,
IIdentityServerInteractionService interaction,
IClientStore clientStore,
- ILoggerFactory loggerFactory,
+ ILogger logger,
UserManager userManager)
{
_loginService = loginService;
_interaction = interaction;
_clientStore = clientStore;
- _logger = loggerFactory.CreateLogger();
+ _logger = logger;
_userManager = userManager;
}
@@ -69,6 +63,7 @@ namespace IdentityServer4.Quickstart.UI.Controllers
}
var vm = await BuildLoginViewModelAsync(returnUrl, context);
+
ViewData["ReturnUrl"] = returnUrl;
return View(vm);
@@ -97,6 +92,7 @@ namespace IdentityServer4.Quickstart.UI.Controllers
};
await _loginService.SignIn(user);
+
// make sure the returnUrl is still valid, and if yes - redirect back to authorize endpoint
if (_interaction.IsValidReturnUrl(model.ReturnUrl))
{
@@ -111,7 +107,9 @@ namespace IdentityServer4.Quickstart.UI.Controllers
// something went wrong, show form with error
var vm = await BuildLoginViewModelAsync(model);
+
ViewData["ReturnUrl"] = model.ReturnUrl;
+
return View(vm);
}
@@ -180,6 +178,7 @@ namespace IdentityServer4.Quickstart.UI.Controllers
public async Task Logout(LogoutViewModel model)
{
var idp = User?.FindFirst(JwtClaimTypes.IdentityProvider)?.Value;
+
if (idp != null && idp != IdentityServerConstants.LocalIdentityProvider)
{
if (model.LogoutId == null)
@@ -191,10 +190,15 @@ namespace IdentityServer4.Quickstart.UI.Controllers
}
string url = "/Account/Logout?logoutId=" + model.LogoutId;
+
try
{
+
// hack: try/catch to handle social providers that throw
- await HttpContext.Authentication.SignOutAsync(idp, new AuthenticationProperties { RedirectUri = url });
+ await HttpContext.SignOutAsync(idp, new AuthenticationProperties
+ {
+ RedirectUri = url
+ });
}
catch (Exception ex)
{
@@ -203,7 +207,7 @@ namespace IdentityServer4.Quickstart.UI.Controllers
}
// delete authentication cookie
- await HttpContext.Authentication.SignOutAsync();
+ await HttpContext.SignOutAsync();
// set this so UI rendering sees an anonymous user
HttpContext.User = new ClaimsPrincipal(new ClaimsIdentity());
@@ -217,7 +221,7 @@ namespace IdentityServer4.Quickstart.UI.Controllers
public async Task DeviceLogOut(string redirectUrl)
{
// delete authentication cookie
- await HttpContext.Authentication.SignOutAsync();
+ await HttpContext.SignOutAsync();
// set this so UI rendering sees an anonymous user
HttpContext.User = new ClaimsPrincipal(new ClaimsIdentity());
diff --git a/src/Services/Identity/Identity.API/Controllers/ConsentController.cs b/src/Services/Identity/Identity.API/Controllers/ConsentController.cs
index a5687dd31..095440d6b 100644
--- a/src/Services/Identity/Identity.API/Controllers/ConsentController.cs
+++ b/src/Services/Identity/Identity.API/Controllers/ConsentController.cs
@@ -1,19 +1,13 @@
-// Copyright (c) Brock Allen & Dominick Baier. All rights reserved.
-// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.
-
-
+using IdentityServer4.Models;
using IdentityServer4.Services;
+using IdentityServer4.Stores;
using Microsoft.AspNetCore.Mvc;
+using Microsoft.eShopOnContainers.Services.Identity.API.Models.AccountViewModels;
using Microsoft.Extensions.Logging;
using System.Linq;
using System.Threading.Tasks;
-using IdentityServer4.Models;
-using IdentityServer4.Stores;
-using IdentityServer4.Quickstart.UI.Models;
-using Identity.API.Models.AccountViewModels;
-using Identity.API.Services;
-namespace IdentityServer4.Quickstart.UI.Controllers
+namespace Microsoft.eShopOnContainers.Services.Identity.API.Controllers
{
///
/// This controller implements the consent logic
diff --git a/src/Services/Identity/Identity.API/Controllers/HomeController.cs b/src/Services/Identity/Identity.API/Controllers/HomeController.cs
index f21ab65e0..66931b764 100644
--- a/src/Services/Identity/Identity.API/Controllers/HomeController.cs
+++ b/src/Services/Identity/Identity.API/Controllers/HomeController.cs
@@ -1,16 +1,12 @@
-// Copyright (c) Brock Allen & Dominick Baier. All rights reserved.
-// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.
-
-
-using eShopOnContainers.Identity;
-using Identity.API.Services;
-using IdentityServer4.Quickstart.UI.Models;
+
using IdentityServer4.Services;
using Microsoft.AspNetCore.Mvc;
+using Microsoft.eShopOnContainers.Services.Identity.API.Models;
+using Microsoft.eShopOnContainers.Services.Identity.API.Services;
using Microsoft.Extensions.Options;
using System.Threading.Tasks;
-namespace IdentityServer4.Quickstart.UI.Controllers
+namespace Microsoft.eShopOnContainers.Services.Identity.API.Controllers
{
public class HomeController : Controller
{
diff --git a/src/Services/Identity/Identity.API/Data/ApplicationDbContext.cs b/src/Services/Identity/Identity.API/Data/ApplicationDbContext.cs
index ddbe7bbfd..aec67258c 100644
--- a/src/Services/Identity/Identity.API/Data/ApplicationDbContext.cs
+++ b/src/Services/Identity/Identity.API/Data/ApplicationDbContext.cs
@@ -1,12 +1,8 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading.Tasks;
-using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
+using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
-using Identity.API.Models;
+using Microsoft.eShopOnContainers.Services.Identity.API.Models;
-namespace Identity.API.Data
+namespace Microsoft.eShopOnContainers.Services.Identity.API.Data
{
public class ApplicationDbContext : IdentityDbContext
{
diff --git a/src/Services/Identity/Identity.API/Data/ApplicationContextSeed.cs b/src/Services/Identity/Identity.API/Data/ApplicationDbContextSeed.cs
similarity index 76%
rename from src/Services/Identity/Identity.API/Data/ApplicationContextSeed.cs
rename to src/Services/Identity/Identity.API/Data/ApplicationDbContextSeed.cs
index 0f81bcf66..3dbf28171 100644
--- a/src/Services/Identity/Identity.API/Data/ApplicationContextSeed.cs
+++ b/src/Services/Identity/Identity.API/Data/ApplicationDbContextSeed.cs
@@ -1,57 +1,40 @@
-namespace Microsoft.eShopOnContainers.Services.Catalog.API.Infrastructure
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.AspNetCore.Identity;
+using Microsoft.eShopOnContainers.Services.Identity.API.Extensions;
+using Microsoft.eShopOnContainers.Services.Identity.API.Models;
+using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Options;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.IO.Compression;
+using System.Linq;
+using System.Text.RegularExpressions;
+using System.Threading.Tasks;
+
+namespace Microsoft.eShopOnContainers.Services.Identity.API.Data
{
- using AspNetCore.Identity;
- using EntityFrameworkCore;
- using Extensions.Logging;
- using global::eShopOnContainers.Identity;
- using global::Identity.API.Data;
- using global::Identity.API.Models;
- using Identity.API.Extensions;
- using Microsoft.AspNetCore.Builder;
- using Microsoft.AspNetCore.Hosting;
- using Microsoft.Extensions.DependencyInjection;
- using Microsoft.Extensions.Options;
- using System;
- using System.Collections.Generic;
- using System.IO;
- using System.IO.Compression;
- using System.Linq;
- using System.Security.Cryptography;
- using System.Text.RegularExpressions;
- using System.Threading.Tasks;
-
- public class ApplicationContextSeed
- {
- private readonly IPasswordHasher _passwordHasher;
- public ApplicationContextSeed(IPasswordHasher passwordHasher)
- {
- _passwordHasher = passwordHasher;
- }
- public async Task SeedAsync(IApplicationBuilder applicationBuilder, IHostingEnvironment env, ILoggerFactory loggerFactory, int? retry = 0)
+ public class ApplicationDbContextSeed
+ {
+ private readonly IPasswordHasher _passwordHasher = new PasswordHasher();
+
+ public async Task SeedAsync(ApplicationDbContext context,IHostingEnvironment env,
+ ILogger logger, IOptions settings,int? retry = 0)
{
int retryForAvaiability = retry.Value;
+
try
{
- var log = loggerFactory.CreateLogger("application seed");
-
- var context = (ApplicationDbContext)applicationBuilder
- .ApplicationServices.GetService(typeof(ApplicationDbContext));
-
- context.Database.Migrate();
-
- var settings = (AppSettings)applicationBuilder
- .ApplicationServices.GetRequiredService>().Value;
-
- var useCustomizationData = settings.UseCustomizationData;
+ var useCustomizationData = settings.Value.UseCustomizationData;
var contentRootPath = env.ContentRootPath;
var webroot = env.WebRootPath;
if (!context.Users.Any())
{
context.Users.AddRange(useCustomizationData
- ? GetUsersFromFile(contentRootPath, log)
+ ? GetUsersFromFile(contentRootPath, logger)
: GetDefaultUser());
await context.SaveChangesAsync();
@@ -59,7 +42,7 @@
if (useCustomizationData)
{
- GetPreconfiguredImages(contentRootPath, webroot, log);
+ GetPreconfiguredImages(contentRootPath, webroot, logger);
}
}
catch (Exception ex)
@@ -67,14 +50,15 @@
if (retryForAvaiability < 10)
{
retryForAvaiability++;
- var log = loggerFactory.CreateLogger("catalog seed");
- log.LogError(ex.Message);
- await SeedAsync(applicationBuilder, env, loggerFactory, retryForAvaiability);
+
+ logger.LogError(ex.Message,$"There is an error migrating data for ApplicationDbContext");
+
+ await SeedAsync(context,env,logger,settings, retryForAvaiability);
}
}
}
- private IEnumerable GetUsersFromFile(string contentRootPath, ILogger log)
+ private IEnumerable GetUsersFromFile(string contentRootPath, ILogger logger)
{
string csvFileUsers = Path.Combine(contentRootPath, "Setup", "Users.csv");
@@ -96,7 +80,8 @@
}
catch (Exception ex)
{
- log.LogError(ex.Message);
+ logger.LogError(ex.Message);
+
return GetDefaultUser();
}
@@ -104,7 +89,7 @@
.Skip(1) // skip header column
.Select(row => Regex.Split(row, ",(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)") )
.SelectTry(column => CreateApplicationUser(column, csvheaders))
- .OnCaughtException(ex => { log.LogError(ex.Message); return null; })
+ .OnCaughtException(ex => { logger.LogError(ex.Message); return null; })
.Where(x => x != null)
.ToList();
@@ -207,14 +192,14 @@
return csvheaders;
}
- static void GetPreconfiguredImages(string contentRootPath, string webroot, ILogger log)
+ static void GetPreconfiguredImages(string contentRootPath, string webroot, ILogger logger)
{
try
{
string imagesZipFile = Path.Combine(contentRootPath, "Setup", "images.zip");
if (!File.Exists(imagesZipFile))
{
- log.LogError($" zip file '{imagesZipFile}' does not exists.");
+ logger.LogError($" zip file '{imagesZipFile}' does not exists.");
return;
}
@@ -236,14 +221,14 @@
}
else
{
- log.LogWarning($"Skip file '{entry.Name}' in zipfile '{imagesZipFile}'");
+ logger.LogWarning($"Skip file '{entry.Name}' in zipfile '{imagesZipFile}'");
}
}
}
}
catch (Exception ex)
{
- log.LogError($"Exception in method GetPreconfiguredImages WebMVC. Exception Message={ex.Message}");
+ logger.LogError($"Exception in method GetPreconfiguredImages WebMVC. Exception Message={ex.Message}");
}
}
}
diff --git a/src/Services/Identity/Identity.API/Data/ConfigurationDbContextSeed.cs b/src/Services/Identity/Identity.API/Data/ConfigurationDbContextSeed.cs
new file mode 100644
index 000000000..bb41f0d0a
--- /dev/null
+++ b/src/Services/Identity/Identity.API/Data/ConfigurationDbContextSeed.cs
@@ -0,0 +1,56 @@
+using IdentityServer4.EntityFramework.DbContexts;
+using IdentityServer4.EntityFramework.Mappers;
+using Microsoft.eShopOnContainers.Services.Identity.API.Configuration;
+using Microsoft.Extensions.Configuration;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace Microsoft.eShopOnContainers.Services.Identity.API.Data
+{
+ public class ConfigurationDbContextSeed
+ {
+ public async Task SeedAsync(ConfigurationDbContext context,IConfiguration configuration)
+ {
+
+ //callbacks urls from config:
+ var clientUrls = new Dictionary();
+
+ clientUrls.Add("Mvc", configuration.GetValue("MvcClient"));
+ clientUrls.Add("Spa", configuration.GetValue("SpaClient"));
+ clientUrls.Add("Xamarin", configuration.GetValue("XamarinCallback"));
+ clientUrls.Add("LocationsApi", configuration.GetValue("LocationApiClient"));
+ clientUrls.Add("MarketingApi", configuration.GetValue("MarketingApiClient"));
+ clientUrls.Add("BasketApi", configuration.GetValue("BasketApiClient"));
+ clientUrls.Add("OrderingApi", configuration.GetValue("OrderingApiClient"));
+
+ if (!context.Clients.Any())
+ {
+ foreach (var client in Config.GetClients(clientUrls))
+ {
+ await context.Clients.AddAsync(client.ToEntity());
+ }
+ await context.SaveChangesAsync();
+ }
+
+ if (!context.IdentityResources.Any())
+ {
+ foreach (var resource in Config.GetResources())
+ {
+ await context.IdentityResources.AddAsync(resource.ToEntity());
+ }
+ await context.SaveChangesAsync();
+ }
+
+ if (!context.ApiResources.Any())
+ {
+ foreach (var api in Config.GetApis())
+ {
+ await context.ApiResources.AddAsync(api.ToEntity());
+ }
+
+ await context.SaveChangesAsync();
+ }
+ }
+ }
+}
diff --git a/src/Services/Identity/Identity.API/Data/Migrations/20161019122215_Init_Scheme.Designer.cs b/src/Services/Identity/Identity.API/Data/Migrations/20161019122215_Init_Scheme.Designer.cs
deleted file mode 100644
index 07e821f4c..000000000
--- a/src/Services/Identity/Identity.API/Data/Migrations/20161019122215_Init_Scheme.Designer.cs
+++ /dev/null
@@ -1,242 +0,0 @@
-using System;
-using Microsoft.EntityFrameworkCore;
-using Microsoft.EntityFrameworkCore.Infrastructure;
-using Microsoft.EntityFrameworkCore.Metadata;
-using Microsoft.EntityFrameworkCore.Migrations;
-using Identity.API.Data;
-
-namespace WebMVC.Migrations
-{
- [DbContext(typeof(ApplicationDbContext))]
- [Migration("20161019122215_Init_Scheme")]
- partial class Init_Scheme
- {
- protected override void BuildTargetModel(ModelBuilder modelBuilder)
- {
- modelBuilder
- .HasAnnotation("ProductVersion", "1.0.0-rtm-21431")
- .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
-
- modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityRole", b =>
- {
- b.Property("Id");
-
- b.Property("ConcurrencyStamp")
- .IsConcurrencyToken();
-
- b.Property("Name")
- .HasAnnotation("MaxLength", 256);
-
- b.Property("NormalizedName")
- .HasAnnotation("MaxLength", 256);
-
- b.HasKey("Id");
-
- b.HasIndex("NormalizedName")
- .HasName("RoleNameIndex");
-
- b.ToTable("AspNetRoles");
- });
-
- modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityRoleClaim", b =>
- {
- b.Property("Id")
- .ValueGeneratedOnAdd();
-
- b.Property("ClaimType");
-
- b.Property("ClaimValue");
-
- b.Property("RoleId")
- .IsRequired();
-
- b.HasKey("Id");
-
- b.HasIndex("RoleId");
-
- b.ToTable("AspNetRoleClaims");
- });
-
- modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserClaim", b =>
- {
- b.Property("Id")
- .ValueGeneratedOnAdd();
-
- b.Property("ClaimType");
-
- b.Property("ClaimValue");
-
- b.Property("UserId")
- .IsRequired();
-
- b.HasKey("Id");
-
- b.HasIndex("UserId");
-
- b.ToTable("AspNetUserClaims");
- });
-
- modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserLogin", b =>
- {
- b.Property("LoginProvider");
-
- b.Property("ProviderKey");
-
- b.Property("ProviderDisplayName");
-
- b.Property("UserId")
- .IsRequired();
-
- b.HasKey("LoginProvider", "ProviderKey");
-
- b.HasIndex("UserId");
-
- b.ToTable("AspNetUserLogins");
- });
-
- modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserRole", b =>
- {
- b.Property("UserId");
-
- b.Property("RoleId");
-
- b.HasKey("UserId", "RoleId");
-
- b.HasIndex("RoleId");
-
- b.HasIndex("UserId");
-
- b.ToTable("AspNetUserRoles");
- });
-
- modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserToken", b =>
- {
- b.Property("UserId");
-
- b.Property("LoginProvider");
-
- b.Property("Name");
-
- b.Property("Value");
-
- b.HasKey("UserId", "LoginProvider", "Name");
-
- b.ToTable("AspNetUserTokens");
- });
-
- modelBuilder.Entity("Microsoft.eShopOnContainers.WebMVC.ViewModels.ApplicationUser", b =>
- {
- b.Property("Id");
-
- b.Property("AccessFailedCount");
-
- b.Property("CardHolderName");
-
- b.Property("CardNumber");
-
- b.Property("CardType");
-
- b.Property("City");
-
- b.Property("ConcurrencyStamp")
- .IsConcurrencyToken();
-
- b.Property("Country");
-
- b.Property("CountryCode");
-
- b.Property("Email")
- .HasAnnotation("MaxLength", 256);
-
- b.Property("EmailConfirmed");
-
- b.Property("Expiration");
-
- b.Property("Latitude");
-
- b.Property("LockoutEnabled");
-
- b.Property("LockoutEnd");
-
- b.Property("Longitude");
-
- b.Property("NormalizedEmail")
- .HasAnnotation("MaxLength", 256);
-
- b.Property("NormalizedUserName")
- .HasAnnotation("MaxLength", 256);
-
- b.Property("PasswordHash");
-
- b.Property("PhoneNumber");
-
- b.Property("PhoneNumberConfirmed");
-
- b.Property("SecurityNumber");
-
- b.Property("SecurityStamp");
-
- b.Property("State");
-
- b.Property("StateCode");
-
- b.Property("Street");
-
- b.Property("TwoFactorEnabled");
-
- b.Property("UserName")
- .HasAnnotation("MaxLength", 256);
-
- b.Property("ZipCode");
-
- b.HasKey("Id");
-
- b.HasIndex("NormalizedEmail")
- .HasName("EmailIndex");
-
- b.HasIndex("NormalizedUserName")
- .IsUnique()
- .HasName("UserNameIndex");
-
- b.ToTable("AspNetUsers");
- });
-
- modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityRoleClaim", b =>
- {
- b.HasOne("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityRole")
- .WithMany("Claims")
- .HasForeignKey("RoleId")
- .OnDelete(DeleteBehavior.Cascade);
- });
-
- modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserClaim", b =>
- {
- b.HasOne("Microsoft.eShopOnContainers.WebMVC.ViewModels.ApplicationUser")
- .WithMany("Claims")
- .HasForeignKey("UserId")
- .OnDelete(DeleteBehavior.Cascade);
- });
-
- modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserLogin", b =>
- {
- b.HasOne("Microsoft.eShopOnContainers.WebMVC.ViewModels.ApplicationUser")
- .WithMany("Logins")
- .HasForeignKey("UserId")
- .OnDelete(DeleteBehavior.Cascade);
- });
-
- modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserRole", b =>
- {
- b.HasOne("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityRole")
- .WithMany("Users")
- .HasForeignKey("RoleId")
- .OnDelete(DeleteBehavior.Cascade);
-
- b.HasOne("Microsoft.eShopOnContainers.WebMVC.ViewModels.ApplicationUser")
- .WithMany("Roles")
- .HasForeignKey("UserId")
- .OnDelete(DeleteBehavior.Cascade);
- });
- }
- }
-}
diff --git a/src/Services/Identity/Identity.API/Data/Migrations/20161020101725_extendProfile.cs b/src/Services/Identity/Identity.API/Data/Migrations/20161020101725_extendProfile.cs
deleted file mode 100644
index 46dfceb9a..000000000
--- a/src/Services/Identity/Identity.API/Data/Migrations/20161020101725_extendProfile.cs
+++ /dev/null
@@ -1,33 +0,0 @@
-using System;
-using System.Collections.Generic;
-using Microsoft.EntityFrameworkCore.Migrations;
-
-namespace WebMVC.Migrations
-{
- public partial class extendProfile : Migration
- {
- protected override void Up(MigrationBuilder migrationBuilder)
- {
- migrationBuilder.AddColumn(
- name: "LastName",
- table: "AspNetUsers",
- nullable: true);
-
- migrationBuilder.AddColumn(
- name: "Name",
- table: "AspNetUsers",
- nullable: true);
- }
-
- protected override void Down(MigrationBuilder migrationBuilder)
- {
- migrationBuilder.DropColumn(
- name: "LastName",
- table: "AspNetUsers");
-
- migrationBuilder.DropColumn(
- name: "Name",
- table: "AspNetUsers");
- }
- }
-}
diff --git a/src/Services/Identity/Identity.API/Dockerfile b/src/Services/Identity/Identity.API/Dockerfile
index bd01695f3..029b5893e 100644
--- a/src/Services/Identity/Identity.API/Dockerfile
+++ b/src/Services/Identity/Identity.API/Dockerfile
@@ -1,4 +1,4 @@
-FROM microsoft/aspnetcore:1.1.2
+FROM microsoft/aspnetcore:2.0.0
ARG source
WORKDIR /app
EXPOSE 80
diff --git a/src/Services/Identity/Identity.API/Extensions/LinqSelectExtensions.cs b/src/Services/Identity/Identity.API/Extensions/LinqSelectExtensions.cs
index e3ff0a3c0..1061881af 100644
--- a/src/Services/Identity/Identity.API/Extensions/LinqSelectExtensions.cs
+++ b/src/Services/Identity/Identity.API/Extensions/LinqSelectExtensions.cs
@@ -2,7 +2,7 @@
using System.Collections.Generic;
using System.Linq;
-namespace Identity.API.Extensions
+namespace Microsoft.eShopOnContainers.Services.Identity.API.Extensions
{
public static class LinqSelectExtensions
{
diff --git a/src/Services/Identity/Identity.API/Identity.API.csproj b/src/Services/Identity/Identity.API/Identity.API.csproj
index 7c221e858..cee95b94f 100644
--- a/src/Services/Identity/Identity.API/Identity.API.csproj
+++ b/src/Services/Identity/Identity.API/Identity.API.csproj
@@ -1,8 +1,8 @@
- netcoreapp1.1
- 1.1.2
+ netcoreapp2.0
+ 2.0.0
aspnet-eShopOnContainers.Identity-90487118-103c-4ff0-b9da-e5e26f7ab0c5
$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;
..\..\..\..\docker-compose.dcproj
@@ -16,32 +16,9 @@
-
-
-
-
-
-
-
-
-
-
-
- All
-
-
- All
-
-
-
-
-
-
-
-
-
-
-
+
+
+
@@ -51,10 +28,10 @@
-
-
-
-
+
+
+
+
@@ -66,6 +43,7 @@
+
diff --git a/src/Services/Identity/Identity.API/Migrations/20170604151240_Init-persisted-grant.cs b/src/Services/Identity/Identity.API/Migrations/20170604151240_Init-persisted-grant.cs
deleted file mode 100644
index 51c896f5f..000000000
--- a/src/Services/Identity/Identity.API/Migrations/20170604151240_Init-persisted-grant.cs
+++ /dev/null
@@ -1,40 +0,0 @@
-using System;
-using System.Collections.Generic;
-using Microsoft.EntityFrameworkCore.Migrations;
-
-namespace Identity.API.Migrations
-{
- public partial class Initpersistedgrant : Migration
- {
- protected override void Up(MigrationBuilder migrationBuilder)
- {
- migrationBuilder.CreateTable(
- name: "PersistedGrants",
- columns: table => new
- {
- Key = table.Column(maxLength: 200, nullable: false),
- ClientId = table.Column(maxLength: 200, nullable: false),
- CreationTime = table.Column(nullable: false),
- Data = table.Column(maxLength: 50000, nullable: false),
- Expiration = table.Column(nullable: true),
- SubjectId = table.Column(maxLength: 200, nullable: true),
- Type = table.Column(maxLength: 50, nullable: false)
- },
- constraints: table =>
- {
- table.PrimaryKey("PK_PersistedGrants", x => x.Key);
- });
-
- migrationBuilder.CreateIndex(
- name: "IX_PersistedGrants_SubjectId_ClientId_Type",
- table: "PersistedGrants",
- columns: new[] { "SubjectId", "ClientId", "Type" });
- }
-
- protected override void Down(MigrationBuilder migrationBuilder)
- {
- migrationBuilder.DropTable(
- name: "PersistedGrants");
- }
- }
-}
diff --git a/src/Services/Identity/Identity.API/Data/Migrations/20161020101725_extendProfile.Designer.cs b/src/Services/Identity/Identity.API/Migrations/20170912114036_Initial.Designer.cs
similarity index 55%
rename from src/Services/Identity/Identity.API/Data/Migrations/20161020101725_extendProfile.Designer.cs
rename to src/Services/Identity/Identity.API/Migrations/20170912114036_Initial.Designer.cs
index 2d118647d..0850b37b9 100644
--- a/src/Services/Identity/Identity.API/Data/Migrations/20161020101725_extendProfile.Designer.cs
+++ b/src/Services/Identity/Identity.API/Migrations/20170912114036_Initial.Designer.cs
@@ -1,44 +1,135 @@
-using System;
+//
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
-using Identity.API.Data;
+using Microsoft.eShopOnContainers.Services.Identity.API.Data;
+using System;
-namespace WebMVC.Migrations
+namespace Identity.API.Migrations
{
[DbContext(typeof(ApplicationDbContext))]
- [Migration("20161020101725_extendProfile")]
- partial class extendProfile
+ [Migration("20170912114036_Initial")]
+ partial class Initial
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
+#pragma warning disable 612, 618
modelBuilder
- .HasAnnotation("ProductVersion", "1.0.0-rtm-21431")
+ .HasAnnotation("ProductVersion", "2.0.0-rtm-26452")
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
- modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityRole", b =>
+ modelBuilder.Entity("Identity.API.Models.ApplicationUser", b =>
{
- b.Property("Id");
+ b.Property("Id")
+ .ValueGeneratedOnAdd();
+
+ b.Property("AccessFailedCount");
+
+ b.Property("CardHolderName")
+ .IsRequired();
+
+ b.Property("CardNumber")
+ .IsRequired();
+
+ b.Property("CardType");
+
+ b.Property("City")
+ .IsRequired();
+
+ b.Property("ConcurrencyStamp")
+ .IsConcurrencyToken();
+
+ b.Property("Country")
+ .IsRequired();
+
+ b.Property("Email")
+ .HasMaxLength(256);
+
+ b.Property("EmailConfirmed");
+
+ b.Property("Expiration")
+ .IsRequired();
+
+ b.Property("LastName")
+ .IsRequired();
+
+ b.Property("LockoutEnabled");
+
+ b.Property("LockoutEnd");
+
+ b.Property("Name")
+ .IsRequired();
+
+ b.Property("NormalizedEmail")
+ .HasMaxLength(256);
+
+ b.Property("NormalizedUserName")
+ .HasMaxLength(256);
+
+ b.Property("PasswordHash");
+
+ b.Property("PhoneNumber");
+
+ b.Property("PhoneNumberConfirmed");
+
+ b.Property("SecurityNumber")
+ .IsRequired();
+
+ b.Property("SecurityStamp");
+
+ b.Property("State")
+ .IsRequired();
+
+ b.Property("Street")
+ .IsRequired();
+
+ b.Property("TwoFactorEnabled");
+
+ b.Property("UserName")
+ .HasMaxLength(256);
+
+ b.Property("ZipCode")
+ .IsRequired();
+
+ b.HasKey("Id");
+
+ b.HasIndex("NormalizedEmail")
+ .HasName("EmailIndex");
+
+ b.HasIndex("NormalizedUserName")
+ .IsUnique()
+ .HasName("UserNameIndex")
+ .HasFilter("[NormalizedUserName] IS NOT NULL");
+
+ b.ToTable("AspNetUsers");
+ });
+
+ modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd();
b.Property("ConcurrencyStamp")
.IsConcurrencyToken();
b.Property("Name")
- .HasAnnotation("MaxLength", 256);
+ .HasMaxLength(256);
b.Property("NormalizedName")
- .HasAnnotation("MaxLength", 256);
+ .HasMaxLength(256);
b.HasKey("Id");
b.HasIndex("NormalizedName")
- .HasName("RoleNameIndex");
+ .IsUnique()
+ .HasName("RoleNameIndex")
+ .HasFilter("[NormalizedName] IS NOT NULL");
b.ToTable("AspNetRoles");
});
- modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityRoleClaim", b =>
+ modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b =>
{
b.Property("Id")
.ValueGeneratedOnAdd();
@@ -57,7 +148,7 @@ namespace WebMVC.Migrations
b.ToTable("AspNetRoleClaims");
});
- modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserClaim", b =>
+ modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b =>
{
b.Property("Id")
.ValueGeneratedOnAdd();
@@ -76,7 +167,7 @@ namespace WebMVC.Migrations
b.ToTable("AspNetUserClaims");
});
- modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserLogin", b =>
+ modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b =>
{
b.Property("LoginProvider");
@@ -94,7 +185,7 @@ namespace WebMVC.Migrations
b.ToTable("AspNetUserLogins");
});
- modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserRole", b =>
+ modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b =>
{
b.Property("UserId");
@@ -104,12 +195,10 @@ namespace WebMVC.Migrations
b.HasIndex("RoleId");
- b.HasIndex("UserId");
-
b.ToTable("AspNetUserRoles");
});
- modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserToken", b =>
+ modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b =>
{
b.Property("UserId");
@@ -124,123 +213,51 @@ namespace WebMVC.Migrations
b.ToTable("AspNetUserTokens");
});
- modelBuilder.Entity("Microsoft.eShopOnContainers.WebMVC.ViewModels.ApplicationUser", b =>
- {
- b.Property("Id");
-
- b.Property("AccessFailedCount");
-
- b.Property("CardHolderName");
-
- b.Property("CardNumber");
-
- b.Property("CardType");
-
- b.Property("City");
-
- b.Property("ConcurrencyStamp")
- .IsConcurrencyToken();
-
- b.Property("Country");
-
- b.Property("CountryCode");
-
- b.Property("Email")
- .HasAnnotation("MaxLength", 256);
-
- b.Property("EmailConfirmed");
-
- b.Property("Expiration");
-
- b.Property("LastName");
-
- b.Property("Latitude");
-
- b.Property("LockoutEnabled");
-
- b.Property("LockoutEnd");
-
- b.Property("Longitude");
-
- b.Property("Name");
-
- b.Property("NormalizedEmail")
- .HasAnnotation("MaxLength", 256);
-
- b.Property("NormalizedUserName")
- .HasAnnotation("MaxLength", 256);
-
- b.Property("PasswordHash");
-
- b.Property("PhoneNumber");
-
- b.Property("PhoneNumberConfirmed");
-
- b.Property("SecurityNumber");
-
- b.Property("SecurityStamp");
-
- b.Property("State");
-
- b.Property("StateCode");
-
- b.Property("Street");
-
- b.Property("TwoFactorEnabled");
-
- b.Property("UserName")
- .HasAnnotation("MaxLength", 256);
-
- b.Property("ZipCode");
-
- b.HasKey("Id");
-
- b.HasIndex("NormalizedEmail")
- .HasName("EmailIndex");
-
- b.HasIndex("NormalizedUserName")
- .IsUnique()
- .HasName("UserNameIndex");
-
- b.ToTable("AspNetUsers");
- });
-
- modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityRoleClaim", b =>
+ modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b =>
{
- b.HasOne("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityRole")
- .WithMany("Claims")
+ b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole")
+ .WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade);
});
- modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserClaim", b =>
+ modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b =>
{
- b.HasOne("Microsoft.eShopOnContainers.WebMVC.ViewModels.ApplicationUser")
- .WithMany("Claims")
+ b.HasOne("Identity.API.Models.ApplicationUser")
+ .WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
});
- modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserLogin", b =>
+ modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b =>
{
- b.HasOne("Microsoft.eShopOnContainers.WebMVC.ViewModels.ApplicationUser")
- .WithMany("Logins")
+ b.HasOne("Identity.API.Models.ApplicationUser")
+ .WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
});
- modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserRole", b =>
+ modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b =>
{
- b.HasOne("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityRole")
- .WithMany("Users")
+ b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole")
+ .WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade);
- b.HasOne("Microsoft.eShopOnContainers.WebMVC.ViewModels.ApplicationUser")
- .WithMany("Roles")
+ b.HasOne("Identity.API.Models.ApplicationUser")
+ .WithMany()
+ .HasForeignKey("UserId")
+ .OnDelete(DeleteBehavior.Cascade);
+ });
+
+ modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b =>
+ {
+ b.HasOne("Identity.API.Models.ApplicationUser")
+ .WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
});
+#pragma warning restore 612, 618
}
}
}
diff --git a/src/Services/Identity/Identity.API/Data/Migrations/20161019122215_Init_Scheme.cs b/src/Services/Identity/Identity.API/Migrations/20170912114036_Initial.cs
similarity index 53%
rename from src/Services/Identity/Identity.API/Data/Migrations/20161019122215_Init_Scheme.cs
rename to src/Services/Identity/Identity.API/Migrations/20170912114036_Initial.cs
index 278c3f422..cf771dac8 100644
--- a/src/Services/Identity/Identity.API/Data/Migrations/20161019122215_Init_Scheme.cs
+++ b/src/Services/Identity/Identity.API/Migrations/20170912114036_Initial.cs
@@ -1,11 +1,11 @@
-using System;
-using System.Collections.Generic;
+using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
-using Microsoft.EntityFrameworkCore.Metadata;
+using System;
+using System.Collections.Generic;
-namespace WebMVC.Migrations
+namespace Identity.API.Migrations
{
- public partial class Init_Scheme : Migration
+ public partial class Initial : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
@@ -13,59 +13,47 @@ namespace WebMVC.Migrations
name: "AspNetRoles",
columns: table => new
{
- Id = table.Column(nullable: false),
- ConcurrencyStamp = table.Column(nullable: true),
- Name = table.Column(maxLength: 256, nullable: true),
- NormalizedName = table.Column(maxLength: 256, nullable: true)
+ Id = table.Column(type: "nvarchar(450)", nullable: false),
+ ConcurrencyStamp = table.Column(type: "nvarchar(max)", nullable: true),
+ Name = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true),
+ NormalizedName = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_AspNetRoles", x => x.Id);
});
- migrationBuilder.CreateTable(
- name: "AspNetUserTokens",
- columns: table => new
- {
- UserId = table.Column(nullable: false),
- LoginProvider = table.Column(nullable: false),
- Name = table.Column(nullable: false),
- Value = table.Column(nullable: true)
- },
- constraints: table =>
- {
- table.PrimaryKey("PK_AspNetUserTokens", x => new { x.UserId, x.LoginProvider, x.Name });
- });
-
migrationBuilder.CreateTable(
name: "AspNetUsers",
columns: table => new
{
- Id = table.Column(nullable: false),
- AccessFailedCount = table.Column(nullable: false),
- CardHolderName = table.Column(nullable: true),
- CardNumber = table.Column(nullable: true),
- CardType = table.Column(nullable: false),
- City = table.Column(nullable: true),
- ConcurrencyStamp = table.Column(nullable: true),
- Country = table.Column(nullable: true),
- Email = table.Column(maxLength: 256, nullable: true),
- EmailConfirmed = table.Column(nullable: false),
- Expiration = table.Column(nullable: true),
- LockoutEnabled = table.Column