Merge branch 'dev'
# Conflicts: # src/Services/Basket/Basket.API/Model/IBasketRepository.cs # src/Services/Basket/Basket.API/Model/RedisBasketRepository.cs # src/Services/Catalog/Catalog.API/Startup.cs # src/Services/Ordering/Ordering.API/Application/Commands/CreateOrderCommandHandler.cs # src/Services/Ordering/Ordering.Infrastructure/Repositories/OrderRepository.cs # test/Services/UnitTest/Ordering/Application/NewOrderCommandHandlerTest.cs
This commit is contained in:
commit
35cc2f9d7b
29
_docker/rabbitmq/Dockerfile.nanowin
Normal file
29
_docker/rabbitmq/Dockerfile.nanowin
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
#https://github.com/spring2/dockerfiles/tree/master/rabbitmq
|
||||||
|
|
||||||
|
FROM microsoft/windowsservercore
|
||||||
|
|
||||||
|
SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"]
|
||||||
|
|
||||||
|
ENV chocolateyUseWindowsCompression false
|
||||||
|
|
||||||
|
RUN iex ((new-object net.webclient).DownloadString('https://chocolatey.org/install.ps1')); \
|
||||||
|
choco install -y curl;
|
||||||
|
|
||||||
|
RUN choco install -y erlang
|
||||||
|
ENV ERLANG_SERVICE_MANAGER_PATH="C:\Program Files\erl8.2\erts-8.2\bin"
|
||||||
|
RUN choco install -y rabbitmq
|
||||||
|
ENV RABBITMQ_SERVER="C:\Program Files\RabbitMQ Server\rabbitmq_server-3.6.5"
|
||||||
|
|
||||||
|
ENV RABBITMQ_CONFIG_FILE="c:\rabbitmq"
|
||||||
|
COPY rabbitmq.config C:/
|
||||||
|
COPY rabbitmq.config C:/Users/ContainerAdministrator/AppData/Roaming/RabbitMQ/
|
||||||
|
COPY enabled_plugins C:/Users/ContainerAdministrator/AppData/Roaming/RabbitMQ/
|
||||||
|
|
||||||
|
|
||||||
|
EXPOSE 4369
|
||||||
|
EXPOSE 5672
|
||||||
|
EXPOSE 5671
|
||||||
|
EXPOSE 15672
|
||||||
|
|
||||||
|
WORKDIR C:/Program\ Files/RabbitMQ\ Server/rabbitmq_server-3.6.5/sbin
|
||||||
|
CMD .\rabbitmq-server.bat
|
1
_docker/rabbitmq/enabled_plugins
Normal file
1
_docker/rabbitmq/enabled_plugins
Normal file
@ -0,0 +1 @@
|
|||||||
|
[rabbitmq_amqp1_0,rabbitmq_management].
|
1
_docker/rabbitmq/rabbitmq.config
Normal file
1
_docker/rabbitmq/rabbitmq.config
Normal file
@ -0,0 +1 @@
|
|||||||
|
[{rabbit, [{loopback_users, []}]}].
|
30
_docker/redis/Dockerfile.nanowin
Normal file
30
_docker/redis/Dockerfile.nanowin
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
# The MSI installs a service which is hard to override, so let's use a zip file.
|
||||||
|
|
||||||
|
FROM microsoft/windowsservercore
|
||||||
|
MAINTAINER alexellis2@gmail.com
|
||||||
|
|
||||||
|
SHELL ["powershell"]
|
||||||
|
RUN $ErrorActionPreference = 'Stop'; \
|
||||||
|
wget https://github.com/MSOpenTech/redis/releases/download/win-3.2.100/Redis-x64-3.2.100.zip -OutFile Redis-x64-3.2.100.zip ; \
|
||||||
|
Expand-Archive Redis-x64-3.2.100.zip -dest 'C:\\Program Files\\Redis\\' ; \
|
||||||
|
Remove-Item Redis-x64-3.2.100.zip -Force
|
||||||
|
|
||||||
|
RUN setx PATH '%PATH%;C:\\Program Files\\Redis\\'
|
||||||
|
WORKDIR 'C:\\Program Files\\Redis\\'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
RUN Get-Content redis.windows.conf | Where { $_ -notmatch 'bind 127.0.0.1' } | Set-Content redis.openport.conf ; \
|
||||||
|
Get-Content redis.openport.conf | Where { $_ -notmatch 'protected-mode yes' } | Set-Content redis.unprotected.conf ; \
|
||||||
|
Add-Content redis.unprotected.conf 'protected-mode no' ; \
|
||||||
|
Add-Content redis.unprotected.conf 'bind 0.0.0.0' ; \
|
||||||
|
Get-Content redis.unprotected.conf
|
||||||
|
|
||||||
|
EXPOSE 6379
|
||||||
|
|
||||||
|
RUN set-itemproperty -path 'HKLM:\SYSTEM\CurrentControlSet\Services\Dnscache\Parameters' -Name ServerPriorityTimeLimit -Value 0 -Type DWord
|
||||||
|
|
||||||
|
# Define our command to be run when launching the container
|
||||||
|
CMD .\\redis-server.exe .\\redis.unprotected.conf --port 6379 ; \
|
||||||
|
Write-Host Redis Started... ; \
|
||||||
|
while ($true) { Start-Sleep -Seconds 3600 }
|
@ -8,3 +8,8 @@ services:
|
|||||||
image: redis
|
image: redis
|
||||||
ports:
|
ports:
|
||||||
- "6379:6379"
|
- "6379:6379"
|
||||||
|
|
||||||
|
rabbitmq:
|
||||||
|
image: rabbitmq
|
||||||
|
ports:
|
||||||
|
- "5672:5672"
|
||||||
|
79
docker-compose-windows.override.yml
Normal file
79
docker-compose-windows.override.yml
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
version: '2.1'
|
||||||
|
|
||||||
|
# The default docker-compose.override file can use the "localhost" as the external name for testing web apps within the same dev machine.
|
||||||
|
# The ESHOP_EXTERNAL_DNS_NAME_OR_IP environment variable is taken, by default, from the ".env" file defined like:
|
||||||
|
# ESHOP_EXTERNAL_DNS_NAME_OR_IP=localhost
|
||||||
|
# but values present in the environment vars at runtime will always override those defined inside the .env file
|
||||||
|
# An external IP or DNS name has to be used (instead localhost and the 10.0.75.1 IP) when testing the Web apps and the Xamarin apps from remote machines/devices using the same WiFi, for instance.
|
||||||
|
|
||||||
|
services:
|
||||||
|
|
||||||
|
basket.api:
|
||||||
|
environment:
|
||||||
|
- ASPNETCORE_ENVIRONMENT=Development
|
||||||
|
- ASPNETCORE_URLS=http://0.0.0.0:5103
|
||||||
|
- ConnectionString=basket.data
|
||||||
|
- identityUrl=http://identity.api:5105 #Local: You need to open your local dev-machine firewall at range 5100-5105. at range 5100-5105.
|
||||||
|
- EventBusConnection=rabbitmq
|
||||||
|
ports:
|
||||||
|
- "5103:5103"
|
||||||
|
|
||||||
|
catalog.api:
|
||||||
|
environment:
|
||||||
|
- ASPNETCORE_ENVIRONMENT=Development
|
||||||
|
- ASPNETCORE_URLS=http://0.0.0.0:5101
|
||||||
|
- 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
|
||||||
|
ports:
|
||||||
|
- "5101:5101"
|
||||||
|
|
||||||
|
identity.api:
|
||||||
|
environment:
|
||||||
|
- ASPNETCORE_ENVIRONMENT=Development
|
||||||
|
- ASPNETCORE_URLS=http://0.0.0.0:5105
|
||||||
|
- 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.
|
||||||
|
ports:
|
||||||
|
- "5105:5105"
|
||||||
|
|
||||||
|
ordering.api:
|
||||||
|
environment:
|
||||||
|
- ASPNETCORE_ENVIRONMENT=Development
|
||||||
|
- ASPNETCORE_URLS=http://0.0.0.0:5102
|
||||||
|
- 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 local dev-machine firewall at range 5100-5105. at range 5100-5105.
|
||||||
|
- EventBusConnection=rabbitmq
|
||||||
|
ports:
|
||||||
|
- "5102:5102"
|
||||||
|
|
||||||
|
webspa:
|
||||||
|
environment:
|
||||||
|
- ASPNETCORE_ENVIRONMENT=Development
|
||||||
|
- ASPNETCORE_URLS=http://0.0.0.0:5104
|
||||||
|
- CatalogUrl=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5101
|
||||||
|
- 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.
|
||||||
|
- BasketUrl=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5103
|
||||||
|
ports:
|
||||||
|
- "5104:5104"
|
||||||
|
|
||||||
|
webmvc:
|
||||||
|
environment:
|
||||||
|
- ASPNETCORE_ENVIRONMENT=Development
|
||||||
|
- ASPNETCORE_URLS=http://0.0.0.0:5100
|
||||||
|
- CatalogUrl=http://catalog.api:5101
|
||||||
|
- OrderingUrl=http://ordering.api:5102
|
||||||
|
- BasketUrl=http://basket.api:5103
|
||||||
|
- 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.
|
||||||
|
ports:
|
||||||
|
- "5100:5100"
|
||||||
|
|
||||||
|
sql.data:
|
||||||
|
environment:
|
||||||
|
- SA_PASSWORD=Pass@word
|
||||||
|
- ACCEPT_EULA=Y
|
||||||
|
ports:
|
||||||
|
- "5433:1433"
|
80
docker-compose-windows.prod.yml
Normal file
80
docker-compose-windows.prod.yml
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
version: '2.1'
|
||||||
|
|
||||||
|
# The Production docker-compose file has to have the external/real IPs or DNS names for the services
|
||||||
|
# The ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP environment variable is taken, by default, from the ".env" file defined like:
|
||||||
|
# ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP=192.168.88.248
|
||||||
|
# but values present in the environment vars at runtime will always override those defined inside the .env file
|
||||||
|
# An external IP or DNS name has to be used when testing the Web apps and the Xamarin apps from remote machines/devices using the same WiFi, for instance.
|
||||||
|
#
|
||||||
|
# Set ASPNETCORE_ENVIRONMENT=Development to get errors while testing.
|
||||||
|
#
|
||||||
|
# You need to start it with the following CLI command:
|
||||||
|
# docker-compose -f docker-compose-windows.yml -f docker-compose-windows.prod.yml up -d
|
||||||
|
|
||||||
|
services:
|
||||||
|
|
||||||
|
basket.api:
|
||||||
|
environment:
|
||||||
|
- ASPNETCORE_ENVIRONMENT=Production
|
||||||
|
- ASPNETCORE_URLS=http://0.0.0.0:5103
|
||||||
|
- ConnectionString=basket.data
|
||||||
|
- identityUrl=http://identity.api:5105 #Local: You need to open your host's firewall at range 5100-5105. at range 5100-5105.
|
||||||
|
ports:
|
||||||
|
- "5103:5103"
|
||||||
|
|
||||||
|
catalog.api:
|
||||||
|
environment:
|
||||||
|
- ASPNETCORE_ENVIRONMENT=Production
|
||||||
|
- ASPNETCORE_URLS=http://0.0.0.0:5101
|
||||||
|
- 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.
|
||||||
|
ports:
|
||||||
|
- "5101:5101"
|
||||||
|
|
||||||
|
identity.api:
|
||||||
|
environment:
|
||||||
|
- ASPNETCORE_ENVIRONMENT=Production
|
||||||
|
- ASPNETCORE_URLS=http://0.0.0.0:5105
|
||||||
|
- 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.
|
||||||
|
ports:
|
||||||
|
- "5105:5105"
|
||||||
|
|
||||||
|
ordering.api:
|
||||||
|
environment:
|
||||||
|
- ASPNETCORE_ENVIRONMENT=Production
|
||||||
|
- ASPNETCORE_URLS=http://0.0.0.0:5102
|
||||||
|
- 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.
|
||||||
|
ports:
|
||||||
|
- "5102:5102"
|
||||||
|
|
||||||
|
webspa:
|
||||||
|
environment:
|
||||||
|
- ASPNETCORE_ENVIRONMENT=Production
|
||||||
|
- ASPNETCORE_URLS=http://0.0.0.0:5104
|
||||||
|
- CatalogUrl=http://${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}:5101
|
||||||
|
- 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
|
||||||
|
ports:
|
||||||
|
- "5104:5104"
|
||||||
|
|
||||||
|
webmvc:
|
||||||
|
environment:
|
||||||
|
- ASPNETCORE_ENVIRONMENT=Production
|
||||||
|
- ASPNETCORE_URLS=http://0.0.0.0:5100
|
||||||
|
- CatalogUrl=http://catalog.api:5101
|
||||||
|
- OrderingUrl=http://ordering.api:5102
|
||||||
|
- 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:5103
|
||||||
|
ports:
|
||||||
|
- "5100:5100"
|
||||||
|
|
||||||
|
sql.data:
|
||||||
|
environment:
|
||||||
|
- SA_PASSWORD=Pass@word
|
||||||
|
- ACCEPT_EULA=Y
|
||||||
|
ports:
|
||||||
|
- "5433:1433"
|
80
docker-compose-windows.yml
Normal file
80
docker-compose-windows.yml
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
version: '2.1'
|
||||||
|
|
||||||
|
services:
|
||||||
|
basket.api:
|
||||||
|
image: eshop/basket.api
|
||||||
|
build:
|
||||||
|
context: ./src/Services/Basket/Basket.API
|
||||||
|
dockerfile: Dockerfile.nanowin
|
||||||
|
depends_on:
|
||||||
|
- basket.data
|
||||||
|
- identity.api
|
||||||
|
|
||||||
|
catalog.api:
|
||||||
|
image: eshop/catalog.api
|
||||||
|
build:
|
||||||
|
context: ./src/Services/Catalog/Catalog.API
|
||||||
|
dockerfile: Dockerfile.nanowin
|
||||||
|
depends_on:
|
||||||
|
- sql.data
|
||||||
|
|
||||||
|
identity.api:
|
||||||
|
image: eshop/identity.api
|
||||||
|
build:
|
||||||
|
context: ./src/Services/Identity/Identity.API
|
||||||
|
dockerfile: Dockerfile.nanowin
|
||||||
|
depends_on:
|
||||||
|
- sql.data
|
||||||
|
|
||||||
|
ordering.api:
|
||||||
|
image: eshop/ordering.api
|
||||||
|
build:
|
||||||
|
context: ./src/Services/Ordering/Ordering.API
|
||||||
|
dockerfile: Dockerfile.nanowin
|
||||||
|
depends_on:
|
||||||
|
- sql.data
|
||||||
|
|
||||||
|
webspa:
|
||||||
|
image: eshop/webspa
|
||||||
|
build:
|
||||||
|
context: ./src/Web/WebSPA
|
||||||
|
dockerfile: Dockerfile.nanowin
|
||||||
|
depends_on:
|
||||||
|
- identity.api
|
||||||
|
- basket.api
|
||||||
|
|
||||||
|
webmvc:
|
||||||
|
image: eshop/webmvc
|
||||||
|
build:
|
||||||
|
context: ./src/Web/WebMVC
|
||||||
|
dockerfile: Dockerfile.nanowin
|
||||||
|
depends_on:
|
||||||
|
- catalog.api
|
||||||
|
- ordering.api
|
||||||
|
- identity.api
|
||||||
|
- basket.api
|
||||||
|
|
||||||
|
sql.data:
|
||||||
|
image: microsoft/mssql-server-windows
|
||||||
|
|
||||||
|
basket.data:
|
||||||
|
image: redis
|
||||||
|
build:
|
||||||
|
context: ./_docker/redis
|
||||||
|
dockerfile: Dockerfile.nanowin
|
||||||
|
ports:
|
||||||
|
- "6379:6379"
|
||||||
|
|
||||||
|
rabbitmq:
|
||||||
|
image: rabbitmq
|
||||||
|
build:
|
||||||
|
context: ./_docker/rabbitmq
|
||||||
|
dockerfile: Dockerfile.nanowin
|
||||||
|
ports:
|
||||||
|
- "5672:5672"
|
||||||
|
|
||||||
|
networks:
|
||||||
|
default:
|
||||||
|
external:
|
||||||
|
name: nat
|
||||||
|
|
@ -14,6 +14,7 @@ services:
|
|||||||
- ASPNETCORE_URLS=http://0.0.0.0:5103
|
- ASPNETCORE_URLS=http://0.0.0.0:5103
|
||||||
- ConnectionString=basket.data
|
- ConnectionString=basket.data
|
||||||
- identityUrl=http://identity.api:5105 #Local: You need to open your local dev-machine firewall at range 5100-5105. at range 5100-5105.
|
- identityUrl=http://identity.api:5105 #Local: You need to open your local dev-machine firewall at range 5100-5105. at range 5100-5105.
|
||||||
|
- EventBusConnection=rabbitmq
|
||||||
ports:
|
ports:
|
||||||
- "5103:5103"
|
- "5103:5103"
|
||||||
|
|
||||||
@ -22,7 +23,8 @@ services:
|
|||||||
- ASPNETCORE_ENVIRONMENT=Development
|
- ASPNETCORE_ENVIRONMENT=Development
|
||||||
- ASPNETCORE_URLS=http://0.0.0.0:5101
|
- ASPNETCORE_URLS=http://0.0.0.0:5101
|
||||||
- ConnectionString=Server=sql.data;Database=Microsoft.eShopOnContainers.Services.CatalogDb;User Id=sa;Password=Pass@word
|
- 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.
|
- 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
|
||||||
ports:
|
ports:
|
||||||
- "5101:5101"
|
- "5101:5101"
|
||||||
|
|
||||||
@ -42,6 +44,7 @@ services:
|
|||||||
- ASPNETCORE_URLS=http://0.0.0.0:5102
|
- ASPNETCORE_URLS=http://0.0.0.0:5102
|
||||||
- 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
|
||||||
- identityUrl=http://identity.api:5105 #Local: You need to open your local dev-machine firewall at range 5100-5105. at range 5100-5105.
|
- identityUrl=http://identity.api:5105 #Local: You need to open your local dev-machine firewall at range 5100-5105. at range 5100-5105.
|
||||||
|
- EventBusConnection=rabbitmq
|
||||||
ports:
|
ports:
|
||||||
- "5102:5102"
|
- "5102:5102"
|
||||||
|
|
||||||
@ -73,4 +76,17 @@ services:
|
|||||||
- SA_PASSWORD=Pass@word
|
- SA_PASSWORD=Pass@word
|
||||||
- ACCEPT_EULA=Y
|
- ACCEPT_EULA=Y
|
||||||
ports:
|
ports:
|
||||||
- "5433:1433"
|
- "5433:1433"
|
||||||
|
|
||||||
|
webstatus:
|
||||||
|
environment:
|
||||||
|
- ASPNETCORE_ENVIRONMENT=Development
|
||||||
|
- ASPNETCORE_URLS=http://0.0.0.0:5107
|
||||||
|
- CatalogUrl=http://catalog.api:5101/hc
|
||||||
|
- OrderingUrl=http://ordering.api:5102/hc
|
||||||
|
- BasketUrl=http://basket.api:5103/hc
|
||||||
|
- IdentityUrl=http://10.0.75.1:5105/hc
|
||||||
|
- mvc=http://webmvc:5100/hc
|
||||||
|
- spa=http://webspa:5104/hc
|
||||||
|
ports:
|
||||||
|
- "5107:5107"
|
||||||
|
@ -8,7 +8,7 @@ version: '2'
|
|||||||
#
|
#
|
||||||
# Set ASPNETCORE_ENVIRONMENT=Development to get errors while testing.
|
# Set ASPNETCORE_ENVIRONMENT=Development to get errors while testing.
|
||||||
#
|
#
|
||||||
# You need to start it with the following CLI command:
|
# You need to start it with the following CLI command:
|
||||||
# docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d
|
# docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d
|
||||||
|
|
||||||
services:
|
services:
|
||||||
@ -77,4 +77,14 @@ services:
|
|||||||
- SA_PASSWORD=Pass@word
|
- SA_PASSWORD=Pass@word
|
||||||
- ACCEPT_EULA=Y
|
- ACCEPT_EULA=Y
|
||||||
ports:
|
ports:
|
||||||
- "5433:1433"
|
- "5433:1433"
|
||||||
|
|
||||||
|
webstatus:
|
||||||
|
environment:
|
||||||
|
- ASPNETCORE_ENVIRONMENT=Development
|
||||||
|
- CatalogUrl=http://catalog.api:5101/hc
|
||||||
|
- OrderingUrl=http://ordering.api:5102/hc
|
||||||
|
- BasketUrl=http://basket.api:5103/hc
|
||||||
|
- IdentityUrl=http://10.0.75.1:5105/hc
|
||||||
|
ports:
|
||||||
|
- "5107:5107"
|
||||||
|
@ -90,3 +90,18 @@ services:
|
|||||||
entrypoint: tail -f /dev/null
|
entrypoint: tail -f /dev/null
|
||||||
labels:
|
labels:
|
||||||
- "com.microsoft.visualstudio.targetoperatingsystem=linux"
|
- "com.microsoft.visualstudio.targetoperatingsystem=linux"
|
||||||
|
|
||||||
|
webstatus:
|
||||||
|
image: eshop/webstatus:dev
|
||||||
|
build:
|
||||||
|
args:
|
||||||
|
source: ${DOCKER_BUILD_SOURCE}
|
||||||
|
environment:
|
||||||
|
- DOTNET_USE_POLLING_FILE_WATCHER=1
|
||||||
|
volumes:
|
||||||
|
- ./src/Web/WebStatus:/app
|
||||||
|
- ~/.nuget/packages:/root/.nuget/packages:ro
|
||||||
|
- ~/clrdbg:/clrdbg:ro
|
||||||
|
entrypoint: tail -f /dev/null
|
||||||
|
labels:
|
||||||
|
- "com.microsoft.visualstudio.targetoperatingsystem=linux"
|
||||||
|
@ -60,3 +60,13 @@ services:
|
|||||||
entrypoint: tail -f /dev/null
|
entrypoint: tail -f /dev/null
|
||||||
labels:
|
labels:
|
||||||
- "com.microsoft.visualstudio.targetoperatingsystem=linux"
|
- "com.microsoft.visualstudio.targetoperatingsystem=linux"
|
||||||
|
|
||||||
|
webstatus:
|
||||||
|
build:
|
||||||
|
args:
|
||||||
|
source: ${DOCKER_BUILD_SOURCE}
|
||||||
|
volumes:
|
||||||
|
- ~/clrdbg:/clrdbg:ro
|
||||||
|
entrypoint: tail -f /dev/null
|
||||||
|
labels:
|
||||||
|
- "com.microsoft.visualstudio.targetoperatingsystem=linux"
|
||||||
|
@ -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
|
image: eshop/catalog.api
|
||||||
@ -17,6 +18,7 @@ services:
|
|||||||
dockerfile: Dockerfile
|
dockerfile: Dockerfile
|
||||||
depends_on:
|
depends_on:
|
||||||
- sql.data
|
- sql.data
|
||||||
|
- rabbitmq
|
||||||
|
|
||||||
identity.api:
|
identity.api:
|
||||||
image: eshop/identity.api
|
image: eshop/identity.api
|
||||||
@ -61,3 +63,14 @@ services:
|
|||||||
image: redis
|
image: redis
|
||||||
ports:
|
ports:
|
||||||
- "6379:6379"
|
- "6379:6379"
|
||||||
|
|
||||||
|
rabbitmq:
|
||||||
|
image: rabbitmq
|
||||||
|
ports:
|
||||||
|
- "5672:5672"
|
||||||
|
|
||||||
|
webstatus:
|
||||||
|
image: eshop/webstatus
|
||||||
|
build:
|
||||||
|
context: ./src/Web/WebStatus
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
@ -39,10 +39,24 @@ EndProject
|
|||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ordering.Infrastructure", "src\Services\Ordering\Ordering.Infrastructure\Ordering.Infrastructure.csproj", "{95F1F07C-4D92-4742-BD07-E5B805AAB651}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ordering.Infrastructure", "src\Services\Ordering\Ordering.Infrastructure\Ordering.Infrastructure.csproj", "{95F1F07C-4D92-4742-BD07-E5B805AAB651}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnitTest", "test\Services\UnitTest\UnitTest.csproj", "{7796F5D8-31FC-45A4-B673-19DE5BA194CF}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnitTest", "test\Services\UnitTest\UnitTest.csproj", "{7796F5D8-31FC-45A4-B673-19DE5BA194CF}"
|
||||||
|
ProjectSection(ProjectDependencies) = postProject
|
||||||
|
{A579E108-5445-403D-A407-339AC4D1611B} = {A579E108-5445-403D-A407-339AC4D1611B}
|
||||||
|
{F16E3C6A-1C94-4EAB-BE91-099618060B68} = {F16E3C6A-1C94-4EAB-BE91-099618060B68}
|
||||||
|
EndProjectSection
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Identity.API", "src\Services\Identity\Identity.API\Identity.API.csproj", "{A579E108-5445-403D-A407-339AC4D1611B}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Identity.API", "src\Services\Identity\Identity.API\Identity.API.csproj", "{A579E108-5445-403D-A407-339AC4D1611B}"
|
||||||
EndProject
|
EndProject
|
||||||
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
|
||||||
|
{A579E108-5445-403D-A407-339AC4D1611B} = {A579E108-5445-403D-A407-339AC4D1611B}
|
||||||
|
{5B810E3D-112E-4857-B197-F09D2FD41E27} = {5B810E3D-112E-4857-B197-F09D2FD41E27}
|
||||||
|
{F16E3C6A-1C94-4EAB-BE91-099618060B68} = {F16E3C6A-1C94-4EAB-BE91-099618060B68}
|
||||||
|
{F0333D8E-0B27-42B7-B2C6-78F3657624E2} = {F0333D8E-0B27-42B7-B2C6-78F3657624E2}
|
||||||
|
{42681D9D-750A-4DF7-BD9F-9292CFD5C253} = {42681D9D-750A-4DF7-BD9F-9292CFD5C253}
|
||||||
|
{2110CBB0-3B38-4EE4-A743-DF6968D80D90} = {2110CBB0-3B38-4EE4-A743-DF6968D80D90}
|
||||||
|
{CFE2FACB-4538-4B99-8A10-306F3882952D} = {CFE2FACB-4538-4B99-8A10-306F3882952D}
|
||||||
|
{231226CE-690B-4979-8870-9A79D80928E2} = {231226CE-690B-4979-8870-9A79D80928E2}
|
||||||
|
EndProjectSection
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WebSPA", "src\Web\WebSPA\WebSPA.csproj", "{F16E3C6A-1C94-4EAB-BE91-099618060B68}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WebSPA", "src\Web\WebSPA\WebSPA.csproj", "{F16E3C6A-1C94-4EAB-BE91-099618060B68}"
|
||||||
EndProject
|
EndProject
|
||||||
@ -50,6 +64,26 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IntegrationTests", "test\Se
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FunctionalTests", "test\Services\FunctionalTests\FunctionalTests.csproj", "{CFE2FACB-4538-4B99-8A10-306F3882952D}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FunctionalTests", "test\Services\FunctionalTests\FunctionalTests.csproj", "{CFE2FACB-4538-4B99-8A10-306F3882952D}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "BuildingBlocks", "BuildingBlocks", "{DB0EFB20-B024-4E5E-A75C-52143C131D25}"
|
||||||
|
EndProject
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "EventBus", "EventBus", "{807BB76E-B2BB-47A2-A57B-3D1B20FF5E7F}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EventBus", "src\BuildingBlocks\EventBus\EventBus\EventBus.csproj", "{0044B293-1DCC-4224-B948-00CF6DC7F510}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EventBusRabbitMQ", "src\BuildingBlocks\EventBus\EventBusRabbitMQ\EventBusRabbitMQ.csproj", "{8088F3FC-6787-45FA-A924-816EC81CBFAC}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IntegrationEventLogEF", "src\BuildingBlocks\EventBus\IntegrationEventLogEF\IntegrationEventLogEF.csproj", "{9EE28E45-1533-472B-8267-56C48855BA0E}"
|
||||||
|
EndProject
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "HealthChecks", "HealthChecks", "{A81ECBC2-6B00-4DCD-8388-469174033379}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.HealthChecks", "src\BuildingBlocks\HealthChecks\src\Microsoft.AspNetCore.HealthChecks\Microsoft.AspNetCore.HealthChecks.csproj", "{DF8367F8-E6BD-4D07-99D2-E416BF8AB01E}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.HealthChecks", "src\BuildingBlocks\HealthChecks\src\Microsoft.Extensions.HealthChecks\Microsoft.Extensions.HealthChecks.csproj", "{942ED6E8-0050-495F-A0EA-01E97F63760C}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.HealthChecks.Data", "src\BuildingBlocks\HealthChecks\src\Microsoft.Extensions.HealthChecks.Data\Microsoft.Extensions.HealthChecks.Data.csproj", "{7804FC60-23E6-490C-8E08-F9FEF829F184}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WebStatus", "src\Web\WebStatus\WebStatus.csproj", "{C0A7918D-B4F2-4E7F-8DE2-1E5279EF079F}"
|
||||||
|
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
|
||||||
@ -544,6 +578,342 @@ Global
|
|||||||
{CFE2FACB-4538-4B99-8A10-306F3882952D}.Release|x64.Build.0 = Release|Any CPU
|
{CFE2FACB-4538-4B99-8A10-306F3882952D}.Release|x64.Build.0 = Release|Any CPU
|
||||||
{CFE2FACB-4538-4B99-8A10-306F3882952D}.Release|x86.ActiveCfg = Release|Any CPU
|
{CFE2FACB-4538-4B99-8A10-306F3882952D}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
{CFE2FACB-4538-4B99-8A10-306F3882952D}.Release|x86.Build.0 = Release|Any CPU
|
{CFE2FACB-4538-4B99-8A10-306F3882952D}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{0044B293-1DCC-4224-B948-00CF6DC7F510}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{0044B293-1DCC-4224-B948-00CF6DC7F510}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{0044B293-1DCC-4224-B948-00CF6DC7F510}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU
|
||||||
|
{0044B293-1DCC-4224-B948-00CF6DC7F510}.Ad-Hoc|ARM.Build.0 = Debug|Any CPU
|
||||||
|
{0044B293-1DCC-4224-B948-00CF6DC7F510}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
|
||||||
|
{0044B293-1DCC-4224-B948-00CF6DC7F510}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
|
||||||
|
{0044B293-1DCC-4224-B948-00CF6DC7F510}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
|
||||||
|
{0044B293-1DCC-4224-B948-00CF6DC7F510}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
|
||||||
|
{0044B293-1DCC-4224-B948-00CF6DC7F510}.Ad-Hoc|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{0044B293-1DCC-4224-B948-00CF6DC7F510}.Ad-Hoc|x64.Build.0 = Debug|Any CPU
|
||||||
|
{0044B293-1DCC-4224-B948-00CF6DC7F510}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{0044B293-1DCC-4224-B948-00CF6DC7F510}.Ad-Hoc|x86.Build.0 = Debug|Any CPU
|
||||||
|
{0044B293-1DCC-4224-B948-00CF6DC7F510}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{0044B293-1DCC-4224-B948-00CF6DC7F510}.AppStore|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{0044B293-1DCC-4224-B948-00CF6DC7F510}.AppStore|ARM.ActiveCfg = Debug|Any CPU
|
||||||
|
{0044B293-1DCC-4224-B948-00CF6DC7F510}.AppStore|ARM.Build.0 = Debug|Any CPU
|
||||||
|
{0044B293-1DCC-4224-B948-00CF6DC7F510}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
|
||||||
|
{0044B293-1DCC-4224-B948-00CF6DC7F510}.AppStore|iPhone.Build.0 = Debug|Any CPU
|
||||||
|
{0044B293-1DCC-4224-B948-00CF6DC7F510}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
|
||||||
|
{0044B293-1DCC-4224-B948-00CF6DC7F510}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
|
||||||
|
{0044B293-1DCC-4224-B948-00CF6DC7F510}.AppStore|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{0044B293-1DCC-4224-B948-00CF6DC7F510}.AppStore|x64.Build.0 = Debug|Any CPU
|
||||||
|
{0044B293-1DCC-4224-B948-00CF6DC7F510}.AppStore|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{0044B293-1DCC-4224-B948-00CF6DC7F510}.AppStore|x86.Build.0 = Debug|Any CPU
|
||||||
|
{0044B293-1DCC-4224-B948-00CF6DC7F510}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{0044B293-1DCC-4224-B948-00CF6DC7F510}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{0044B293-1DCC-4224-B948-00CF6DC7F510}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||||
|
{0044B293-1DCC-4224-B948-00CF6DC7F510}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||||
|
{0044B293-1DCC-4224-B948-00CF6DC7F510}.Debug|iPhone.ActiveCfg = Debug|Any CPU
|
||||||
|
{0044B293-1DCC-4224-B948-00CF6DC7F510}.Debug|iPhone.Build.0 = Debug|Any CPU
|
||||||
|
{0044B293-1DCC-4224-B948-00CF6DC7F510}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
|
||||||
|
{0044B293-1DCC-4224-B948-00CF6DC7F510}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
|
||||||
|
{0044B293-1DCC-4224-B948-00CF6DC7F510}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{0044B293-1DCC-4224-B948-00CF6DC7F510}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{0044B293-1DCC-4224-B948-00CF6DC7F510}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{0044B293-1DCC-4224-B948-00CF6DC7F510}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{0044B293-1DCC-4224-B948-00CF6DC7F510}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{0044B293-1DCC-4224-B948-00CF6DC7F510}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{0044B293-1DCC-4224-B948-00CF6DC7F510}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||||
|
{0044B293-1DCC-4224-B948-00CF6DC7F510}.Release|ARM.Build.0 = Release|Any CPU
|
||||||
|
{0044B293-1DCC-4224-B948-00CF6DC7F510}.Release|iPhone.ActiveCfg = Release|Any CPU
|
||||||
|
{0044B293-1DCC-4224-B948-00CF6DC7F510}.Release|iPhone.Build.0 = Release|Any CPU
|
||||||
|
{0044B293-1DCC-4224-B948-00CF6DC7F510}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
|
||||||
|
{0044B293-1DCC-4224-B948-00CF6DC7F510}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
|
||||||
|
{0044B293-1DCC-4224-B948-00CF6DC7F510}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{0044B293-1DCC-4224-B948-00CF6DC7F510}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{0044B293-1DCC-4224-B948-00CF6DC7F510}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{0044B293-1DCC-4224-B948-00CF6DC7F510}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{8088F3FC-6787-45FA-A924-816EC81CBFAC}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{8088F3FC-6787-45FA-A924-816EC81CBFAC}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{8088F3FC-6787-45FA-A924-816EC81CBFAC}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU
|
||||||
|
{8088F3FC-6787-45FA-A924-816EC81CBFAC}.Ad-Hoc|ARM.Build.0 = Debug|Any CPU
|
||||||
|
{8088F3FC-6787-45FA-A924-816EC81CBFAC}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
|
||||||
|
{8088F3FC-6787-45FA-A924-816EC81CBFAC}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
|
||||||
|
{8088F3FC-6787-45FA-A924-816EC81CBFAC}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
|
||||||
|
{8088F3FC-6787-45FA-A924-816EC81CBFAC}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
|
||||||
|
{8088F3FC-6787-45FA-A924-816EC81CBFAC}.Ad-Hoc|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{8088F3FC-6787-45FA-A924-816EC81CBFAC}.Ad-Hoc|x64.Build.0 = Debug|Any CPU
|
||||||
|
{8088F3FC-6787-45FA-A924-816EC81CBFAC}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{8088F3FC-6787-45FA-A924-816EC81CBFAC}.Ad-Hoc|x86.Build.0 = Debug|Any CPU
|
||||||
|
{8088F3FC-6787-45FA-A924-816EC81CBFAC}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{8088F3FC-6787-45FA-A924-816EC81CBFAC}.AppStore|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{8088F3FC-6787-45FA-A924-816EC81CBFAC}.AppStore|ARM.ActiveCfg = Debug|Any CPU
|
||||||
|
{8088F3FC-6787-45FA-A924-816EC81CBFAC}.AppStore|ARM.Build.0 = Debug|Any CPU
|
||||||
|
{8088F3FC-6787-45FA-A924-816EC81CBFAC}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
|
||||||
|
{8088F3FC-6787-45FA-A924-816EC81CBFAC}.AppStore|iPhone.Build.0 = Debug|Any CPU
|
||||||
|
{8088F3FC-6787-45FA-A924-816EC81CBFAC}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
|
||||||
|
{8088F3FC-6787-45FA-A924-816EC81CBFAC}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
|
||||||
|
{8088F3FC-6787-45FA-A924-816EC81CBFAC}.AppStore|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{8088F3FC-6787-45FA-A924-816EC81CBFAC}.AppStore|x64.Build.0 = Debug|Any CPU
|
||||||
|
{8088F3FC-6787-45FA-A924-816EC81CBFAC}.AppStore|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{8088F3FC-6787-45FA-A924-816EC81CBFAC}.AppStore|x86.Build.0 = Debug|Any CPU
|
||||||
|
{8088F3FC-6787-45FA-A924-816EC81CBFAC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{8088F3FC-6787-45FA-A924-816EC81CBFAC}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{8088F3FC-6787-45FA-A924-816EC81CBFAC}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||||
|
{8088F3FC-6787-45FA-A924-816EC81CBFAC}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||||
|
{8088F3FC-6787-45FA-A924-816EC81CBFAC}.Debug|iPhone.ActiveCfg = Debug|Any CPU
|
||||||
|
{8088F3FC-6787-45FA-A924-816EC81CBFAC}.Debug|iPhone.Build.0 = Debug|Any CPU
|
||||||
|
{8088F3FC-6787-45FA-A924-816EC81CBFAC}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
|
||||||
|
{8088F3FC-6787-45FA-A924-816EC81CBFAC}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
|
||||||
|
{8088F3FC-6787-45FA-A924-816EC81CBFAC}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{8088F3FC-6787-45FA-A924-816EC81CBFAC}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{8088F3FC-6787-45FA-A924-816EC81CBFAC}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{8088F3FC-6787-45FA-A924-816EC81CBFAC}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{8088F3FC-6787-45FA-A924-816EC81CBFAC}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{8088F3FC-6787-45FA-A924-816EC81CBFAC}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{8088F3FC-6787-45FA-A924-816EC81CBFAC}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||||
|
{8088F3FC-6787-45FA-A924-816EC81CBFAC}.Release|ARM.Build.0 = Release|Any CPU
|
||||||
|
{8088F3FC-6787-45FA-A924-816EC81CBFAC}.Release|iPhone.ActiveCfg = Release|Any CPU
|
||||||
|
{8088F3FC-6787-45FA-A924-816EC81CBFAC}.Release|iPhone.Build.0 = Release|Any CPU
|
||||||
|
{8088F3FC-6787-45FA-A924-816EC81CBFAC}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
|
||||||
|
{8088F3FC-6787-45FA-A924-816EC81CBFAC}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
|
||||||
|
{8088F3FC-6787-45FA-A924-816EC81CBFAC}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{8088F3FC-6787-45FA-A924-816EC81CBFAC}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{8088F3FC-6787-45FA-A924-816EC81CBFAC}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{8088F3FC-6787-45FA-A924-816EC81CBFAC}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{9EE28E45-1533-472B-8267-56C48855BA0E}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{9EE28E45-1533-472B-8267-56C48855BA0E}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{9EE28E45-1533-472B-8267-56C48855BA0E}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU
|
||||||
|
{9EE28E45-1533-472B-8267-56C48855BA0E}.Ad-Hoc|ARM.Build.0 = Debug|Any CPU
|
||||||
|
{9EE28E45-1533-472B-8267-56C48855BA0E}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
|
||||||
|
{9EE28E45-1533-472B-8267-56C48855BA0E}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
|
||||||
|
{9EE28E45-1533-472B-8267-56C48855BA0E}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
|
||||||
|
{9EE28E45-1533-472B-8267-56C48855BA0E}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
|
||||||
|
{9EE28E45-1533-472B-8267-56C48855BA0E}.Ad-Hoc|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{9EE28E45-1533-472B-8267-56C48855BA0E}.Ad-Hoc|x64.Build.0 = Debug|Any CPU
|
||||||
|
{9EE28E45-1533-472B-8267-56C48855BA0E}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{9EE28E45-1533-472B-8267-56C48855BA0E}.Ad-Hoc|x86.Build.0 = Debug|Any CPU
|
||||||
|
{9EE28E45-1533-472B-8267-56C48855BA0E}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{9EE28E45-1533-472B-8267-56C48855BA0E}.AppStore|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{9EE28E45-1533-472B-8267-56C48855BA0E}.AppStore|ARM.ActiveCfg = Debug|Any CPU
|
||||||
|
{9EE28E45-1533-472B-8267-56C48855BA0E}.AppStore|ARM.Build.0 = Debug|Any CPU
|
||||||
|
{9EE28E45-1533-472B-8267-56C48855BA0E}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
|
||||||
|
{9EE28E45-1533-472B-8267-56C48855BA0E}.AppStore|iPhone.Build.0 = Debug|Any CPU
|
||||||
|
{9EE28E45-1533-472B-8267-56C48855BA0E}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
|
||||||
|
{9EE28E45-1533-472B-8267-56C48855BA0E}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
|
||||||
|
{9EE28E45-1533-472B-8267-56C48855BA0E}.AppStore|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{9EE28E45-1533-472B-8267-56C48855BA0E}.AppStore|x64.Build.0 = Debug|Any CPU
|
||||||
|
{9EE28E45-1533-472B-8267-56C48855BA0E}.AppStore|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{9EE28E45-1533-472B-8267-56C48855BA0E}.AppStore|x86.Build.0 = Debug|Any CPU
|
||||||
|
{9EE28E45-1533-472B-8267-56C48855BA0E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{9EE28E45-1533-472B-8267-56C48855BA0E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{9EE28E45-1533-472B-8267-56C48855BA0E}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||||
|
{9EE28E45-1533-472B-8267-56C48855BA0E}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||||
|
{9EE28E45-1533-472B-8267-56C48855BA0E}.Debug|iPhone.ActiveCfg = Debug|Any CPU
|
||||||
|
{9EE28E45-1533-472B-8267-56C48855BA0E}.Debug|iPhone.Build.0 = Debug|Any CPU
|
||||||
|
{9EE28E45-1533-472B-8267-56C48855BA0E}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
|
||||||
|
{9EE28E45-1533-472B-8267-56C48855BA0E}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
|
||||||
|
{9EE28E45-1533-472B-8267-56C48855BA0E}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{9EE28E45-1533-472B-8267-56C48855BA0E}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{9EE28E45-1533-472B-8267-56C48855BA0E}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{9EE28E45-1533-472B-8267-56C48855BA0E}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{9EE28E45-1533-472B-8267-56C48855BA0E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{9EE28E45-1533-472B-8267-56C48855BA0E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{9EE28E45-1533-472B-8267-56C48855BA0E}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||||
|
{9EE28E45-1533-472B-8267-56C48855BA0E}.Release|ARM.Build.0 = Release|Any CPU
|
||||||
|
{9EE28E45-1533-472B-8267-56C48855BA0E}.Release|iPhone.ActiveCfg = Release|Any CPU
|
||||||
|
{9EE28E45-1533-472B-8267-56C48855BA0E}.Release|iPhone.Build.0 = Release|Any CPU
|
||||||
|
{9EE28E45-1533-472B-8267-56C48855BA0E}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
|
||||||
|
{9EE28E45-1533-472B-8267-56C48855BA0E}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
|
||||||
|
{9EE28E45-1533-472B-8267-56C48855BA0E}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{9EE28E45-1533-472B-8267-56C48855BA0E}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{9EE28E45-1533-472B-8267-56C48855BA0E}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{9EE28E45-1533-472B-8267-56C48855BA0E}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{DF8367F8-E6BD-4D07-99D2-E416BF8AB01E}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{DF8367F8-E6BD-4D07-99D2-E416BF8AB01E}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{DF8367F8-E6BD-4D07-99D2-E416BF8AB01E}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU
|
||||||
|
{DF8367F8-E6BD-4D07-99D2-E416BF8AB01E}.Ad-Hoc|ARM.Build.0 = Debug|Any CPU
|
||||||
|
{DF8367F8-E6BD-4D07-99D2-E416BF8AB01E}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
|
||||||
|
{DF8367F8-E6BD-4D07-99D2-E416BF8AB01E}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
|
||||||
|
{DF8367F8-E6BD-4D07-99D2-E416BF8AB01E}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
|
||||||
|
{DF8367F8-E6BD-4D07-99D2-E416BF8AB01E}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
|
||||||
|
{DF8367F8-E6BD-4D07-99D2-E416BF8AB01E}.Ad-Hoc|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{DF8367F8-E6BD-4D07-99D2-E416BF8AB01E}.Ad-Hoc|x64.Build.0 = Debug|Any CPU
|
||||||
|
{DF8367F8-E6BD-4D07-99D2-E416BF8AB01E}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{DF8367F8-E6BD-4D07-99D2-E416BF8AB01E}.Ad-Hoc|x86.Build.0 = Debug|Any CPU
|
||||||
|
{DF8367F8-E6BD-4D07-99D2-E416BF8AB01E}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{DF8367F8-E6BD-4D07-99D2-E416BF8AB01E}.AppStore|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{DF8367F8-E6BD-4D07-99D2-E416BF8AB01E}.AppStore|ARM.ActiveCfg = Debug|Any CPU
|
||||||
|
{DF8367F8-E6BD-4D07-99D2-E416BF8AB01E}.AppStore|ARM.Build.0 = Debug|Any CPU
|
||||||
|
{DF8367F8-E6BD-4D07-99D2-E416BF8AB01E}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
|
||||||
|
{DF8367F8-E6BD-4D07-99D2-E416BF8AB01E}.AppStore|iPhone.Build.0 = Debug|Any CPU
|
||||||
|
{DF8367F8-E6BD-4D07-99D2-E416BF8AB01E}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
|
||||||
|
{DF8367F8-E6BD-4D07-99D2-E416BF8AB01E}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
|
||||||
|
{DF8367F8-E6BD-4D07-99D2-E416BF8AB01E}.AppStore|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{DF8367F8-E6BD-4D07-99D2-E416BF8AB01E}.AppStore|x64.Build.0 = Debug|Any CPU
|
||||||
|
{DF8367F8-E6BD-4D07-99D2-E416BF8AB01E}.AppStore|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{DF8367F8-E6BD-4D07-99D2-E416BF8AB01E}.AppStore|x86.Build.0 = Debug|Any CPU
|
||||||
|
{DF8367F8-E6BD-4D07-99D2-E416BF8AB01E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{DF8367F8-E6BD-4D07-99D2-E416BF8AB01E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{DF8367F8-E6BD-4D07-99D2-E416BF8AB01E}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||||
|
{DF8367F8-E6BD-4D07-99D2-E416BF8AB01E}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||||
|
{DF8367F8-E6BD-4D07-99D2-E416BF8AB01E}.Debug|iPhone.ActiveCfg = Debug|Any CPU
|
||||||
|
{DF8367F8-E6BD-4D07-99D2-E416BF8AB01E}.Debug|iPhone.Build.0 = Debug|Any CPU
|
||||||
|
{DF8367F8-E6BD-4D07-99D2-E416BF8AB01E}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
|
||||||
|
{DF8367F8-E6BD-4D07-99D2-E416BF8AB01E}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
|
||||||
|
{DF8367F8-E6BD-4D07-99D2-E416BF8AB01E}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{DF8367F8-E6BD-4D07-99D2-E416BF8AB01E}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{DF8367F8-E6BD-4D07-99D2-E416BF8AB01E}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{DF8367F8-E6BD-4D07-99D2-E416BF8AB01E}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{DF8367F8-E6BD-4D07-99D2-E416BF8AB01E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{DF8367F8-E6BD-4D07-99D2-E416BF8AB01E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{DF8367F8-E6BD-4D07-99D2-E416BF8AB01E}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||||
|
{DF8367F8-E6BD-4D07-99D2-E416BF8AB01E}.Release|ARM.Build.0 = Release|Any CPU
|
||||||
|
{DF8367F8-E6BD-4D07-99D2-E416BF8AB01E}.Release|iPhone.ActiveCfg = Release|Any CPU
|
||||||
|
{DF8367F8-E6BD-4D07-99D2-E416BF8AB01E}.Release|iPhone.Build.0 = Release|Any CPU
|
||||||
|
{DF8367F8-E6BD-4D07-99D2-E416BF8AB01E}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
|
||||||
|
{DF8367F8-E6BD-4D07-99D2-E416BF8AB01E}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
|
||||||
|
{DF8367F8-E6BD-4D07-99D2-E416BF8AB01E}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{DF8367F8-E6BD-4D07-99D2-E416BF8AB01E}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{DF8367F8-E6BD-4D07-99D2-E416BF8AB01E}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{DF8367F8-E6BD-4D07-99D2-E416BF8AB01E}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU
|
||||||
|
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Ad-Hoc|ARM.Build.0 = Debug|Any CPU
|
||||||
|
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
|
||||||
|
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
|
||||||
|
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
|
||||||
|
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
|
||||||
|
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Ad-Hoc|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Ad-Hoc|x64.Build.0 = Debug|Any CPU
|
||||||
|
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Ad-Hoc|x86.Build.0 = Debug|Any CPU
|
||||||
|
{942ED6E8-0050-495F-A0EA-01E97F63760C}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{942ED6E8-0050-495F-A0EA-01E97F63760C}.AppStore|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{942ED6E8-0050-495F-A0EA-01E97F63760C}.AppStore|ARM.ActiveCfg = Debug|Any CPU
|
||||||
|
{942ED6E8-0050-495F-A0EA-01E97F63760C}.AppStore|ARM.Build.0 = Debug|Any CPU
|
||||||
|
{942ED6E8-0050-495F-A0EA-01E97F63760C}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
|
||||||
|
{942ED6E8-0050-495F-A0EA-01E97F63760C}.AppStore|iPhone.Build.0 = Debug|Any CPU
|
||||||
|
{942ED6E8-0050-495F-A0EA-01E97F63760C}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
|
||||||
|
{942ED6E8-0050-495F-A0EA-01E97F63760C}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
|
||||||
|
{942ED6E8-0050-495F-A0EA-01E97F63760C}.AppStore|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{942ED6E8-0050-495F-A0EA-01E97F63760C}.AppStore|x64.Build.0 = Debug|Any CPU
|
||||||
|
{942ED6E8-0050-495F-A0EA-01E97F63760C}.AppStore|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{942ED6E8-0050-495F-A0EA-01E97F63760C}.AppStore|x86.Build.0 = Debug|Any CPU
|
||||||
|
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||||
|
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||||
|
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Debug|iPhone.ActiveCfg = Debug|Any CPU
|
||||||
|
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Debug|iPhone.Build.0 = Debug|Any CPU
|
||||||
|
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
|
||||||
|
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
|
||||||
|
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||||
|
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Release|ARM.Build.0 = Release|Any CPU
|
||||||
|
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Release|iPhone.ActiveCfg = Release|Any CPU
|
||||||
|
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Release|iPhone.Build.0 = Release|Any CPU
|
||||||
|
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
|
||||||
|
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
|
||||||
|
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{7804FC60-23E6-490C-8E08-F9FEF829F184}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{7804FC60-23E6-490C-8E08-F9FEF829F184}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{7804FC60-23E6-490C-8E08-F9FEF829F184}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU
|
||||||
|
{7804FC60-23E6-490C-8E08-F9FEF829F184}.Ad-Hoc|ARM.Build.0 = Debug|Any CPU
|
||||||
|
{7804FC60-23E6-490C-8E08-F9FEF829F184}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
|
||||||
|
{7804FC60-23E6-490C-8E08-F9FEF829F184}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
|
||||||
|
{7804FC60-23E6-490C-8E08-F9FEF829F184}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
|
||||||
|
{7804FC60-23E6-490C-8E08-F9FEF829F184}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
|
||||||
|
{7804FC60-23E6-490C-8E08-F9FEF829F184}.Ad-Hoc|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{7804FC60-23E6-490C-8E08-F9FEF829F184}.Ad-Hoc|x64.Build.0 = Debug|Any CPU
|
||||||
|
{7804FC60-23E6-490C-8E08-F9FEF829F184}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{7804FC60-23E6-490C-8E08-F9FEF829F184}.Ad-Hoc|x86.Build.0 = Debug|Any CPU
|
||||||
|
{7804FC60-23E6-490C-8E08-F9FEF829F184}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{7804FC60-23E6-490C-8E08-F9FEF829F184}.AppStore|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{7804FC60-23E6-490C-8E08-F9FEF829F184}.AppStore|ARM.ActiveCfg = Debug|Any CPU
|
||||||
|
{7804FC60-23E6-490C-8E08-F9FEF829F184}.AppStore|ARM.Build.0 = Debug|Any CPU
|
||||||
|
{7804FC60-23E6-490C-8E08-F9FEF829F184}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
|
||||||
|
{7804FC60-23E6-490C-8E08-F9FEF829F184}.AppStore|iPhone.Build.0 = Debug|Any CPU
|
||||||
|
{7804FC60-23E6-490C-8E08-F9FEF829F184}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
|
||||||
|
{7804FC60-23E6-490C-8E08-F9FEF829F184}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
|
||||||
|
{7804FC60-23E6-490C-8E08-F9FEF829F184}.AppStore|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{7804FC60-23E6-490C-8E08-F9FEF829F184}.AppStore|x64.Build.0 = Debug|Any CPU
|
||||||
|
{7804FC60-23E6-490C-8E08-F9FEF829F184}.AppStore|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{7804FC60-23E6-490C-8E08-F9FEF829F184}.AppStore|x86.Build.0 = Debug|Any CPU
|
||||||
|
{7804FC60-23E6-490C-8E08-F9FEF829F184}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{7804FC60-23E6-490C-8E08-F9FEF829F184}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{7804FC60-23E6-490C-8E08-F9FEF829F184}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||||
|
{7804FC60-23E6-490C-8E08-F9FEF829F184}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||||
|
{7804FC60-23E6-490C-8E08-F9FEF829F184}.Debug|iPhone.ActiveCfg = Debug|Any CPU
|
||||||
|
{7804FC60-23E6-490C-8E08-F9FEF829F184}.Debug|iPhone.Build.0 = Debug|Any CPU
|
||||||
|
{7804FC60-23E6-490C-8E08-F9FEF829F184}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
|
||||||
|
{7804FC60-23E6-490C-8E08-F9FEF829F184}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
|
||||||
|
{7804FC60-23E6-490C-8E08-F9FEF829F184}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{7804FC60-23E6-490C-8E08-F9FEF829F184}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{7804FC60-23E6-490C-8E08-F9FEF829F184}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{7804FC60-23E6-490C-8E08-F9FEF829F184}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{7804FC60-23E6-490C-8E08-F9FEF829F184}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{7804FC60-23E6-490C-8E08-F9FEF829F184}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{7804FC60-23E6-490C-8E08-F9FEF829F184}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||||
|
{7804FC60-23E6-490C-8E08-F9FEF829F184}.Release|ARM.Build.0 = Release|Any CPU
|
||||||
|
{7804FC60-23E6-490C-8E08-F9FEF829F184}.Release|iPhone.ActiveCfg = Release|Any CPU
|
||||||
|
{7804FC60-23E6-490C-8E08-F9FEF829F184}.Release|iPhone.Build.0 = Release|Any CPU
|
||||||
|
{7804FC60-23E6-490C-8E08-F9FEF829F184}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
|
||||||
|
{7804FC60-23E6-490C-8E08-F9FEF829F184}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
|
||||||
|
{7804FC60-23E6-490C-8E08-F9FEF829F184}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{7804FC60-23E6-490C-8E08-F9FEF829F184}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{7804FC60-23E6-490C-8E08-F9FEF829F184}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{7804FC60-23E6-490C-8E08-F9FEF829F184}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{C0A7918D-B4F2-4E7F-8DE2-1E5279EF079F}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{C0A7918D-B4F2-4E7F-8DE2-1E5279EF079F}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{C0A7918D-B4F2-4E7F-8DE2-1E5279EF079F}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU
|
||||||
|
{C0A7918D-B4F2-4E7F-8DE2-1E5279EF079F}.Ad-Hoc|ARM.Build.0 = Debug|Any CPU
|
||||||
|
{C0A7918D-B4F2-4E7F-8DE2-1E5279EF079F}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
|
||||||
|
{C0A7918D-B4F2-4E7F-8DE2-1E5279EF079F}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
|
||||||
|
{C0A7918D-B4F2-4E7F-8DE2-1E5279EF079F}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
|
||||||
|
{C0A7918D-B4F2-4E7F-8DE2-1E5279EF079F}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
|
||||||
|
{C0A7918D-B4F2-4E7F-8DE2-1E5279EF079F}.Ad-Hoc|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{C0A7918D-B4F2-4E7F-8DE2-1E5279EF079F}.Ad-Hoc|x64.Build.0 = Debug|Any CPU
|
||||||
|
{C0A7918D-B4F2-4E7F-8DE2-1E5279EF079F}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{C0A7918D-B4F2-4E7F-8DE2-1E5279EF079F}.Ad-Hoc|x86.Build.0 = Debug|Any CPU
|
||||||
|
{C0A7918D-B4F2-4E7F-8DE2-1E5279EF079F}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{C0A7918D-B4F2-4E7F-8DE2-1E5279EF079F}.AppStore|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{C0A7918D-B4F2-4E7F-8DE2-1E5279EF079F}.AppStore|ARM.ActiveCfg = Debug|Any CPU
|
||||||
|
{C0A7918D-B4F2-4E7F-8DE2-1E5279EF079F}.AppStore|ARM.Build.0 = Debug|Any CPU
|
||||||
|
{C0A7918D-B4F2-4E7F-8DE2-1E5279EF079F}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
|
||||||
|
{C0A7918D-B4F2-4E7F-8DE2-1E5279EF079F}.AppStore|iPhone.Build.0 = Debug|Any CPU
|
||||||
|
{C0A7918D-B4F2-4E7F-8DE2-1E5279EF079F}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
|
||||||
|
{C0A7918D-B4F2-4E7F-8DE2-1E5279EF079F}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
|
||||||
|
{C0A7918D-B4F2-4E7F-8DE2-1E5279EF079F}.AppStore|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{C0A7918D-B4F2-4E7F-8DE2-1E5279EF079F}.AppStore|x64.Build.0 = Debug|Any CPU
|
||||||
|
{C0A7918D-B4F2-4E7F-8DE2-1E5279EF079F}.AppStore|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{C0A7918D-B4F2-4E7F-8DE2-1E5279EF079F}.AppStore|x86.Build.0 = Debug|Any CPU
|
||||||
|
{C0A7918D-B4F2-4E7F-8DE2-1E5279EF079F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{C0A7918D-B4F2-4E7F-8DE2-1E5279EF079F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{C0A7918D-B4F2-4E7F-8DE2-1E5279EF079F}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||||
|
{C0A7918D-B4F2-4E7F-8DE2-1E5279EF079F}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||||
|
{C0A7918D-B4F2-4E7F-8DE2-1E5279EF079F}.Debug|iPhone.ActiveCfg = Debug|Any CPU
|
||||||
|
{C0A7918D-B4F2-4E7F-8DE2-1E5279EF079F}.Debug|iPhone.Build.0 = Debug|Any CPU
|
||||||
|
{C0A7918D-B4F2-4E7F-8DE2-1E5279EF079F}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
|
||||||
|
{C0A7918D-B4F2-4E7F-8DE2-1E5279EF079F}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
|
||||||
|
{C0A7918D-B4F2-4E7F-8DE2-1E5279EF079F}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{C0A7918D-B4F2-4E7F-8DE2-1E5279EF079F}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{C0A7918D-B4F2-4E7F-8DE2-1E5279EF079F}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{C0A7918D-B4F2-4E7F-8DE2-1E5279EF079F}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{C0A7918D-B4F2-4E7F-8DE2-1E5279EF079F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{C0A7918D-B4F2-4E7F-8DE2-1E5279EF079F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{C0A7918D-B4F2-4E7F-8DE2-1E5279EF079F}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||||
|
{C0A7918D-B4F2-4E7F-8DE2-1E5279EF079F}.Release|ARM.Build.0 = Release|Any CPU
|
||||||
|
{C0A7918D-B4F2-4E7F-8DE2-1E5279EF079F}.Release|iPhone.ActiveCfg = Release|Any CPU
|
||||||
|
{C0A7918D-B4F2-4E7F-8DE2-1E5279EF079F}.Release|iPhone.Build.0 = Release|Any CPU
|
||||||
|
{C0A7918D-B4F2-4E7F-8DE2-1E5279EF079F}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
|
||||||
|
{C0A7918D-B4F2-4E7F-8DE2-1E5279EF079F}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
|
||||||
|
{C0A7918D-B4F2-4E7F-8DE2-1E5279EF079F}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{C0A7918D-B4F2-4E7F-8DE2-1E5279EF079F}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{C0A7918D-B4F2-4E7F-8DE2-1E5279EF079F}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{C0A7918D-B4F2-4E7F-8DE2-1E5279EF079F}.Release|x86.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
@ -567,5 +937,15 @@ Global
|
|||||||
{F16E3C6A-1C94-4EAB-BE91-099618060B68} = {E279BF0F-7F66-4F3A-A3AB-2CDA66C1CD04}
|
{F16E3C6A-1C94-4EAB-BE91-099618060B68} = {E279BF0F-7F66-4F3A-A3AB-2CDA66C1CD04}
|
||||||
{5B810E3D-112E-4857-B197-F09D2FD41E27} = {EF0337F2-ED00-4643-89FD-EE10863F1870}
|
{5B810E3D-112E-4857-B197-F09D2FD41E27} = {EF0337F2-ED00-4643-89FD-EE10863F1870}
|
||||||
{CFE2FACB-4538-4B99-8A10-306F3882952D} = {EF0337F2-ED00-4643-89FD-EE10863F1870}
|
{CFE2FACB-4538-4B99-8A10-306F3882952D} = {EF0337F2-ED00-4643-89FD-EE10863F1870}
|
||||||
|
{DB0EFB20-B024-4E5E-A75C-52143C131D25} = {932D8224-11F6-4D07-B109-DA28AD288A63}
|
||||||
|
{807BB76E-B2BB-47A2-A57B-3D1B20FF5E7F} = {DB0EFB20-B024-4E5E-A75C-52143C131D25}
|
||||||
|
{0044B293-1DCC-4224-B948-00CF6DC7F510} = {807BB76E-B2BB-47A2-A57B-3D1B20FF5E7F}
|
||||||
|
{8088F3FC-6787-45FA-A924-816EC81CBFAC} = {807BB76E-B2BB-47A2-A57B-3D1B20FF5E7F}
|
||||||
|
{9EE28E45-1533-472B-8267-56C48855BA0E} = {807BB76E-B2BB-47A2-A57B-3D1B20FF5E7F}
|
||||||
|
{A81ECBC2-6B00-4DCD-8388-469174033379} = {DB0EFB20-B024-4E5E-A75C-52143C131D25}
|
||||||
|
{DF8367F8-E6BD-4D07-99D2-E416BF8AB01E} = {A81ECBC2-6B00-4DCD-8388-469174033379}
|
||||||
|
{942ED6E8-0050-495F-A0EA-01E97F63760C} = {A81ECBC2-6B00-4DCD-8388-469174033379}
|
||||||
|
{7804FC60-23E6-490C-8E08-F9FEF829F184} = {A81ECBC2-6B00-4DCD-8388-469174033379}
|
||||||
|
{C0A7918D-B4F2-4E7F-8DE2-1E5279EF079F} = {E279BF0F-7F66-4F3A-A3AB-2CDA66C1CD04}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
EndGlobal
|
EndGlobal
|
||||||
|
@ -1,18 +1,10 @@
|
|||||||
|
|
||||||
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.26213.1
|
VisualStudioVersion = 15.0.26228.9
|
||||||
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
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{3AF739CD-81D8-428D-A08A-0A58372DEBF6}"
|
|
||||||
ProjectSection(SolutionItems) = preProject
|
|
||||||
docker-compose.override.yml = docker-compose.override.yml
|
|
||||||
docker-compose.yml = docker-compose.yml
|
|
||||||
global.json = global.json
|
|
||||||
NuGet.config = NuGet.config
|
|
||||||
EndProjectSection
|
|
||||||
EndProject
|
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Services", "Services", "{91CF7717-08AB-4E65-B10E-0B426F01E2E8}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Services", "Services", "{91CF7717-08AB-4E65-B10E-0B426F01E2E8}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Web Apps", "Web Apps", "{E279BF0F-7F66-4F3A-A3AB-2CDA66C1CD04}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Web Apps", "Web Apps", "{E279BF0F-7F66-4F3A-A3AB-2CDA66C1CD04}"
|
||||||
@ -49,7 +41,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Shared Code", "Shared Code"
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Targets", "Targets", "{9CC7814B-72A6-465B-A61C-57B512DEE303}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Targets", "Targets", "{9CC7814B-72A6-465B-A61C-57B512DEE303}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WebSPA", "src\Web\WebSPA\WebSPA.csproj"", "{9842DB3A-1391-48C7-A49C-2FABD0A18AC2}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WebSPA", "src\Web\WebSPA\WebSPA.csproj", "{9842DB3A-1391-48C7-A49C-2FABD0A18AC2}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Mobile Apps", "Mobile Apps", "{B7B1D395-4E06-4036-BE86-C216756B9367}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Mobile Apps", "Mobile Apps", "{B7B1D395-4E06-4036-BE86-C216756B9367}"
|
||||||
EndProject
|
EndProject
|
||||||
@ -75,6 +67,28 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnitTest", "test\Services\U
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Identity.API", "src\Services\Identity\Identity.API\Identity.API.csproj", "{A579E108-5445-403D-A407-339AC4D1611B}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Identity.API", "src\Services\Identity\Identity.API\Identity.API.csproj", "{A579E108-5445-403D-A407-339AC4D1611B}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{E53339B2-1760-4266-BCC7-CA923CBCF16C}") = "docker-compose", "docker-compose.dcproj", "{FEA0C318-FFED-4D39-8781-265718CA43DD}"
|
||||||
|
ProjectSection(ProjectDependencies) = postProject
|
||||||
|
{A579E108-5445-403D-A407-339AC4D1611B} = {A579E108-5445-403D-A407-339AC4D1611B}
|
||||||
|
{9842DB3A-1391-48C7-A49C-2FABD0A18AC2} = {9842DB3A-1391-48C7-A49C-2FABD0A18AC2}
|
||||||
|
{F0333D8E-0B27-42B7-B2C6-78F3657624E2} = {F0333D8E-0B27-42B7-B2C6-78F3657624E2}
|
||||||
|
{42681D9D-750A-4DF7-BD9F-9292CFD5C253} = {42681D9D-750A-4DF7-BD9F-9292CFD5C253}
|
||||||
|
{2110CBB0-3B38-4EE4-A743-DF6968D80D90} = {2110CBB0-3B38-4EE4-A743-DF6968D80D90}
|
||||||
|
{231226CE-690B-4979-8870-9A79D80928E2} = {231226CE-690B-4979-8870-9A79D80928E2}
|
||||||
|
EndProjectSection
|
||||||
|
EndProject
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "BuildingBlocks", "BuildingBlocks", "{1EF3AC0F-F27C-46DD-AC53-D762D2C11C45}"
|
||||||
|
EndProject
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "EventBus", "EventBus", "{B473B70F-0796-4862-B1AD-BB742D93B868}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EventBus", "src\BuildingBlocks\EventBus\EventBus\EventBus.csproj", "{3D6B7A87-162E-4479-B256-1291BEB503B6}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EventBusRabbitMQ", "src\BuildingBlocks\EventBus\EventBusRabbitMQ\EventBusRabbitMQ.csproj", "{52AF222A-258C-4032-ACDD-857D7251BC1E}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IntegrationEventLogEF", "src\BuildingBlocks\EventBus\IntegrationEventLogEF\IntegrationEventLogEF.csproj", "{438B774F-5569-4DE2-AA62-3F8BAEB31C55}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FunctionalTests", "test\Services\FunctionalTests\FunctionalTests.csproj", "{2DA840CE-FCEA-4CF7-B1A1-ADD7775E7357}"
|
||||||
|
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
|
||||||
@ -1004,6 +1018,198 @@ Global
|
|||||||
{FEA0C318-FFED-4D39-8781-265718CA43DD}.Release|x64.Build.0 = Release|Any CPU
|
{FEA0C318-FFED-4D39-8781-265718CA43DD}.Release|x64.Build.0 = Release|Any CPU
|
||||||
{FEA0C318-FFED-4D39-8781-265718CA43DD}.Release|x86.ActiveCfg = Release|Any CPU
|
{FEA0C318-FFED-4D39-8781-265718CA43DD}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
{FEA0C318-FFED-4D39-8781-265718CA43DD}.Release|x86.Build.0 = Release|Any CPU
|
{FEA0C318-FFED-4D39-8781-265718CA43DD}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{3D6B7A87-162E-4479-B256-1291BEB503B6}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{3D6B7A87-162E-4479-B256-1291BEB503B6}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{3D6B7A87-162E-4479-B256-1291BEB503B6}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU
|
||||||
|
{3D6B7A87-162E-4479-B256-1291BEB503B6}.Ad-Hoc|ARM.Build.0 = Debug|Any CPU
|
||||||
|
{3D6B7A87-162E-4479-B256-1291BEB503B6}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
|
||||||
|
{3D6B7A87-162E-4479-B256-1291BEB503B6}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
|
||||||
|
{3D6B7A87-162E-4479-B256-1291BEB503B6}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
|
||||||
|
{3D6B7A87-162E-4479-B256-1291BEB503B6}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
|
||||||
|
{3D6B7A87-162E-4479-B256-1291BEB503B6}.Ad-Hoc|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{3D6B7A87-162E-4479-B256-1291BEB503B6}.Ad-Hoc|x64.Build.0 = Debug|Any CPU
|
||||||
|
{3D6B7A87-162E-4479-B256-1291BEB503B6}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{3D6B7A87-162E-4479-B256-1291BEB503B6}.Ad-Hoc|x86.Build.0 = Debug|Any CPU
|
||||||
|
{3D6B7A87-162E-4479-B256-1291BEB503B6}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{3D6B7A87-162E-4479-B256-1291BEB503B6}.AppStore|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{3D6B7A87-162E-4479-B256-1291BEB503B6}.AppStore|ARM.ActiveCfg = Debug|Any CPU
|
||||||
|
{3D6B7A87-162E-4479-B256-1291BEB503B6}.AppStore|ARM.Build.0 = Debug|Any CPU
|
||||||
|
{3D6B7A87-162E-4479-B256-1291BEB503B6}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
|
||||||
|
{3D6B7A87-162E-4479-B256-1291BEB503B6}.AppStore|iPhone.Build.0 = Debug|Any CPU
|
||||||
|
{3D6B7A87-162E-4479-B256-1291BEB503B6}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
|
||||||
|
{3D6B7A87-162E-4479-B256-1291BEB503B6}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
|
||||||
|
{3D6B7A87-162E-4479-B256-1291BEB503B6}.AppStore|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{3D6B7A87-162E-4479-B256-1291BEB503B6}.AppStore|x64.Build.0 = Debug|Any CPU
|
||||||
|
{3D6B7A87-162E-4479-B256-1291BEB503B6}.AppStore|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{3D6B7A87-162E-4479-B256-1291BEB503B6}.AppStore|x86.Build.0 = Debug|Any CPU
|
||||||
|
{3D6B7A87-162E-4479-B256-1291BEB503B6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{3D6B7A87-162E-4479-B256-1291BEB503B6}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{3D6B7A87-162E-4479-B256-1291BEB503B6}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||||
|
{3D6B7A87-162E-4479-B256-1291BEB503B6}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||||
|
{3D6B7A87-162E-4479-B256-1291BEB503B6}.Debug|iPhone.ActiveCfg = Debug|Any CPU
|
||||||
|
{3D6B7A87-162E-4479-B256-1291BEB503B6}.Debug|iPhone.Build.0 = Debug|Any CPU
|
||||||
|
{3D6B7A87-162E-4479-B256-1291BEB503B6}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
|
||||||
|
{3D6B7A87-162E-4479-B256-1291BEB503B6}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
|
||||||
|
{3D6B7A87-162E-4479-B256-1291BEB503B6}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{3D6B7A87-162E-4479-B256-1291BEB503B6}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{3D6B7A87-162E-4479-B256-1291BEB503B6}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{3D6B7A87-162E-4479-B256-1291BEB503B6}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{3D6B7A87-162E-4479-B256-1291BEB503B6}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{3D6B7A87-162E-4479-B256-1291BEB503B6}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{3D6B7A87-162E-4479-B256-1291BEB503B6}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||||
|
{3D6B7A87-162E-4479-B256-1291BEB503B6}.Release|ARM.Build.0 = Release|Any CPU
|
||||||
|
{3D6B7A87-162E-4479-B256-1291BEB503B6}.Release|iPhone.ActiveCfg = Release|Any CPU
|
||||||
|
{3D6B7A87-162E-4479-B256-1291BEB503B6}.Release|iPhone.Build.0 = Release|Any CPU
|
||||||
|
{3D6B7A87-162E-4479-B256-1291BEB503B6}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
|
||||||
|
{3D6B7A87-162E-4479-B256-1291BEB503B6}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
|
||||||
|
{3D6B7A87-162E-4479-B256-1291BEB503B6}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{3D6B7A87-162E-4479-B256-1291BEB503B6}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{3D6B7A87-162E-4479-B256-1291BEB503B6}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{3D6B7A87-162E-4479-B256-1291BEB503B6}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{52AF222A-258C-4032-ACDD-857D7251BC1E}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{52AF222A-258C-4032-ACDD-857D7251BC1E}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{52AF222A-258C-4032-ACDD-857D7251BC1E}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU
|
||||||
|
{52AF222A-258C-4032-ACDD-857D7251BC1E}.Ad-Hoc|ARM.Build.0 = Debug|Any CPU
|
||||||
|
{52AF222A-258C-4032-ACDD-857D7251BC1E}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
|
||||||
|
{52AF222A-258C-4032-ACDD-857D7251BC1E}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
|
||||||
|
{52AF222A-258C-4032-ACDD-857D7251BC1E}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
|
||||||
|
{52AF222A-258C-4032-ACDD-857D7251BC1E}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
|
||||||
|
{52AF222A-258C-4032-ACDD-857D7251BC1E}.Ad-Hoc|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{52AF222A-258C-4032-ACDD-857D7251BC1E}.Ad-Hoc|x64.Build.0 = Debug|Any CPU
|
||||||
|
{52AF222A-258C-4032-ACDD-857D7251BC1E}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{52AF222A-258C-4032-ACDD-857D7251BC1E}.Ad-Hoc|x86.Build.0 = Debug|Any CPU
|
||||||
|
{52AF222A-258C-4032-ACDD-857D7251BC1E}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{52AF222A-258C-4032-ACDD-857D7251BC1E}.AppStore|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{52AF222A-258C-4032-ACDD-857D7251BC1E}.AppStore|ARM.ActiveCfg = Debug|Any CPU
|
||||||
|
{52AF222A-258C-4032-ACDD-857D7251BC1E}.AppStore|ARM.Build.0 = Debug|Any CPU
|
||||||
|
{52AF222A-258C-4032-ACDD-857D7251BC1E}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
|
||||||
|
{52AF222A-258C-4032-ACDD-857D7251BC1E}.AppStore|iPhone.Build.0 = Debug|Any CPU
|
||||||
|
{52AF222A-258C-4032-ACDD-857D7251BC1E}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
|
||||||
|
{52AF222A-258C-4032-ACDD-857D7251BC1E}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
|
||||||
|
{52AF222A-258C-4032-ACDD-857D7251BC1E}.AppStore|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{52AF222A-258C-4032-ACDD-857D7251BC1E}.AppStore|x64.Build.0 = Debug|Any CPU
|
||||||
|
{52AF222A-258C-4032-ACDD-857D7251BC1E}.AppStore|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{52AF222A-258C-4032-ACDD-857D7251BC1E}.AppStore|x86.Build.0 = Debug|Any CPU
|
||||||
|
{52AF222A-258C-4032-ACDD-857D7251BC1E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{52AF222A-258C-4032-ACDD-857D7251BC1E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{52AF222A-258C-4032-ACDD-857D7251BC1E}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||||
|
{52AF222A-258C-4032-ACDD-857D7251BC1E}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||||
|
{52AF222A-258C-4032-ACDD-857D7251BC1E}.Debug|iPhone.ActiveCfg = Debug|Any CPU
|
||||||
|
{52AF222A-258C-4032-ACDD-857D7251BC1E}.Debug|iPhone.Build.0 = Debug|Any CPU
|
||||||
|
{52AF222A-258C-4032-ACDD-857D7251BC1E}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
|
||||||
|
{52AF222A-258C-4032-ACDD-857D7251BC1E}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
|
||||||
|
{52AF222A-258C-4032-ACDD-857D7251BC1E}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{52AF222A-258C-4032-ACDD-857D7251BC1E}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{52AF222A-258C-4032-ACDD-857D7251BC1E}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{52AF222A-258C-4032-ACDD-857D7251BC1E}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{52AF222A-258C-4032-ACDD-857D7251BC1E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{52AF222A-258C-4032-ACDD-857D7251BC1E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{52AF222A-258C-4032-ACDD-857D7251BC1E}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||||
|
{52AF222A-258C-4032-ACDD-857D7251BC1E}.Release|ARM.Build.0 = Release|Any CPU
|
||||||
|
{52AF222A-258C-4032-ACDD-857D7251BC1E}.Release|iPhone.ActiveCfg = Release|Any CPU
|
||||||
|
{52AF222A-258C-4032-ACDD-857D7251BC1E}.Release|iPhone.Build.0 = Release|Any CPU
|
||||||
|
{52AF222A-258C-4032-ACDD-857D7251BC1E}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
|
||||||
|
{52AF222A-258C-4032-ACDD-857D7251BC1E}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
|
||||||
|
{52AF222A-258C-4032-ACDD-857D7251BC1E}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{52AF222A-258C-4032-ACDD-857D7251BC1E}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{52AF222A-258C-4032-ACDD-857D7251BC1E}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{52AF222A-258C-4032-ACDD-857D7251BC1E}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{438B774F-5569-4DE2-AA62-3F8BAEB31C55}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{438B774F-5569-4DE2-AA62-3F8BAEB31C55}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{438B774F-5569-4DE2-AA62-3F8BAEB31C55}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU
|
||||||
|
{438B774F-5569-4DE2-AA62-3F8BAEB31C55}.Ad-Hoc|ARM.Build.0 = Debug|Any CPU
|
||||||
|
{438B774F-5569-4DE2-AA62-3F8BAEB31C55}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
|
||||||
|
{438B774F-5569-4DE2-AA62-3F8BAEB31C55}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
|
||||||
|
{438B774F-5569-4DE2-AA62-3F8BAEB31C55}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
|
||||||
|
{438B774F-5569-4DE2-AA62-3F8BAEB31C55}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
|
||||||
|
{438B774F-5569-4DE2-AA62-3F8BAEB31C55}.Ad-Hoc|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{438B774F-5569-4DE2-AA62-3F8BAEB31C55}.Ad-Hoc|x64.Build.0 = Debug|Any CPU
|
||||||
|
{438B774F-5569-4DE2-AA62-3F8BAEB31C55}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{438B774F-5569-4DE2-AA62-3F8BAEB31C55}.Ad-Hoc|x86.Build.0 = Debug|Any CPU
|
||||||
|
{438B774F-5569-4DE2-AA62-3F8BAEB31C55}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{438B774F-5569-4DE2-AA62-3F8BAEB31C55}.AppStore|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{438B774F-5569-4DE2-AA62-3F8BAEB31C55}.AppStore|ARM.ActiveCfg = Debug|Any CPU
|
||||||
|
{438B774F-5569-4DE2-AA62-3F8BAEB31C55}.AppStore|ARM.Build.0 = Debug|Any CPU
|
||||||
|
{438B774F-5569-4DE2-AA62-3F8BAEB31C55}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
|
||||||
|
{438B774F-5569-4DE2-AA62-3F8BAEB31C55}.AppStore|iPhone.Build.0 = Debug|Any CPU
|
||||||
|
{438B774F-5569-4DE2-AA62-3F8BAEB31C55}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
|
||||||
|
{438B774F-5569-4DE2-AA62-3F8BAEB31C55}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
|
||||||
|
{438B774F-5569-4DE2-AA62-3F8BAEB31C55}.AppStore|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{438B774F-5569-4DE2-AA62-3F8BAEB31C55}.AppStore|x64.Build.0 = Debug|Any CPU
|
||||||
|
{438B774F-5569-4DE2-AA62-3F8BAEB31C55}.AppStore|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{438B774F-5569-4DE2-AA62-3F8BAEB31C55}.AppStore|x86.Build.0 = Debug|Any CPU
|
||||||
|
{438B774F-5569-4DE2-AA62-3F8BAEB31C55}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{438B774F-5569-4DE2-AA62-3F8BAEB31C55}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{438B774F-5569-4DE2-AA62-3F8BAEB31C55}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||||
|
{438B774F-5569-4DE2-AA62-3F8BAEB31C55}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||||
|
{438B774F-5569-4DE2-AA62-3F8BAEB31C55}.Debug|iPhone.ActiveCfg = Debug|Any CPU
|
||||||
|
{438B774F-5569-4DE2-AA62-3F8BAEB31C55}.Debug|iPhone.Build.0 = Debug|Any CPU
|
||||||
|
{438B774F-5569-4DE2-AA62-3F8BAEB31C55}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
|
||||||
|
{438B774F-5569-4DE2-AA62-3F8BAEB31C55}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
|
||||||
|
{438B774F-5569-4DE2-AA62-3F8BAEB31C55}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{438B774F-5569-4DE2-AA62-3F8BAEB31C55}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{438B774F-5569-4DE2-AA62-3F8BAEB31C55}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{438B774F-5569-4DE2-AA62-3F8BAEB31C55}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{438B774F-5569-4DE2-AA62-3F8BAEB31C55}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{438B774F-5569-4DE2-AA62-3F8BAEB31C55}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{438B774F-5569-4DE2-AA62-3F8BAEB31C55}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||||
|
{438B774F-5569-4DE2-AA62-3F8BAEB31C55}.Release|ARM.Build.0 = Release|Any CPU
|
||||||
|
{438B774F-5569-4DE2-AA62-3F8BAEB31C55}.Release|iPhone.ActiveCfg = Release|Any CPU
|
||||||
|
{438B774F-5569-4DE2-AA62-3F8BAEB31C55}.Release|iPhone.Build.0 = Release|Any CPU
|
||||||
|
{438B774F-5569-4DE2-AA62-3F8BAEB31C55}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
|
||||||
|
{438B774F-5569-4DE2-AA62-3F8BAEB31C55}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
|
||||||
|
{438B774F-5569-4DE2-AA62-3F8BAEB31C55}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{438B774F-5569-4DE2-AA62-3F8BAEB31C55}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{438B774F-5569-4DE2-AA62-3F8BAEB31C55}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{438B774F-5569-4DE2-AA62-3F8BAEB31C55}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{2DA840CE-FCEA-4CF7-B1A1-ADD7775E7357}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{2DA840CE-FCEA-4CF7-B1A1-ADD7775E7357}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{2DA840CE-FCEA-4CF7-B1A1-ADD7775E7357}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU
|
||||||
|
{2DA840CE-FCEA-4CF7-B1A1-ADD7775E7357}.Ad-Hoc|ARM.Build.0 = Debug|Any CPU
|
||||||
|
{2DA840CE-FCEA-4CF7-B1A1-ADD7775E7357}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
|
||||||
|
{2DA840CE-FCEA-4CF7-B1A1-ADD7775E7357}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
|
||||||
|
{2DA840CE-FCEA-4CF7-B1A1-ADD7775E7357}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
|
||||||
|
{2DA840CE-FCEA-4CF7-B1A1-ADD7775E7357}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
|
||||||
|
{2DA840CE-FCEA-4CF7-B1A1-ADD7775E7357}.Ad-Hoc|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{2DA840CE-FCEA-4CF7-B1A1-ADD7775E7357}.Ad-Hoc|x64.Build.0 = Debug|Any CPU
|
||||||
|
{2DA840CE-FCEA-4CF7-B1A1-ADD7775E7357}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{2DA840CE-FCEA-4CF7-B1A1-ADD7775E7357}.Ad-Hoc|x86.Build.0 = Debug|Any CPU
|
||||||
|
{2DA840CE-FCEA-4CF7-B1A1-ADD7775E7357}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{2DA840CE-FCEA-4CF7-B1A1-ADD7775E7357}.AppStore|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{2DA840CE-FCEA-4CF7-B1A1-ADD7775E7357}.AppStore|ARM.ActiveCfg = Debug|Any CPU
|
||||||
|
{2DA840CE-FCEA-4CF7-B1A1-ADD7775E7357}.AppStore|ARM.Build.0 = Debug|Any CPU
|
||||||
|
{2DA840CE-FCEA-4CF7-B1A1-ADD7775E7357}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
|
||||||
|
{2DA840CE-FCEA-4CF7-B1A1-ADD7775E7357}.AppStore|iPhone.Build.0 = Debug|Any CPU
|
||||||
|
{2DA840CE-FCEA-4CF7-B1A1-ADD7775E7357}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
|
||||||
|
{2DA840CE-FCEA-4CF7-B1A1-ADD7775E7357}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
|
||||||
|
{2DA840CE-FCEA-4CF7-B1A1-ADD7775E7357}.AppStore|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{2DA840CE-FCEA-4CF7-B1A1-ADD7775E7357}.AppStore|x64.Build.0 = Debug|Any CPU
|
||||||
|
{2DA840CE-FCEA-4CF7-B1A1-ADD7775E7357}.AppStore|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{2DA840CE-FCEA-4CF7-B1A1-ADD7775E7357}.AppStore|x86.Build.0 = Debug|Any CPU
|
||||||
|
{2DA840CE-FCEA-4CF7-B1A1-ADD7775E7357}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{2DA840CE-FCEA-4CF7-B1A1-ADD7775E7357}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{2DA840CE-FCEA-4CF7-B1A1-ADD7775E7357}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||||
|
{2DA840CE-FCEA-4CF7-B1A1-ADD7775E7357}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||||
|
{2DA840CE-FCEA-4CF7-B1A1-ADD7775E7357}.Debug|iPhone.ActiveCfg = Debug|Any CPU
|
||||||
|
{2DA840CE-FCEA-4CF7-B1A1-ADD7775E7357}.Debug|iPhone.Build.0 = Debug|Any CPU
|
||||||
|
{2DA840CE-FCEA-4CF7-B1A1-ADD7775E7357}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
|
||||||
|
{2DA840CE-FCEA-4CF7-B1A1-ADD7775E7357}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
|
||||||
|
{2DA840CE-FCEA-4CF7-B1A1-ADD7775E7357}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{2DA840CE-FCEA-4CF7-B1A1-ADD7775E7357}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{2DA840CE-FCEA-4CF7-B1A1-ADD7775E7357}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{2DA840CE-FCEA-4CF7-B1A1-ADD7775E7357}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{2DA840CE-FCEA-4CF7-B1A1-ADD7775E7357}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{2DA840CE-FCEA-4CF7-B1A1-ADD7775E7357}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{2DA840CE-FCEA-4CF7-B1A1-ADD7775E7357}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||||
|
{2DA840CE-FCEA-4CF7-B1A1-ADD7775E7357}.Release|ARM.Build.0 = Release|Any CPU
|
||||||
|
{2DA840CE-FCEA-4CF7-B1A1-ADD7775E7357}.Release|iPhone.ActiveCfg = Release|Any CPU
|
||||||
|
{2DA840CE-FCEA-4CF7-B1A1-ADD7775E7357}.Release|iPhone.Build.0 = Release|Any CPU
|
||||||
|
{2DA840CE-FCEA-4CF7-B1A1-ADD7775E7357}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
|
||||||
|
{2DA840CE-FCEA-4CF7-B1A1-ADD7775E7357}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
|
||||||
|
{2DA840CE-FCEA-4CF7-B1A1-ADD7775E7357}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{2DA840CE-FCEA-4CF7-B1A1-ADD7775E7357}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{2DA840CE-FCEA-4CF7-B1A1-ADD7775E7357}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{2DA840CE-FCEA-4CF7-B1A1-ADD7775E7357}.Release|x86.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
@ -1039,5 +1245,11 @@ Global
|
|||||||
{67F9D3A8-F71E-4428-913F-C37AE82CDB24} = {778289CA-31F7-4464-8C2A-612EE846F8A7}
|
{67F9D3A8-F71E-4428-913F-C37AE82CDB24} = {778289CA-31F7-4464-8C2A-612EE846F8A7}
|
||||||
{7796F5D8-31FC-45A4-B673-19DE5BA194CF} = {EF0337F2-ED00-4643-89FD-EE10863F1870}
|
{7796F5D8-31FC-45A4-B673-19DE5BA194CF} = {EF0337F2-ED00-4643-89FD-EE10863F1870}
|
||||||
{A579E108-5445-403D-A407-339AC4D1611B} = {02DF7FEE-C302-433D-A6CD-237A2569F236}
|
{A579E108-5445-403D-A407-339AC4D1611B} = {02DF7FEE-C302-433D-A6CD-237A2569F236}
|
||||||
|
{1EF3AC0F-F27C-46DD-AC53-D762D2C11C45} = {932D8224-11F6-4D07-B109-DA28AD288A63}
|
||||||
|
{B473B70F-0796-4862-B1AD-BB742D93B868} = {1EF3AC0F-F27C-46DD-AC53-D762D2C11C45}
|
||||||
|
{3D6B7A87-162E-4479-B256-1291BEB503B6} = {B473B70F-0796-4862-B1AD-BB742D93B868}
|
||||||
|
{52AF222A-258C-4032-ACDD-857D7251BC1E} = {B473B70F-0796-4862-B1AD-BB742D93B868}
|
||||||
|
{438B774F-5569-4DE2-AA62-3F8BAEB31C55} = {B473B70F-0796-4862-B1AD-BB742D93B868}
|
||||||
|
{2DA840CE-FCEA-4CF7-B1A1-ADD7775E7357} = {EF0337F2-ED00-4643-89FD-EE10863F1870}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
EndGlobal
|
EndGlobal
|
||||||
|
@ -0,0 +1,14 @@
|
|||||||
|
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions
|
||||||
|
{
|
||||||
|
public interface IEventBus
|
||||||
|
{
|
||||||
|
void Subscribe<T>(IIntegrationEventHandler<T> handler) where T: IntegrationEvent;
|
||||||
|
void Unsubscribe<T>(IIntegrationEventHandler<T> handler) where T : IntegrationEvent;
|
||||||
|
void Publish(IntegrationEvent @event);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions
|
||||||
|
{
|
||||||
|
public interface IIntegrationEventHandler<in TIntegrationEvent> : IIntegrationEventHandler
|
||||||
|
where TIntegrationEvent: IntegrationEvent
|
||||||
|
{
|
||||||
|
Task Handle(TIntegrationEvent @event);
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface IIntegrationEventHandler
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
17
src/BuildingBlocks/EventBus/EventBus/EventBus.csproj
Normal file
17
src/BuildingBlocks/EventBus/EventBus/EventBus.csproj
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>netcoreapp1.1</TargetFramework>
|
||||||
|
<RuntimeFrameworkVersion>1.1.0</RuntimeFrameworkVersion>
|
||||||
|
<RootNamespace>Microsoft.eShopOnContainers.BuildingBlocks.EventBus</RootNamespace>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Folder Include="Abstractions\" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Newtonsoft.Json" Version="9.0.1" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
@ -0,0 +1,18 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events
|
||||||
|
{
|
||||||
|
public class IntegrationEvent
|
||||||
|
{
|
||||||
|
public IntegrationEvent()
|
||||||
|
{
|
||||||
|
Id = Guid.NewGuid();
|
||||||
|
CreationDate = DateTime.UtcNow;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Guid Id { get; }
|
||||||
|
public DateTime CreationDate { get; }
|
||||||
|
}
|
||||||
|
}
|
171
src/BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.cs
Normal file
171
src/BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.cs
Normal file
@ -0,0 +1,171 @@
|
|||||||
|
|
||||||
|
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions;
|
||||||
|
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using RabbitMQ.Client;
|
||||||
|
using RabbitMQ.Client.Events;
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ
|
||||||
|
{
|
||||||
|
public class EventBusRabbitMQ : IEventBus, IDisposable
|
||||||
|
{
|
||||||
|
private readonly string _brokerName = "eshop_event_bus";
|
||||||
|
private readonly string _connectionString;
|
||||||
|
private readonly Dictionary<string, List<IIntegrationEventHandler>> _handlers;
|
||||||
|
private readonly List<Type> _eventTypes;
|
||||||
|
|
||||||
|
private IModel _model;
|
||||||
|
private IConnection _connection;
|
||||||
|
private string _queueName;
|
||||||
|
|
||||||
|
|
||||||
|
public EventBusRabbitMQ(string connectionString)
|
||||||
|
{
|
||||||
|
_connectionString = connectionString;
|
||||||
|
_handlers = new Dictionary<string, List<IIntegrationEventHandler>>();
|
||||||
|
_eventTypes = new List<Type>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Publish(IntegrationEvent @event)
|
||||||
|
{
|
||||||
|
var eventName = @event.GetType().Name;
|
||||||
|
var factory = new ConnectionFactory() { HostName = _connectionString };
|
||||||
|
using (var connection = factory.CreateConnection())
|
||||||
|
using (var channel = connection.CreateModel())
|
||||||
|
{
|
||||||
|
channel.ExchangeDeclare(exchange: _brokerName,
|
||||||
|
type: "direct");
|
||||||
|
|
||||||
|
string message = JsonConvert.SerializeObject(@event);
|
||||||
|
var body = Encoding.UTF8.GetBytes(message);
|
||||||
|
|
||||||
|
channel.BasicPublish(exchange: _brokerName,
|
||||||
|
routingKey: eventName,
|
||||||
|
basicProperties: null,
|
||||||
|
body: body);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Subscribe<T>(IIntegrationEventHandler<T> handler) where T : IntegrationEvent
|
||||||
|
{
|
||||||
|
var eventName = typeof(T).Name;
|
||||||
|
if (_handlers.ContainsKey(eventName))
|
||||||
|
{
|
||||||
|
_handlers[eventName].Add(handler);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var channel = GetChannel();
|
||||||
|
channel.QueueBind(queue: _queueName,
|
||||||
|
exchange: _brokerName,
|
||||||
|
routingKey: eventName);
|
||||||
|
|
||||||
|
_handlers.Add(eventName, new List<IIntegrationEventHandler>());
|
||||||
|
_handlers[eventName].Add(handler);
|
||||||
|
_eventTypes.Add(typeof(T));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Unsubscribe<T>(IIntegrationEventHandler<T> handler) where T : IntegrationEvent
|
||||||
|
{
|
||||||
|
var eventName = typeof(T).Name;
|
||||||
|
if (_handlers.ContainsKey(eventName) && _handlers[eventName].Contains(handler))
|
||||||
|
{
|
||||||
|
_handlers[eventName].Remove(handler);
|
||||||
|
|
||||||
|
if (_handlers[eventName].Count == 0)
|
||||||
|
{
|
||||||
|
_handlers.Remove(eventName);
|
||||||
|
var eventType = _eventTypes.Single(e => e.Name == eventName);
|
||||||
|
_eventTypes.Remove(eventType);
|
||||||
|
_model.QueueUnbind(queue: _queueName,
|
||||||
|
exchange: _brokerName,
|
||||||
|
routingKey: eventName);
|
||||||
|
|
||||||
|
if (_handlers.Keys.Count == 0)
|
||||||
|
{
|
||||||
|
_queueName = string.Empty;
|
||||||
|
_model.Dispose();
|
||||||
|
_connection.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
_handlers.Clear();
|
||||||
|
_model?.Dispose();
|
||||||
|
_connection?.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
private IModel GetChannel()
|
||||||
|
{
|
||||||
|
if (_model != null)
|
||||||
|
{
|
||||||
|
return _model;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
(_model, _connection) = CreateConnection();
|
||||||
|
return _model;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private (IModel model, IConnection connection) CreateConnection()
|
||||||
|
{
|
||||||
|
var factory = new ConnectionFactory() { HostName = _connectionString };
|
||||||
|
var con = factory.CreateConnection();
|
||||||
|
var channel = con.CreateModel();
|
||||||
|
|
||||||
|
channel.ExchangeDeclare(exchange: _brokerName,
|
||||||
|
type: "direct");
|
||||||
|
if (string.IsNullOrEmpty(_queueName))
|
||||||
|
{
|
||||||
|
_queueName = channel.QueueDeclare().QueueName;
|
||||||
|
}
|
||||||
|
|
||||||
|
var consumer = new EventingBasicConsumer(channel);
|
||||||
|
consumer.Received += async (model, ea) =>
|
||||||
|
{
|
||||||
|
var eventName = ea.RoutingKey;
|
||||||
|
var message = Encoding.UTF8.GetString(ea.Body);
|
||||||
|
|
||||||
|
await ProcessEvent(eventName, message);
|
||||||
|
};
|
||||||
|
channel.BasicConsume(queue: _queueName,
|
||||||
|
noAck: true,
|
||||||
|
consumer: consumer);
|
||||||
|
|
||||||
|
return (channel, con);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task ProcessEvent(string eventName, string message)
|
||||||
|
{
|
||||||
|
if (_handlers.ContainsKey(eventName))
|
||||||
|
{
|
||||||
|
Type eventType = _eventTypes.Single(t => t.Name == eventName);
|
||||||
|
var integrationEvent = JsonConvert.DeserializeObject(message, eventType);
|
||||||
|
var concreteType = typeof(IIntegrationEventHandler<>).MakeGenericType(eventType);
|
||||||
|
var handlers = _handlers[eventName];
|
||||||
|
|
||||||
|
foreach (var handler in handlers)
|
||||||
|
{
|
||||||
|
await (Task)concreteType.GetMethod("Handle").Invoke(handler, new object[] { integrationEvent });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>netcoreapp1.1</TargetFramework>
|
||||||
|
<RuntimeFrameworkVersion>1.1.0</RuntimeFrameworkVersion>
|
||||||
|
<RootNamespace>Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ</RootNamespace>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Newtonsoft.Json" Version="9.0.1" />
|
||||||
|
<PackageReference Include="RabbitMQ.Client" Version="4.1.1" />
|
||||||
|
<PackageReference Include="System.ValueTuple" Version="4.3.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\EventBus\EventBus.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
@ -0,0 +1,13 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF
|
||||||
|
{
|
||||||
|
public enum EventStateEnum
|
||||||
|
{
|
||||||
|
NotPublished = 0,
|
||||||
|
Published = 1,
|
||||||
|
PublishedFailed = 2
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,48 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF
|
||||||
|
{
|
||||||
|
public class IntegrationEventLogContext : DbContext
|
||||||
|
{
|
||||||
|
public IntegrationEventLogContext(DbContextOptions<IntegrationEventLogContext> options) : base(options)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public DbSet<IntegrationEventLogEntry> IntegrationEventLogs { get; set; }
|
||||||
|
|
||||||
|
protected override void OnModelCreating(ModelBuilder builder)
|
||||||
|
{
|
||||||
|
builder.Entity<IntegrationEventLogEntry>(ConfigureIntegrationEventLogEntry);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConfigureIntegrationEventLogEntry(EntityTypeBuilder<IntegrationEventLogEntry> builder)
|
||||||
|
{
|
||||||
|
builder.ToTable("IntegrationEventLog");
|
||||||
|
|
||||||
|
builder.HasKey(e => e.EventId);
|
||||||
|
|
||||||
|
builder.Property(e => e.EventId)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
builder.Property(e => e.Content)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
builder.Property(e => e.CreationTime)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
builder.Property(e => e.State)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
builder.Property(e => e.TimesSent)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
builder.Property(e => e.EventTypeName)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>netcoreapp1.1</TargetFramework>
|
||||||
|
<RuntimeFrameworkVersion>1.1.0</RuntimeFrameworkVersion>
|
||||||
|
<RootNamespace>Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF</RootNamespace>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="1.1.1" />
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="1.1.1" />
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="1.1.1" />
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="1.1.1" />
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer.Design" Version="1.1.1" />
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="1.1.0" />
|
||||||
|
<PackageReference Include="Newtonsoft.Json" Version="9.0.1" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<DotNetCliToolReference Include="Microsoft.EntityFrameworkCore.Tools.DotNet" Version="1.0.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\EventBus\EventBus.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
@ -0,0 +1,28 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events;
|
||||||
|
|
||||||
|
namespace Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF
|
||||||
|
{
|
||||||
|
public class IntegrationEventLogEntry
|
||||||
|
{
|
||||||
|
private IntegrationEventLogEntry() { }
|
||||||
|
public IntegrationEventLogEntry(IntegrationEvent @event)
|
||||||
|
{
|
||||||
|
EventId = @event.Id;
|
||||||
|
CreationTime = @event.CreationDate;
|
||||||
|
EventTypeName = @event.GetType().FullName;
|
||||||
|
Content = JsonConvert.SerializeObject(@event);
|
||||||
|
State = EventStateEnum.NotPublished;
|
||||||
|
TimesSent = 0;
|
||||||
|
}
|
||||||
|
public Guid EventId { get; private set; }
|
||||||
|
public string EventTypeName { get; private set; }
|
||||||
|
public EventStateEnum State { get; set; }
|
||||||
|
public int TimesSent { get; set; }
|
||||||
|
public DateTime CreationTime { get; private set; }
|
||||||
|
public string Content { get; private set; }
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,15 @@
|
|||||||
|
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Data.Common;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF.Services
|
||||||
|
{
|
||||||
|
public interface IIntegrationEventLogService
|
||||||
|
{
|
||||||
|
Task SaveEventAsync(IntegrationEvent @event, DbTransaction transaction);
|
||||||
|
Task MarkEventAsPublishedAsync(IntegrationEvent @event);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,53 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage;
|
||||||
|
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events;
|
||||||
|
using System.Data.Common;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF.Services
|
||||||
|
{
|
||||||
|
public class IntegrationEventLogService : IIntegrationEventLogService
|
||||||
|
{
|
||||||
|
private readonly IntegrationEventLogContext _integrationEventLogContext;
|
||||||
|
private readonly DbConnection _dbConnection;
|
||||||
|
|
||||||
|
public IntegrationEventLogService(DbConnection dbConnection)
|
||||||
|
{
|
||||||
|
_dbConnection = dbConnection?? throw new ArgumentNullException("dbConnection");
|
||||||
|
_integrationEventLogContext = new IntegrationEventLogContext(
|
||||||
|
new DbContextOptionsBuilder<IntegrationEventLogContext>()
|
||||||
|
.UseSqlServer(_dbConnection)
|
||||||
|
.ConfigureWarnings(warnings => warnings.Throw(RelationalEventId.QueryClientEvaluationWarning))
|
||||||
|
.Options);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task SaveEventAsync(IntegrationEvent @event, DbTransaction transaction)
|
||||||
|
{
|
||||||
|
if(transaction == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException("transaction", $"A {typeof(DbTransaction).FullName} is required as a pre-requisite to save the event.");
|
||||||
|
}
|
||||||
|
|
||||||
|
var eventLogEntry = new IntegrationEventLogEntry(@event);
|
||||||
|
|
||||||
|
_integrationEventLogContext.Database.UseTransaction(transaction);
|
||||||
|
_integrationEventLogContext.IntegrationEventLogs.Add(eventLogEntry);
|
||||||
|
|
||||||
|
return _integrationEventLogContext.SaveChangesAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task MarkEventAsPublishedAsync(IntegrationEvent @event)
|
||||||
|
{
|
||||||
|
var eventLogEntry = _integrationEventLogContext.IntegrationEventLogs.Single(ie => ie.EventId == @event.Id);
|
||||||
|
eventLogEntry.TimesSent++;
|
||||||
|
eventLogEntry.State = EventStateEnum.Published;
|
||||||
|
|
||||||
|
_integrationEventLogContext.IntegrationEventLogs.Update(eventLogEntry);
|
||||||
|
|
||||||
|
return _integrationEventLogContext.SaveChangesAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,68 @@
|
|||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.AspNetCore.Http.Features;
|
||||||
|
using Microsoft.Extensions.HealthChecks;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.HealthChecks
|
||||||
|
{
|
||||||
|
public class HealthCheckMiddleware
|
||||||
|
{
|
||||||
|
private RequestDelegate _next;
|
||||||
|
private string _path;
|
||||||
|
private int? _port;
|
||||||
|
private IHealthCheckService _service;
|
||||||
|
|
||||||
|
public HealthCheckMiddleware(RequestDelegate next, IHealthCheckService service, int port)
|
||||||
|
{
|
||||||
|
_port = port;
|
||||||
|
_service = service;
|
||||||
|
_next = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
public HealthCheckMiddleware(RequestDelegate next, IHealthCheckService service, string path)
|
||||||
|
{
|
||||||
|
_path = path;
|
||||||
|
_service = service;
|
||||||
|
_next = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task Invoke(HttpContext context)
|
||||||
|
{
|
||||||
|
if (IsHealthCheckRequest(context))
|
||||||
|
{
|
||||||
|
var result = await _service.CheckHealthAsync();
|
||||||
|
var status = result.CheckStatus;
|
||||||
|
|
||||||
|
if (status != CheckStatus.Healthy)
|
||||||
|
context.Response.StatusCode = 503;
|
||||||
|
|
||||||
|
context.Response.Headers.Add("content-type", "application/json");
|
||||||
|
await context.Response.WriteAsync(JsonConvert.SerializeObject(new { status = status.ToString() }));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
await _next.Invoke(context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool IsHealthCheckRequest(HttpContext context)
|
||||||
|
{
|
||||||
|
if (_port.HasValue)
|
||||||
|
{
|
||||||
|
var connInfo = context.Features.Get<IHttpConnectionFeature>();
|
||||||
|
if (connInfo.LocalPort == _port)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (context.Request.Path == _path)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,38 @@
|
|||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using Microsoft.AspNetCore.Builder;
|
||||||
|
using Microsoft.AspNetCore.Hosting;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.HealthChecks
|
||||||
|
{
|
||||||
|
public class HealthCheckStartupFilter : IStartupFilter
|
||||||
|
{
|
||||||
|
private string _path;
|
||||||
|
private int? _port;
|
||||||
|
|
||||||
|
public HealthCheckStartupFilter(int port)
|
||||||
|
{
|
||||||
|
_port = port;
|
||||||
|
}
|
||||||
|
|
||||||
|
public HealthCheckStartupFilter(string path)
|
||||||
|
{
|
||||||
|
_path = path;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Action<IApplicationBuilder> Configure(Action<IApplicationBuilder> next)
|
||||||
|
{
|
||||||
|
return app =>
|
||||||
|
{
|
||||||
|
if (_port.HasValue)
|
||||||
|
app.UseMiddleware<HealthCheckMiddleware>(_port);
|
||||||
|
else
|
||||||
|
app.UseMiddleware<HealthCheckMiddleware>(_path);
|
||||||
|
|
||||||
|
next(app);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,36 @@
|
|||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using Microsoft.AspNetCore.HealthChecks;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Hosting
|
||||||
|
{
|
||||||
|
public static class HealthCheckWebHostBuilderExtension
|
||||||
|
{
|
||||||
|
public static IWebHostBuilder UseHealthChecks(this IWebHostBuilder builder, int port)
|
||||||
|
{
|
||||||
|
Guard.ArgumentValid(port > 0 && port < 65536, nameof(port), "Port must be a value between 1 and 65535");
|
||||||
|
|
||||||
|
builder.ConfigureServices(services =>
|
||||||
|
{
|
||||||
|
var existingUrl = builder.GetSetting(WebHostDefaults.ServerUrlsKey);
|
||||||
|
builder.UseSetting(WebHostDefaults.ServerUrlsKey, $"{existingUrl};http://localhost:{port}");
|
||||||
|
|
||||||
|
services.AddSingleton<IStartupFilter>(new HealthCheckStartupFilter(port));
|
||||||
|
});
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IWebHostBuilder UseHealthChecks(this IWebHostBuilder builder, string path)
|
||||||
|
{
|
||||||
|
Guard.ArgumentNotNull(nameof(path), path);
|
||||||
|
// REVIEW: Is there a better URL path validator somewhere?
|
||||||
|
Guard.ArgumentValid(!path.Contains("?"), nameof(path), "Path cannot contain query string values");
|
||||||
|
Guard.ArgumentValid(path.StartsWith("/"), nameof(path), "Path should start with /");
|
||||||
|
|
||||||
|
builder.ConfigureServices(services => services.AddSingleton<IStartupFilter>(new HealthCheckStartupFilter(path)));
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,38 @@
|
|||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using Microsoft.Extensions.HealthChecks;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Hosting
|
||||||
|
{
|
||||||
|
public static class HealthCheckWebHostExtensions
|
||||||
|
{
|
||||||
|
private const int DEFAULT_TIMEOUT_SECONDS = 300;
|
||||||
|
|
||||||
|
public static void RunWhenHealthy(this IWebHost webHost)
|
||||||
|
{
|
||||||
|
webHost.RunWhenHealthy(TimeSpan.FromSeconds(DEFAULT_TIMEOUT_SECONDS));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void RunWhenHealthy(this IWebHost webHost, TimeSpan timeout)
|
||||||
|
{
|
||||||
|
var healthChecks = webHost.Services.GetService(typeof(IHealthCheckService)) as IHealthCheckService;
|
||||||
|
|
||||||
|
var loops = 0;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
var checkResult = healthChecks.CheckHealthAsync().Result;
|
||||||
|
if (checkResult.CheckStatus == CheckStatus.Healthy)
|
||||||
|
{
|
||||||
|
webHost.Run();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
System.Threading.Thread.Sleep(1000);
|
||||||
|
loops++;
|
||||||
|
|
||||||
|
} while (loops < timeout.TotalSeconds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,16 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>netcoreapp1.0</TargetFramework>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Include="..\common\Guard.cs" Link="Internal\Guard.cs" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore.Hosting" Version="1.0.2" />
|
||||||
|
<ProjectReference Include="..\Microsoft.Extensions.HealthChecks\Microsoft.Extensions.HealthChecks.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
@ -0,0 +1,45 @@
|
|||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Data;
|
||||||
|
using System.Data.SqlClient;
|
||||||
|
|
||||||
|
namespace Microsoft.Extensions.HealthChecks
|
||||||
|
{
|
||||||
|
public static class HealthCheckBuilderDataExtensions
|
||||||
|
{
|
||||||
|
public static HealthCheckBuilder AddSqlCheck(this HealthCheckBuilder builder, string name, string connectionString)
|
||||||
|
{
|
||||||
|
builder.AddCheck($"SqlCheck({name})", async () =>
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
//TODO: There is probably a much better way to do this.
|
||||||
|
using (var connection = new SqlConnection(connectionString))
|
||||||
|
{
|
||||||
|
connection.Open();
|
||||||
|
using (var command = connection.CreateCommand())
|
||||||
|
{
|
||||||
|
command.CommandType = CommandType.Text;
|
||||||
|
command.CommandText = "SELECT 1";
|
||||||
|
var result = (int)await command.ExecuteScalarAsync().ConfigureAwait(false);
|
||||||
|
if (result == 1)
|
||||||
|
{
|
||||||
|
return HealthCheckResult.Healthy($"SqlCheck({name}): Healthy");
|
||||||
|
}
|
||||||
|
|
||||||
|
return HealthCheckResult.Unhealthy($"SqlCheck({name}): Unhealthy");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch(Exception ex)
|
||||||
|
{
|
||||||
|
return HealthCheckResult.Unhealthy($"SqlCheck({name}): Exception during check: {ex.GetType().FullName}");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>netstandard1.3</TargetFramework>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Include="..\common\Guard.cs" Link="Internal\Guard.cs" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="System.Data.SqlClient" Version="4.3.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\Microsoft.Extensions.HealthChecks\Microsoft.Extensions.HealthChecks.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
@ -0,0 +1,13 @@
|
|||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
namespace Microsoft.Extensions.HealthChecks
|
||||||
|
{
|
||||||
|
public enum CheckStatus
|
||||||
|
{
|
||||||
|
Unknown,
|
||||||
|
Unhealthy,
|
||||||
|
Healthy,
|
||||||
|
Warning
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,110 @@
|
|||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Microsoft.Extensions.HealthChecks
|
||||||
|
{
|
||||||
|
public static partial class HealthCheckBuilderExtensions
|
||||||
|
{
|
||||||
|
// Lambda versions of AddCheck for Func/Func<Task>/Func<ValueTask>
|
||||||
|
|
||||||
|
public static HealthCheckBuilder AddCheck(this HealthCheckBuilder builder, string name, Func<IHealthCheckResult> check)
|
||||||
|
{
|
||||||
|
Guard.ArgumentNotNull(nameof(builder), builder);
|
||||||
|
|
||||||
|
builder.AddCheck(name, HealthCheck.FromCheck(check, builder.DefaultCacheDuration));
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static HealthCheckBuilder AddCheck(this HealthCheckBuilder builder, string name, Func<CancellationToken, IHealthCheckResult> check)
|
||||||
|
{
|
||||||
|
Guard.ArgumentNotNull(nameof(builder), builder);
|
||||||
|
|
||||||
|
builder.AddCheck(name, HealthCheck.FromCheck(check, builder.DefaultCacheDuration));
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static HealthCheckBuilder AddCheck(this HealthCheckBuilder builder, string name, Func<IHealthCheckResult> check, TimeSpan cacheDuration)
|
||||||
|
{
|
||||||
|
Guard.ArgumentNotNull(nameof(builder), builder);
|
||||||
|
|
||||||
|
builder.AddCheck(name, HealthCheck.FromCheck(check, cacheDuration));
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static HealthCheckBuilder AddCheck(this HealthCheckBuilder builder, string name, Func<CancellationToken, IHealthCheckResult> check, TimeSpan cacheDuration)
|
||||||
|
{
|
||||||
|
Guard.ArgumentNotNull(nameof(builder), builder);
|
||||||
|
|
||||||
|
builder.AddCheck(name, HealthCheck.FromCheck(check, cacheDuration));
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static HealthCheckBuilder AddCheck(this HealthCheckBuilder builder, string name, Func<Task<IHealthCheckResult>> check)
|
||||||
|
{
|
||||||
|
Guard.ArgumentNotNull(nameof(builder), builder);
|
||||||
|
|
||||||
|
builder.AddCheck(name, HealthCheck.FromTaskCheck(check, builder.DefaultCacheDuration));
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static HealthCheckBuilder AddCheck(this HealthCheckBuilder builder, string name, Func<CancellationToken, Task<IHealthCheckResult>> check)
|
||||||
|
{
|
||||||
|
Guard.ArgumentNotNull(nameof(builder), builder);
|
||||||
|
|
||||||
|
builder.AddCheck(name, HealthCheck.FromTaskCheck(check, builder.DefaultCacheDuration));
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static HealthCheckBuilder AddCheck(this HealthCheckBuilder builder, string name, Func<Task<IHealthCheckResult>> check, TimeSpan cacheDuration)
|
||||||
|
{
|
||||||
|
Guard.ArgumentNotNull(nameof(builder), builder);
|
||||||
|
|
||||||
|
builder.AddCheck(name, HealthCheck.FromTaskCheck(check, cacheDuration));
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static HealthCheckBuilder AddCheck(this HealthCheckBuilder builder, string name, Func<CancellationToken, Task<IHealthCheckResult>> check, TimeSpan cacheDuration)
|
||||||
|
{
|
||||||
|
Guard.ArgumentNotNull(nameof(builder), builder);
|
||||||
|
|
||||||
|
builder.AddCheck(name, HealthCheck.FromTaskCheck(check, cacheDuration));
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static HealthCheckBuilder AddValueTaskCheck(this HealthCheckBuilder builder, string name, Func<ValueTask<IHealthCheckResult>> check)
|
||||||
|
{
|
||||||
|
Guard.ArgumentNotNull(nameof(builder), builder);
|
||||||
|
|
||||||
|
builder.AddCheck(name, HealthCheck.FromValueTaskCheck(check, builder.DefaultCacheDuration));
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static HealthCheckBuilder AddValueTaskCheck(this HealthCheckBuilder builder, string name, Func<CancellationToken, ValueTask<IHealthCheckResult>> check)
|
||||||
|
{
|
||||||
|
Guard.ArgumentNotNull(nameof(builder), builder);
|
||||||
|
|
||||||
|
builder.AddCheck(name, HealthCheck.FromValueTaskCheck(check, builder.DefaultCacheDuration));
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static HealthCheckBuilder AddValueTaskCheck(this HealthCheckBuilder builder, string name, Func<ValueTask<IHealthCheckResult>> check, TimeSpan cacheDuration)
|
||||||
|
{
|
||||||
|
Guard.ArgumentNotNull(nameof(builder), builder);
|
||||||
|
|
||||||
|
builder.AddCheck(name, HealthCheck.FromValueTaskCheck(check, cacheDuration));
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static HealthCheckBuilder AddValueTaskCheck(this HealthCheckBuilder builder, string name, Func<CancellationToken, ValueTask<IHealthCheckResult>> check, TimeSpan cacheDuration)
|
||||||
|
{
|
||||||
|
Guard.ArgumentNotNull(nameof(builder), builder);
|
||||||
|
|
||||||
|
builder.AddCheck(name, HealthCheck.FromValueTaskCheck(check, cacheDuration));
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,55 @@
|
|||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Microsoft.Extensions.HealthChecks
|
||||||
|
{
|
||||||
|
public static partial class HealthCheckBuilderExtensions
|
||||||
|
{
|
||||||
|
// Numeric checks
|
||||||
|
|
||||||
|
public static HealthCheckBuilder AddMinValueCheck<T>(this HealthCheckBuilder builder, string name, T minValue, Func<T> currentValueFunc)
|
||||||
|
where T : IComparable<T>
|
||||||
|
{
|
||||||
|
Guard.ArgumentNotNull(nameof(builder), builder);
|
||||||
|
Guard.ArgumentNotNullOrWhitespace(nameof(name), name);
|
||||||
|
Guard.ArgumentNotNull(nameof(currentValueFunc), currentValueFunc);
|
||||||
|
|
||||||
|
builder.AddCheck(name, () =>
|
||||||
|
{
|
||||||
|
var currentValue = currentValueFunc();
|
||||||
|
var status = currentValue.CompareTo(minValue) >= 0 ? CheckStatus.Healthy : CheckStatus.Unhealthy;
|
||||||
|
return HealthCheckResult.FromStatus(
|
||||||
|
status,
|
||||||
|
$"{name}: min={minValue}, current={currentValue}",
|
||||||
|
new Dictionary<string, object> { { "min", minValue }, { "current", currentValue } }
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static HealthCheckBuilder AddMaxValueCheck<T>(this HealthCheckBuilder builder, string name, T maxValue, Func<T> currentValueFunc)
|
||||||
|
where T : IComparable<T>
|
||||||
|
{
|
||||||
|
Guard.ArgumentNotNull(nameof(builder), builder);
|
||||||
|
Guard.ArgumentNotNullOrWhitespace(nameof(name), name);
|
||||||
|
Guard.ArgumentNotNull(nameof(currentValueFunc), currentValueFunc);
|
||||||
|
|
||||||
|
builder.AddCheck($"{name}", () =>
|
||||||
|
{
|
||||||
|
var currentValue = currentValueFunc();
|
||||||
|
var status = currentValue.CompareTo(maxValue) <= 0 ? CheckStatus.Healthy : CheckStatus.Unhealthy;
|
||||||
|
return HealthCheckResult.FromStatus(
|
||||||
|
status,
|
||||||
|
$"{name}: max={maxValue}, current={currentValue}",
|
||||||
|
new Dictionary<string, object> { { "max", maxValue }, { "current", currentValue } }
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System.Diagnostics;
|
||||||
|
|
||||||
|
namespace Microsoft.Extensions.HealthChecks
|
||||||
|
{
|
||||||
|
public static partial class HealthCheckBuilderExtensions
|
||||||
|
{
|
||||||
|
// System checks
|
||||||
|
|
||||||
|
public static HealthCheckBuilder AddPrivateMemorySizeCheck(this HealthCheckBuilder builder, long maxSize)
|
||||||
|
=> AddMaxValueCheck(builder, $"PrivateMemorySize({maxSize})", maxSize, () => Process.GetCurrentProcess().PrivateMemorySize64);
|
||||||
|
|
||||||
|
public static HealthCheckBuilder AddVirtualMemorySizeCheck(this HealthCheckBuilder builder, long maxSize)
|
||||||
|
=> AddMaxValueCheck(builder, $"VirtualMemorySize({maxSize})", maxSize, () => Process.GetCurrentProcess().VirtualMemorySize64);
|
||||||
|
|
||||||
|
public static HealthCheckBuilder AddWorkingSetCheck(this HealthCheckBuilder builder, long maxSize)
|
||||||
|
=> AddMaxValueCheck(builder, $"WorkingSet({maxSize})", maxSize, () => Process.GetCurrentProcess().WorkingSet64);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,109 @@
|
|||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.Extensions.HealthChecks.Internal;
|
||||||
|
|
||||||
|
namespace Microsoft.Extensions.HealthChecks
|
||||||
|
{
|
||||||
|
public static partial class HealthCheckBuilderExtensions
|
||||||
|
{
|
||||||
|
// URL checks
|
||||||
|
|
||||||
|
public static HealthCheckBuilder AddUrlCheck(this HealthCheckBuilder builder, string url)
|
||||||
|
=> AddUrlCheck(builder, url, response => UrlChecker.DefaultUrlCheck(response));
|
||||||
|
|
||||||
|
public static HealthCheckBuilder AddUrlCheck(this HealthCheckBuilder builder, string url,
|
||||||
|
Func<HttpResponseMessage, IHealthCheckResult> checkFunc)
|
||||||
|
{
|
||||||
|
Guard.ArgumentNotNull(nameof(checkFunc), checkFunc);
|
||||||
|
|
||||||
|
return AddUrlCheck(builder, url, response => new ValueTask<IHealthCheckResult>(checkFunc(response)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static HealthCheckBuilder AddUrlCheck(this HealthCheckBuilder builder, string url,
|
||||||
|
Func<HttpResponseMessage, Task<IHealthCheckResult>> checkFunc)
|
||||||
|
{
|
||||||
|
Guard.ArgumentNotNull(nameof(checkFunc), checkFunc);
|
||||||
|
|
||||||
|
return AddUrlCheck(builder, url, response => new ValueTask<IHealthCheckResult>(checkFunc(response)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static HealthCheckBuilder AddUrlCheck(this HealthCheckBuilder builder, string url,
|
||||||
|
Func<HttpResponseMessage, ValueTask<IHealthCheckResult>> checkFunc)
|
||||||
|
{
|
||||||
|
Guard.ArgumentNotNull(nameof(builder), builder);
|
||||||
|
Guard.ArgumentNotNullOrWhitespace(nameof(url), url);
|
||||||
|
Guard.ArgumentNotNull(nameof(checkFunc), checkFunc);
|
||||||
|
|
||||||
|
var urlCheck = new UrlChecker(checkFunc, url);
|
||||||
|
builder.AddCheck($"UrlCheck({url})", () => urlCheck.CheckAsync());
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static HealthCheckBuilder AddUrlChecks(this HealthCheckBuilder builder, IEnumerable<string> urlItems, string groupName)
|
||||||
|
=> AddUrlChecks(builder, urlItems, groupName, CheckStatus.Warning, response => UrlChecker.DefaultUrlCheck(response));
|
||||||
|
|
||||||
|
public static HealthCheckBuilder AddUrlChecks(this HealthCheckBuilder builder, IEnumerable<string> urlItems, string groupName,
|
||||||
|
Func<HttpResponseMessage, IHealthCheckResult> checkFunc)
|
||||||
|
{
|
||||||
|
Guard.ArgumentNotNull(nameof(checkFunc), checkFunc);
|
||||||
|
|
||||||
|
return AddUrlChecks(builder, urlItems, groupName, CheckStatus.Warning, response => new ValueTask<IHealthCheckResult>(checkFunc(response)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static HealthCheckBuilder AddUrlChecks(this HealthCheckBuilder builder, IEnumerable<string> urlItems, string groupName,
|
||||||
|
Func<HttpResponseMessage, Task<IHealthCheckResult>> checkFunc)
|
||||||
|
{
|
||||||
|
Guard.ArgumentNotNull(nameof(checkFunc), checkFunc);
|
||||||
|
|
||||||
|
return AddUrlChecks(builder, urlItems, groupName, CheckStatus.Warning, response => new ValueTask<IHealthCheckResult>(checkFunc(response)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static HealthCheckBuilder AddUrlChecks(this HealthCheckBuilder builder, IEnumerable<string> urlItems, string groupName,
|
||||||
|
Func<HttpResponseMessage, ValueTask<IHealthCheckResult>> checkFunc)
|
||||||
|
{
|
||||||
|
Guard.ArgumentNotNull(nameof(checkFunc), checkFunc);
|
||||||
|
|
||||||
|
return AddUrlChecks(builder, urlItems, groupName, CheckStatus.Warning, response => checkFunc(response));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static HealthCheckBuilder AddUrlChecks(this HealthCheckBuilder builder, IEnumerable<string> urlItems, string groupName,
|
||||||
|
CheckStatus partialSuccessStatus)
|
||||||
|
=> AddUrlChecks(builder, urlItems, groupName, partialSuccessStatus, response => UrlChecker.DefaultUrlCheck(response));
|
||||||
|
|
||||||
|
public static HealthCheckBuilder AddUrlChecks(this HealthCheckBuilder builder, IEnumerable<string> urlItems, string groupName,
|
||||||
|
CheckStatus partialSuccessStatus, Func<HttpResponseMessage, IHealthCheckResult> checkFunc)
|
||||||
|
{
|
||||||
|
Guard.ArgumentNotNull(nameof(checkFunc), checkFunc);
|
||||||
|
|
||||||
|
return AddUrlChecks(builder, urlItems, groupName, partialSuccessStatus, response => new ValueTask<IHealthCheckResult>(checkFunc(response)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static HealthCheckBuilder AddUrlChecks(this HealthCheckBuilder builder, IEnumerable<string> urlItems, string groupName,
|
||||||
|
CheckStatus partialSuccessStatus, Func<HttpResponseMessage, Task<IHealthCheckResult>> checkFunc)
|
||||||
|
{
|
||||||
|
Guard.ArgumentNotNull(nameof(checkFunc), checkFunc);
|
||||||
|
|
||||||
|
return AddUrlChecks(builder, urlItems, groupName, partialSuccessStatus, response => new ValueTask<IHealthCheckResult>(checkFunc(response)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static HealthCheckBuilder AddUrlChecks(this HealthCheckBuilder builder, IEnumerable<string> urlItems, string groupName,
|
||||||
|
CheckStatus partialSuccessStatus, Func<HttpResponseMessage, ValueTask<IHealthCheckResult>> checkFunc)
|
||||||
|
{
|
||||||
|
var urls = urlItems?.ToArray();
|
||||||
|
|
||||||
|
Guard.ArgumentNotNull(nameof(builder), builder);
|
||||||
|
Guard.ArgumentNotNullOrEmpty(nameof(urlItems), urls);
|
||||||
|
Guard.ArgumentNotNullOrWhitespace(nameof(groupName), groupName);
|
||||||
|
|
||||||
|
var urlChecker = new UrlChecker(checkFunc, urls) { PartiallyHealthyStatus = partialSuccessStatus };
|
||||||
|
builder.AddCheck($"UrlChecks({groupName})", () => urlChecker.CheckAsync());
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,83 @@
|
|||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace Microsoft.Extensions.HealthChecks
|
||||||
|
{
|
||||||
|
// REVIEW: Does this need to be thread safe?
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a composite health check result built from several results.
|
||||||
|
/// </summary>
|
||||||
|
public class CompositeHealthCheckResult : IHealthCheckResult
|
||||||
|
{
|
||||||
|
private static readonly IReadOnlyDictionary<string, object> _emptyData = new Dictionary<string, object>();
|
||||||
|
private readonly CheckStatus _initialStatus;
|
||||||
|
private readonly CheckStatus _partiallyHealthyStatus;
|
||||||
|
private readonly Dictionary<string, IHealthCheckResult> _results = new Dictionary<string, IHealthCheckResult>(StringComparer.OrdinalIgnoreCase);
|
||||||
|
|
||||||
|
public CompositeHealthCheckResult(CheckStatus partiallyHealthyStatus = CheckStatus.Warning,
|
||||||
|
CheckStatus initialStatus = CheckStatus.Unknown)
|
||||||
|
{
|
||||||
|
_partiallyHealthyStatus = partiallyHealthyStatus;
|
||||||
|
_initialStatus = initialStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CheckStatus CheckStatus
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var checkStatuses = new HashSet<CheckStatus>(_results.Select(x => x.Value.CheckStatus));
|
||||||
|
if (checkStatuses.Count == 0)
|
||||||
|
return _initialStatus;
|
||||||
|
if (checkStatuses.Count == 1)
|
||||||
|
return checkStatuses.First();
|
||||||
|
if (checkStatuses.Contains(CheckStatus.Healthy))
|
||||||
|
return _partiallyHealthyStatus;
|
||||||
|
|
||||||
|
return CheckStatus.Unhealthy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Description => string.Join(Environment.NewLine, _results.Select(r => r.Value.Description));
|
||||||
|
|
||||||
|
public IReadOnlyDictionary<string, object> Data
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var result = new Dictionary<string, object>();
|
||||||
|
|
||||||
|
foreach (var kvp in _results)
|
||||||
|
result.Add(kvp.Key, kvp.Value.Data);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public IReadOnlyDictionary<string, IHealthCheckResult> Results => _results;
|
||||||
|
|
||||||
|
// REVIEW: Should description be required? Seems redundant for success checks.
|
||||||
|
|
||||||
|
public void Add(string name, CheckStatus status, string description)
|
||||||
|
=> Add(name, status, description, null);
|
||||||
|
|
||||||
|
public void Add(string name, CheckStatus status, string description, Dictionary<string, object> data)
|
||||||
|
{
|
||||||
|
Guard.ArgumentNotNullOrWhitespace(nameof(name), name);
|
||||||
|
Guard.ArgumentValid(status != CheckStatus.Unknown, nameof(status), "Cannot add unknown status to composite health check result");
|
||||||
|
Guard.ArgumentNotNullOrWhitespace(nameof(description), description);
|
||||||
|
|
||||||
|
_results.Add(name, HealthCheckResult.FromStatus(status, description, data));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Add(string name, IHealthCheckResult checkResult)
|
||||||
|
{
|
||||||
|
Guard.ArgumentNotNullOrWhitespace(nameof(name), name);
|
||||||
|
Guard.ArgumentNotNull(nameof(checkResult), checkResult);
|
||||||
|
|
||||||
|
_results.Add(name, checkResult);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,76 @@
|
|||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Microsoft.Extensions.HealthChecks
|
||||||
|
{
|
||||||
|
public class HealthCheck : IHealthCheck
|
||||||
|
{
|
||||||
|
private DateTimeOffset _cacheExpiration;
|
||||||
|
private IHealthCheckResult _cachedResult;
|
||||||
|
private volatile int _writerCount;
|
||||||
|
|
||||||
|
protected HealthCheck(Func<CancellationToken, ValueTask<IHealthCheckResult>> check, TimeSpan cacheDuration)
|
||||||
|
{
|
||||||
|
Guard.ArgumentNotNull(nameof(check), check);
|
||||||
|
Guard.ArgumentValid(cacheDuration >= TimeSpan.Zero, nameof(cacheDuration), "Cache duration must either be zero (disabled) or a positive value");
|
||||||
|
|
||||||
|
Check = check;
|
||||||
|
CacheDuration = cacheDuration;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TimeSpan CacheDuration { get; }
|
||||||
|
|
||||||
|
protected Func<CancellationToken, ValueTask<IHealthCheckResult>> Check { get; }
|
||||||
|
|
||||||
|
protected virtual DateTimeOffset UtcNow => DateTimeOffset.UtcNow;
|
||||||
|
|
||||||
|
public async ValueTask<IHealthCheckResult> CheckAsync(CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
while (_cacheExpiration <= UtcNow)
|
||||||
|
{
|
||||||
|
// Can't use a standard lock here because of async, so we'll use this flag to determine when we should write a value,
|
||||||
|
// and the waiters who aren't allowed to write will just spin wait for the new value.
|
||||||
|
if (Interlocked.Exchange(ref _writerCount, 1) != 0)
|
||||||
|
{
|
||||||
|
await Task.Delay(5, cancellationToken).ConfigureAwait(false);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_cachedResult = await Check(cancellationToken).ConfigureAwait(false);
|
||||||
|
_cacheExpiration = UtcNow + CacheDuration;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_writerCount = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return _cachedResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static HealthCheck FromCheck(Func<IHealthCheckResult> check, TimeSpan cacheDuration)
|
||||||
|
=> new HealthCheck(token => new ValueTask<IHealthCheckResult>(check()), cacheDuration);
|
||||||
|
|
||||||
|
public static HealthCheck FromCheck(Func<CancellationToken, IHealthCheckResult> check, TimeSpan cacheDuration)
|
||||||
|
=> new HealthCheck(token => new ValueTask<IHealthCheckResult>(check(token)), cacheDuration);
|
||||||
|
|
||||||
|
public static HealthCheck FromTaskCheck(Func<Task<IHealthCheckResult>> check, TimeSpan cacheDuration)
|
||||||
|
=> new HealthCheck(token => new ValueTask<IHealthCheckResult>(check()), cacheDuration);
|
||||||
|
|
||||||
|
public static HealthCheck FromTaskCheck(Func<CancellationToken, Task<IHealthCheckResult>> check, TimeSpan cacheDuration)
|
||||||
|
=> new HealthCheck(token => new ValueTask<IHealthCheckResult>(check(token)), cacheDuration);
|
||||||
|
|
||||||
|
public static HealthCheck FromValueTaskCheck(Func<ValueTask<IHealthCheckResult>> check, TimeSpan cacheDuration)
|
||||||
|
=> new HealthCheck(token => check(), cacheDuration);
|
||||||
|
|
||||||
|
public static HealthCheck FromValueTaskCheck(Func<CancellationToken, ValueTask<IHealthCheckResult>> check, TimeSpan cacheDuration)
|
||||||
|
=> new HealthCheck(check, cacheDuration);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,40 @@
|
|||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Microsoft.Extensions.HealthChecks
|
||||||
|
{
|
||||||
|
public class HealthCheckBuilder
|
||||||
|
{
|
||||||
|
private readonly Dictionary<string, IHealthCheck> _checks;
|
||||||
|
|
||||||
|
public HealthCheckBuilder()
|
||||||
|
{
|
||||||
|
_checks = new Dictionary<string, IHealthCheck>(StringComparer.OrdinalIgnoreCase);
|
||||||
|
DefaultCacheDuration = TimeSpan.FromMinutes(5);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IReadOnlyDictionary<string, IHealthCheck> Checks => _checks;
|
||||||
|
|
||||||
|
public TimeSpan DefaultCacheDuration { get; private set; }
|
||||||
|
|
||||||
|
public HealthCheckBuilder AddCheck(string name, IHealthCheck check)
|
||||||
|
{
|
||||||
|
Guard.ArgumentNotNullOrWhitespace(nameof(name), name);
|
||||||
|
Guard.ArgumentNotNull(nameof(check), check);
|
||||||
|
|
||||||
|
_checks.Add(name, check);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public HealthCheckBuilder WithDefaultCacheDuration(TimeSpan duration)
|
||||||
|
{
|
||||||
|
Guard.ArgumentValid(duration >= TimeSpan.Zero, nameof(duration), "Duration must be zero (disabled) or a positive duration");
|
||||||
|
|
||||||
|
DefaultCacheDuration = duration;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Microsoft.Extensions.HealthChecks
|
||||||
|
{
|
||||||
|
public static class HealthCheckExtensions
|
||||||
|
{
|
||||||
|
public static ValueTask<IHealthCheckResult> CheckAsync(this IHealthCheck healthCheck)
|
||||||
|
{
|
||||||
|
Guard.ArgumentNotNull(nameof(healthCheck), healthCheck);
|
||||||
|
|
||||||
|
return healthCheck.CheckAsync(CancellationToken.None);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,54 @@
|
|||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace Microsoft.Extensions.HealthChecks
|
||||||
|
{
|
||||||
|
public class HealthCheckResult : IHealthCheckResult
|
||||||
|
{
|
||||||
|
private static readonly IReadOnlyDictionary<string, object> _emptyData = new Dictionary<string, object>();
|
||||||
|
|
||||||
|
public CheckStatus CheckStatus { get; }
|
||||||
|
public IReadOnlyDictionary<string, object> Data { get; }
|
||||||
|
public string Description { get; }
|
||||||
|
|
||||||
|
private HealthCheckResult(CheckStatus checkStatus, string description, IReadOnlyDictionary<string, object> data)
|
||||||
|
{
|
||||||
|
CheckStatus = checkStatus;
|
||||||
|
Description = description;
|
||||||
|
Data = data ?? _emptyData;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static HealthCheckResult Unhealthy(string description)
|
||||||
|
=> new HealthCheckResult(CheckStatus.Unhealthy, description, null);
|
||||||
|
|
||||||
|
public static HealthCheckResult Unhealthy(string description, IReadOnlyDictionary<string, object> data)
|
||||||
|
=> new HealthCheckResult(CheckStatus.Unhealthy, description, data);
|
||||||
|
|
||||||
|
public static HealthCheckResult Healthy(string description)
|
||||||
|
=> new HealthCheckResult(CheckStatus.Healthy, description, null);
|
||||||
|
|
||||||
|
public static HealthCheckResult Healthy(string description, IReadOnlyDictionary<string, object> data)
|
||||||
|
=> new HealthCheckResult(CheckStatus.Healthy, description, data);
|
||||||
|
|
||||||
|
public static HealthCheckResult Warning(string description)
|
||||||
|
=> new HealthCheckResult(CheckStatus.Warning, description, null);
|
||||||
|
|
||||||
|
public static HealthCheckResult Warning(string description, IReadOnlyDictionary<string, object> data)
|
||||||
|
=> new HealthCheckResult(CheckStatus.Warning, description, data);
|
||||||
|
|
||||||
|
public static HealthCheckResult Unknown(string description)
|
||||||
|
=> new HealthCheckResult(CheckStatus.Unknown, description, null);
|
||||||
|
|
||||||
|
public static HealthCheckResult Unknown(string description, IReadOnlyDictionary<string, object> data)
|
||||||
|
=> new HealthCheckResult(CheckStatus.Unknown, description, data);
|
||||||
|
|
||||||
|
public static HealthCheckResult FromStatus(CheckStatus status, string description)
|
||||||
|
=> new HealthCheckResult(status, description, null);
|
||||||
|
|
||||||
|
public static HealthCheckResult FromStatus(CheckStatus status, string description, IReadOnlyDictionary<string, object> data)
|
||||||
|
=> new HealthCheckResult(status, description, data);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Microsoft.Extensions.HealthChecks
|
||||||
|
{
|
||||||
|
public class HealthCheckResults
|
||||||
|
{
|
||||||
|
public IList<IHealthCheckResult> CheckResults { get; } = new List<IHealthCheckResult>();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,54 @@
|
|||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
|
namespace Microsoft.Extensions.HealthChecks
|
||||||
|
{
|
||||||
|
public class HealthCheckService : IHealthCheckService
|
||||||
|
{
|
||||||
|
public IReadOnlyDictionary<string, IHealthCheck> _checks;
|
||||||
|
|
||||||
|
private ILogger<HealthCheckService> _logger;
|
||||||
|
|
||||||
|
public HealthCheckService(HealthCheckBuilder builder, ILogger<HealthCheckService> logger)
|
||||||
|
{
|
||||||
|
_checks = builder.Checks;
|
||||||
|
_logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<CompositeHealthCheckResult> CheckHealthAsync(CheckStatus partiallyHealthyStatus, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var logMessage = new StringBuilder();
|
||||||
|
var result = new CompositeHealthCheckResult(partiallyHealthyStatus);
|
||||||
|
|
||||||
|
foreach (var check in _checks)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var healthCheckResult = await check.Value.CheckAsync().ConfigureAwait(false);
|
||||||
|
logMessage.AppendLine($"HealthCheck: {check.Key} : {healthCheckResult.CheckStatus}");
|
||||||
|
result.Add(check.Key, healthCheckResult);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
logMessage.AppendLine($"HealthCheck: {check.Key} : Exception {ex.GetType().FullName} thrown");
|
||||||
|
result.Add(check.Key, CheckStatus.Unhealthy, $"Exception during check: {ex.GetType().FullName}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (logMessage.Length == 0)
|
||||||
|
logMessage.AppendLine("HealthCheck: No checks have been registered");
|
||||||
|
|
||||||
|
_logger.Log((result.CheckStatus == CheckStatus.Healthy ? LogLevel.Information : LogLevel.Error), 0, logMessage.ToString(), null, MessageFormatter);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string MessageFormatter(string state, Exception error) => state;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,22 @@
|
|||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using Microsoft.Extensions.HealthChecks;
|
||||||
|
|
||||||
|
namespace Microsoft.Extensions.DependencyInjection
|
||||||
|
{
|
||||||
|
public static class HealthCheckServiceCollectionExtensions
|
||||||
|
{
|
||||||
|
public static IServiceCollection AddHealthChecks(this IServiceCollection services, Action<HealthCheckBuilder> checkupAction)
|
||||||
|
{
|
||||||
|
var checkupBuilder = new HealthCheckBuilder();
|
||||||
|
|
||||||
|
checkupAction.Invoke(checkupBuilder);
|
||||||
|
|
||||||
|
services.AddSingleton(checkupBuilder);
|
||||||
|
services.AddSingleton<IHealthCheckService, HealthCheckService>();
|
||||||
|
return services;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,38 @@
|
|||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Microsoft.Extensions.HealthChecks
|
||||||
|
{
|
||||||
|
public static class HealthCheckServiceExtensions
|
||||||
|
{
|
||||||
|
public static Task<CompositeHealthCheckResult> CheckHealthAsync(this IHealthCheckService service)
|
||||||
|
{
|
||||||
|
Guard.ArgumentNotNull(nameof(service), service);
|
||||||
|
|
||||||
|
return service.CheckHealthAsync(CheckStatus.Unhealthy, CancellationToken.None);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Task<CompositeHealthCheckResult> CheckHealthAsync(this IHealthCheckService service, CheckStatus partiallyHealthyStatus)
|
||||||
|
{
|
||||||
|
Guard.ArgumentNotNull(nameof(service), service);
|
||||||
|
|
||||||
|
return service.CheckHealthAsync(partiallyHealthyStatus, CancellationToken.None);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Task<CompositeHealthCheckResult> CheckHealthAsync(this IHealthCheckService service, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
Guard.ArgumentNotNull(nameof(service), service);
|
||||||
|
|
||||||
|
return service.CheckHealthAsync(CheckStatus.Unhealthy, cancellationToken);
|
||||||
|
}
|
||||||
|
public static Task<CompositeHealthCheckResult> CheckHealthAsync(this IHealthCheckService service, CheckStatus partiallyHealthyStatus, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
Guard.ArgumentNotNull(nameof(service), service);
|
||||||
|
|
||||||
|
return service.CheckHealthAsync(partiallyHealthyStatus, cancellationToken);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,16 @@
|
|||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Microsoft.Extensions.HealthChecks
|
||||||
|
{
|
||||||
|
public interface IHealthCheck
|
||||||
|
{
|
||||||
|
TimeSpan CacheDuration { get; }
|
||||||
|
|
||||||
|
ValueTask<IHealthCheckResult> CheckAsync(CancellationToken cancellationToken);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,14 @@
|
|||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Microsoft.Extensions.HealthChecks
|
||||||
|
{
|
||||||
|
public interface IHealthCheckResult
|
||||||
|
{
|
||||||
|
CheckStatus CheckStatus { get; }
|
||||||
|
string Description { get; }
|
||||||
|
IReadOnlyDictionary<string, object> Data { get; }
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Microsoft.Extensions.HealthChecks
|
||||||
|
{
|
||||||
|
public interface IHealthCheckService
|
||||||
|
{
|
||||||
|
Task<CompositeHealthCheckResult> CheckHealthAsync(CheckStatus partiallyHealthyStatus, CancellationToken cancellationToken);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,92 @@
|
|||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Net;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Net.Http.Headers;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Microsoft.Extensions.HealthChecks.Internal
|
||||||
|
{
|
||||||
|
public class UrlChecker
|
||||||
|
{
|
||||||
|
private readonly Func<HttpResponseMessage, ValueTask<IHealthCheckResult>> _checkFunc;
|
||||||
|
private readonly string[] _urls;
|
||||||
|
|
||||||
|
// REVIEW: Cache timeout here?
|
||||||
|
public UrlChecker(Func<HttpResponseMessage, ValueTask<IHealthCheckResult>> checkFunc, params string[] urls)
|
||||||
|
{
|
||||||
|
Guard.ArgumentNotNull(nameof(checkFunc), checkFunc);
|
||||||
|
Guard.ArgumentNotNullOrEmpty(nameof(urls), urls);
|
||||||
|
|
||||||
|
_checkFunc = checkFunc;
|
||||||
|
_urls = urls;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CheckStatus PartiallyHealthyStatus { get; set; } = CheckStatus.Warning;
|
||||||
|
|
||||||
|
public Task<IHealthCheckResult> CheckAsync()
|
||||||
|
=> _urls.Length == 1 ? CheckSingleAsync() : CheckMultiAsync();
|
||||||
|
|
||||||
|
public async Task<IHealthCheckResult> CheckSingleAsync()
|
||||||
|
{
|
||||||
|
var httpClient = CreateHttpClient();
|
||||||
|
var result = default(IHealthCheckResult);
|
||||||
|
await CheckUrlAsync(httpClient, _urls[0], (_, checkResult) => result = checkResult).ConfigureAwait(false);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<IHealthCheckResult> CheckMultiAsync()
|
||||||
|
{
|
||||||
|
var composite = new CompositeHealthCheckResult(PartiallyHealthyStatus);
|
||||||
|
var httpClient = CreateHttpClient();
|
||||||
|
|
||||||
|
// REVIEW: Should these be done in parallel?
|
||||||
|
foreach (var url in _urls)
|
||||||
|
await CheckUrlAsync(httpClient, url, (name, checkResult) => composite.Add(name, checkResult)).ConfigureAwait(false);
|
||||||
|
|
||||||
|
return composite;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task CheckUrlAsync(HttpClient httpClient, string url, Action<string, IHealthCheckResult> adder)
|
||||||
|
{
|
||||||
|
var name = $"UrlCheck({url})";
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var response = await httpClient.GetAsync(url).ConfigureAwait(false);
|
||||||
|
var result = await _checkFunc(response);
|
||||||
|
adder(name, result);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
adder(name, HealthCheckResult.Unhealthy($"Exception during check: {ex.GetType().FullName}"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private HttpClient CreateHttpClient()
|
||||||
|
{
|
||||||
|
var httpClient = GetHttpClient();
|
||||||
|
httpClient.DefaultRequestHeaders.CacheControl = new CacheControlHeaderValue { NoCache = true };
|
||||||
|
return httpClient;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async ValueTask<IHealthCheckResult> DefaultUrlCheck(HttpResponseMessage response)
|
||||||
|
{
|
||||||
|
// REVIEW: Should this be an explicit 200 check, or just an "is success" check?
|
||||||
|
var status = response.StatusCode == HttpStatusCode.OK ? CheckStatus.Healthy : CheckStatus.Unhealthy;
|
||||||
|
var data = new Dictionary<string, object>
|
||||||
|
{
|
||||||
|
{ "url", response.RequestMessage.RequestUri.ToString() },
|
||||||
|
{ "status", (int)response.StatusCode },
|
||||||
|
{ "reason", response.ReasonPhrase },
|
||||||
|
{ "body", await response.Content?.ReadAsStringAsync() }
|
||||||
|
};
|
||||||
|
return HealthCheckResult.FromStatus(status, $"UrlCheck({response.RequestMessage.RequestUri}): status code {response.StatusCode} ({(int)response.StatusCode})", data);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual HttpClient GetHttpClient()
|
||||||
|
=> new HttpClient();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,20 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>netstandard1.3</TargetFramework>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Include="..\common\Guard.cs" Link="Internal\Guard.cs" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Logging" Version="1.0.2" />
|
||||||
|
<PackageReference Include="Newtonsoft.Json" Version="9.0.1" />
|
||||||
|
<PackageReference Include="System.Diagnostics.Process" Version="4.3.0" />
|
||||||
|
<PackageReference Include="System.Threading.Tasks.Parallel" Version="4.3.0" />
|
||||||
|
<PackageReference Include="System.Threading.Thread" Version="4.3.0" />
|
||||||
|
<PackageReference Include="System.Threading.Tasks.Extensions" Version="4.3.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
45
src/BuildingBlocks/HealthChecks/src/common/Guard.cs
Normal file
45
src/BuildingBlocks/HealthChecks/src/common/Guard.cs
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
static class Guard
|
||||||
|
{
|
||||||
|
public static void ArgumentNotNull(string argumentName, object value)
|
||||||
|
{
|
||||||
|
if (value == null)
|
||||||
|
throw new ArgumentNullException(argumentName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void ArgumentNotNullOrEmpty<T>(string argumentName, string value)
|
||||||
|
{
|
||||||
|
if (value == null)
|
||||||
|
throw new ArgumentNullException(argumentName);
|
||||||
|
if (string.IsNullOrEmpty(value))
|
||||||
|
throw new ArgumentException("Value cannot be an empty string", argumentName);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use IReadOnlyCollection<T> instead of IEnumerable<T> to discourage double enumeration
|
||||||
|
public static void ArgumentNotNullOrEmpty<T>(string argumentName, IReadOnlyCollection<T> items)
|
||||||
|
{
|
||||||
|
if (items == null)
|
||||||
|
throw new ArgumentNullException(argumentName);
|
||||||
|
if (items.Count == 0)
|
||||||
|
throw new ArgumentException("Collection must contain at least one item", argumentName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void ArgumentNotNullOrWhitespace(string argumentName, string value)
|
||||||
|
{
|
||||||
|
if (value == null)
|
||||||
|
throw new ArgumentNullException(argumentName);
|
||||||
|
if (string.IsNullOrWhiteSpace(value))
|
||||||
|
throw new ArgumentException("Value must contain a non-whitespace value", argumentName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void ArgumentValid(bool valid, string argumentName, string exceptionMessage)
|
||||||
|
{
|
||||||
|
if (!valid)
|
||||||
|
throw new ArgumentException(exceptionMessage, argumentName);
|
||||||
|
}
|
||||||
|
}
|
@ -23,22 +23,30 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="System.Threading" Version="4.3.0" />
|
<PackageReference Include="System.Threading" Version="4.3.0" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="1.1.0" />
|
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="1.1.2" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Server.IISIntegration" Version="1.1.0" />
|
<PackageReference Include="Microsoft.AspNetCore.Server.IISIntegration" Version="1.1.1" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="1.1.0" />
|
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="1.1.1" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="1.1.0" />
|
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="1.1.1" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="1.1.0" />
|
<PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="1.1.1" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="1.1.0" />
|
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="1.1.1" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="1.1.0" />
|
<PackageReference Include="Microsoft.Extensions.Logging" Version="1.1.1" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="1.1.0" />
|
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="1.1.1" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="1.1.0" />
|
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="1.1.1" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="1.1.0" />
|
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="1.1.1" />
|
||||||
<PackageReference Include="StackExchange.Redis" Version="1.1.608" />
|
<PackageReference Include="StackExchange.Redis" Version="1.1.608" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="9.0.1" />
|
<PackageReference Include="Newtonsoft.Json" Version="9.0.1" />
|
||||||
<PackageReference Include="IdentityServer4.AccessTokenValidation" Version="1.0.1-rc3" />
|
<PackageReference Include="IdentityServer4.AccessTokenValidation" Version="1.0.1-rc3" />
|
||||||
<PackageReference Include="Swashbuckle" Version="6.0.0-beta902" />
|
<PackageReference Include="Swashbuckle" Version="6.0.0-beta902" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\..\BuildingBlocks\EventBus\EventBusRabbitMQ\EventBusRabbitMQ.csproj" />
|
||||||
|
<ProjectReference Include="..\..\..\BuildingBlocks\EventBus\EventBus\EventBus.csproj" />
|
||||||
|
<ProjectReference Include="..\..\..\BuildingBlocks\HealthChecks\src\Microsoft.AspNetCore.HealthChecks\Microsoft.AspNetCore.HealthChecks.csproj" />
|
||||||
|
<ProjectReference Include="..\..\..\BuildingBlocks\HealthChecks\src\Microsoft.Extensions.HealthChecks.Data\Microsoft.Extensions.HealthChecks.Data.csproj" />
|
||||||
|
<ProjectReference Include="..\..\..\BuildingBlocks\HealthChecks\src\Microsoft.Extensions.HealthChecks\Microsoft.Extensions.HealthChecks.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Update="Dockerfile">
|
<None Update="Dockerfile">
|
||||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
@ -8,5 +8,7 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API
|
|||||||
public class BasketSettings
|
public class BasketSettings
|
||||||
{
|
{
|
||||||
public string ConnectionString { get; set; }
|
public string ConnectionString { get; set; }
|
||||||
|
|
||||||
|
public string EventBusConnection { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
8
src/Services/Basket/Basket.API/Dockerfile.nanowin
Normal file
8
src/Services/Basket/Basket.API/Dockerfile.nanowin
Normal 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"]
|
@ -0,0 +1,18 @@
|
|||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Basket.API.Infrastructure.ActionResults
|
||||||
|
{
|
||||||
|
public class InternalServerErrorObjectResult : ObjectResult
|
||||||
|
{
|
||||||
|
public InternalServerErrorObjectResult(object error)
|
||||||
|
: base(error)
|
||||||
|
{
|
||||||
|
StatusCode = StatusCodes.Status500InternalServerError;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,24 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Basket.API.Infrastructure.Exceptions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Exception type for app exceptions
|
||||||
|
/// </summary>
|
||||||
|
public class BasketDomainException : Exception
|
||||||
|
{
|
||||||
|
public BasketDomainException()
|
||||||
|
{ }
|
||||||
|
|
||||||
|
public BasketDomainException(string message)
|
||||||
|
: base(message)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
public BasketDomainException(string message, Exception innerException)
|
||||||
|
: base(message, innerException)
|
||||||
|
{ }
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,67 @@
|
|||||||
|
using Basket.API.Infrastructure.ActionResults;
|
||||||
|
using Basket.API.Infrastructure.Exceptions;
|
||||||
|
using Microsoft.AspNetCore.Hosting;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.AspNetCore.Mvc.Filters;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Basket.API.Infrastructure.Filters
|
||||||
|
{
|
||||||
|
public class HttpGlobalExceptionFilter : IExceptionFilter
|
||||||
|
{
|
||||||
|
private readonly IHostingEnvironment env;
|
||||||
|
private readonly ILogger<HttpGlobalExceptionFilter> logger;
|
||||||
|
|
||||||
|
public HttpGlobalExceptionFilter(IHostingEnvironment env, ILogger<HttpGlobalExceptionFilter> logger)
|
||||||
|
{
|
||||||
|
this.env = env;
|
||||||
|
this.logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnException(ExceptionContext context)
|
||||||
|
{
|
||||||
|
logger.LogError(new EventId(context.Exception.HResult),
|
||||||
|
context.Exception,
|
||||||
|
context.Exception.Message);
|
||||||
|
|
||||||
|
if (context.Exception.GetType() == typeof(BasketDomainException))
|
||||||
|
{
|
||||||
|
var json = new JsonErrorResponse
|
||||||
|
{
|
||||||
|
Messages = new[] { context.Exception.Message }
|
||||||
|
};
|
||||||
|
|
||||||
|
context.Result = new BadRequestObjectResult(json);
|
||||||
|
context.HttpContext.Response.StatusCode = (int)HttpStatusCode.BadRequest;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var json = new JsonErrorResponse
|
||||||
|
{
|
||||||
|
Messages = new[] { "An error ocurr.Try it again." }
|
||||||
|
};
|
||||||
|
|
||||||
|
if (env.IsDevelopment())
|
||||||
|
{
|
||||||
|
json.DeveloperMeesage = context.Exception;
|
||||||
|
}
|
||||||
|
|
||||||
|
context.Result = new InternalServerErrorObjectResult(json);
|
||||||
|
context.HttpContext.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
|
||||||
|
}
|
||||||
|
context.ExceptionHandled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private class JsonErrorResponse
|
||||||
|
{
|
||||||
|
public string[] Messages { get; set; }
|
||||||
|
|
||||||
|
public object DeveloperMeesage { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,46 @@
|
|||||||
|
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions;
|
||||||
|
using Microsoft.eShopOnContainers.Services.Basket.API.IntegrationEvents.Events;
|
||||||
|
using Microsoft.eShopOnContainers.Services.Basket.API.Model;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Microsoft.eShopOnContainers.Services.Basket.API.IntegrationEvents.EventHandling
|
||||||
|
{
|
||||||
|
public class ProductPriceChangedIntegrationEventHandler : IIntegrationEventHandler<ProductPriceChangedIntegrationEvent>
|
||||||
|
{
|
||||||
|
private readonly IBasketRepository _repository;
|
||||||
|
public ProductPriceChangedIntegrationEventHandler(IBasketRepository repository)
|
||||||
|
{
|
||||||
|
_repository = repository;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task Handle(ProductPriceChangedIntegrationEvent @event)
|
||||||
|
{
|
||||||
|
var userIds = await _repository.GetUsers();
|
||||||
|
foreach (var id in userIds)
|
||||||
|
{
|
||||||
|
var basket = await _repository.GetBasketAsync(id);
|
||||||
|
await UpdatePriceInBasketItems(@event.ProductId, @event.NewPrice, @event.OldPrice, basket);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task UpdatePriceInBasketItems(int productId, decimal newPrice, decimal oldPrice, CustomerBasket basket)
|
||||||
|
{
|
||||||
|
var itemsToUpdate = basket?.Items?.Where(x => int.Parse(x.ProductId) == productId).ToList();
|
||||||
|
if (itemsToUpdate != null)
|
||||||
|
{
|
||||||
|
foreach (var item in itemsToUpdate)
|
||||||
|
{
|
||||||
|
if(item.UnitPrice == oldPrice)
|
||||||
|
{
|
||||||
|
var originalPrice = item.UnitPrice;
|
||||||
|
item.UnitPrice = newPrice;
|
||||||
|
item.OldUnitPrice = originalPrice;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
await _repository.UpdateBasketAsync(basket);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,26 @@
|
|||||||
|
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Microsoft.eShopOnContainers.Services.Basket.API.IntegrationEvents.Events
|
||||||
|
{
|
||||||
|
// Integration Events notes:
|
||||||
|
// An Event is “something that has happened in the past”, therefore its name has to be
|
||||||
|
// An Integration Event is an event that can cause side effects to other microsrvices, Bounded-Contexts or external systems.
|
||||||
|
public class ProductPriceChangedIntegrationEvent : IntegrationEvent
|
||||||
|
{
|
||||||
|
public int ProductId { get; private set; }
|
||||||
|
|
||||||
|
public decimal NewPrice { get; private set; }
|
||||||
|
|
||||||
|
public decimal OldPrice { get; private set; }
|
||||||
|
|
||||||
|
public ProductPriceChangedIntegrationEvent(int productId, decimal newPrice, decimal oldPrice)
|
||||||
|
{
|
||||||
|
ProductId = productId;
|
||||||
|
NewPrice = newPrice;
|
||||||
|
OldPrice = oldPrice;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -11,6 +11,7 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API.Model
|
|||||||
public string ProductId { get; set; }
|
public string ProductId { get; set; }
|
||||||
public string ProductName { get; set; }
|
public string ProductName { get; set; }
|
||||||
public decimal UnitPrice { get; set; }
|
public decimal UnitPrice { get; set; }
|
||||||
|
public decimal OldUnitPrice { get; set; }
|
||||||
public int Quantity { get; set; }
|
public int Quantity { get; set; }
|
||||||
public string PictureUrl { get; set; }
|
public string PictureUrl { get; set; }
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API.Model
|
|||||||
public interface IBasketRepository
|
public interface IBasketRepository
|
||||||
{
|
{
|
||||||
Task<CustomerBasket> GetBasketAsync(string customerId);
|
Task<CustomerBasket> GetBasketAsync(string customerId);
|
||||||
|
Task<IEnumerable<string>> GetUsers();
|
||||||
Task<CustomerBasket> UpdateBasketAsync(CustomerBasket basket);
|
Task<CustomerBasket> UpdateBasketAsync(CustomerBasket basket);
|
||||||
Task<bool> DeleteBasketAsync(string id);
|
Task<bool> DeleteBasketAsync(string id);
|
||||||
}
|
}
|
||||||
|
@ -31,6 +31,18 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API.Model
|
|||||||
return await database.KeyDeleteAsync(id.ToString());
|
return await database.KeyDeleteAsync(id.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<IEnumerable<string>> GetUsers()
|
||||||
|
{
|
||||||
|
var server = await GetServer();
|
||||||
|
|
||||||
|
IEnumerable<RedisKey> data = server.Keys();
|
||||||
|
if (data == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return data.Select(k => k.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
public async Task<CustomerBasket> GetBasketAsync(string customerId)
|
public async Task<CustomerBasket> GetBasketAsync(string customerId)
|
||||||
{
|
{
|
||||||
var database = await GetDatabase();
|
var database = await GetDatabase();
|
||||||
@ -63,14 +75,32 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API.Model
|
|||||||
{
|
{
|
||||||
if (_redis == null)
|
if (_redis == null)
|
||||||
{
|
{
|
||||||
//TODO: Need to make this more robust. Also want to understand why the static connection method cannot accept dns names.
|
await ConnectToRedisAsync();
|
||||||
var ips = await Dns.GetHostAddressesAsync(_settings.ConnectionString);
|
|
||||||
_logger.LogInformation($"Connecting to database {_settings.ConnectionString} at IP {ips.First().ToString()}");
|
|
||||||
_redis = await ConnectionMultiplexer.ConnectAsync(ips.First().ToString());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return _redis.GetDatabase();
|
return _redis.GetDatabase();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task<IServer> GetServer()
|
||||||
|
{
|
||||||
|
if (_redis == null)
|
||||||
|
{
|
||||||
|
await ConnectToRedisAsync();
|
||||||
|
}
|
||||||
|
var endpoint = _redis.GetEndPoints();
|
||||||
|
|
||||||
|
return _redis.GetServer(endpoint.First());
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task ConnectToRedisAsync()
|
||||||
|
{
|
||||||
|
//TODO: Need to make this more robust. Also want to understand why the static connection method cannot accept dns names.
|
||||||
|
var ips = await Dns.GetHostAddressesAsync(_settings.ConnectionString);
|
||||||
|
_logger.LogInformation($"Connecting to database {_settings.ConnectionString} at IP {ips.First().ToString()}");
|
||||||
|
_redis = await ConnectionMultiplexer.ConnectAsync(ips.First().ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API
|
|||||||
{
|
{
|
||||||
var host = new WebHostBuilder()
|
var host = new WebHostBuilder()
|
||||||
.UseKestrel()
|
.UseKestrel()
|
||||||
|
.UseHealthChecks("/hc")
|
||||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
.UseContentRoot(Directory.GetCurrentDirectory())
|
||||||
.UseIISIntegration()
|
.UseIISIntegration()
|
||||||
.UseStartup<Startup>()
|
.UseStartup<Startup>()
|
||||||
|
@ -1,7 +1,4 @@
|
|||||||
using System;
|
using System.Linq;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Microsoft.AspNetCore.Builder;
|
using Microsoft.AspNetCore.Builder;
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
@ -11,8 +8,15 @@ using Microsoft.eShopOnContainers.Services.Basket.API.Model;
|
|||||||
using StackExchange.Redis;
|
using StackExchange.Redis;
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using Swashbuckle.Swagger.Model;
|
|
||||||
using Microsoft.eShopOnContainers.Services.Basket.API.Auth.Server;
|
using Microsoft.eShopOnContainers.Services.Basket.API.Auth.Server;
|
||||||
|
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions;
|
||||||
|
using Microsoft.eShopOnContainers.Services.Basket.API.IntegrationEvents.Events;
|
||||||
|
using Microsoft.eShopOnContainers.Services.Basket.API.IntegrationEvents.EventHandling;
|
||||||
|
using Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ;
|
||||||
|
using System;
|
||||||
|
using Microsoft.Extensions.HealthChecks;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Basket.API.Infrastructure.Filters;
|
||||||
|
|
||||||
namespace Microsoft.eShopOnContainers.Services.Basket.API
|
namespace Microsoft.eShopOnContainers.Services.Basket.API
|
||||||
{
|
{
|
||||||
@ -33,8 +37,18 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API
|
|||||||
// This method gets called by the runtime. Use this method to add services to the container.
|
// This method gets called by the runtime. Use this method to add services to the container.
|
||||||
public void ConfigureServices(IServiceCollection services)
|
public void ConfigureServices(IServiceCollection services)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
services.AddHealthChecks(checks =>
|
||||||
|
{
|
||||||
|
checks.AddValueTaskCheck("Always OK", () => new ValueTask<IHealthCheckResult>(HealthCheckResult.Healthy("Ok")));
|
||||||
|
});
|
||||||
|
|
||||||
// Add framework services.
|
// Add framework services.
|
||||||
services.AddMvc();
|
services.AddMvc(options =>
|
||||||
|
{
|
||||||
|
options.Filters.Add(typeof(HttpGlobalExceptionFilter));
|
||||||
|
}).AddControllersAsServices();
|
||||||
|
|
||||||
services.Configure<BasketSettings>(Configuration);
|
services.Configure<BasketSettings>(Configuration);
|
||||||
|
|
||||||
//By connecting here we are making sure that our service
|
//By connecting here we are making sure that our service
|
||||||
@ -76,6 +90,12 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API
|
|||||||
});
|
});
|
||||||
|
|
||||||
services.AddTransient<IBasketRepository, RedisBasketRepository>();
|
services.AddTransient<IBasketRepository, RedisBasketRepository>();
|
||||||
|
services.AddTransient<IIntegrationEventHandler<ProductPriceChangedIntegrationEvent>, ProductPriceChangedIntegrationEventHandler>();
|
||||||
|
|
||||||
|
var serviceProvider = services.BuildServiceProvider();
|
||||||
|
var configuration = serviceProvider.GetRequiredService<IOptionsSnapshot<BasketSettings>>().Value;
|
||||||
|
services.AddSingleton<IEventBus>(provider => new EventBusRabbitMQ(configuration.EventBusConnection));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
||||||
@ -89,20 +109,28 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API
|
|||||||
// Use frameworks
|
// Use frameworks
|
||||||
app.UseCors("CorsPolicy");
|
app.UseCors("CorsPolicy");
|
||||||
|
|
||||||
var identityUrl = Configuration.GetValue<string>("IdentityUrl");
|
ConfigureAuth(app);
|
||||||
|
|
||||||
app.UseIdentityServerAuthentication(new IdentityServerAuthenticationOptions
|
|
||||||
{
|
|
||||||
Authority = identityUrl.ToString(),
|
|
||||||
ScopeName = "basket",
|
|
||||||
RequireHttpsMetadata = false
|
|
||||||
});
|
|
||||||
|
|
||||||
app.UseMvcWithDefaultRoute();
|
app.UseMvcWithDefaultRoute();
|
||||||
|
|
||||||
app.UseSwagger()
|
app.UseSwagger()
|
||||||
.UseSwaggerUi();
|
.UseSwaggerUi();
|
||||||
|
|
||||||
|
var catalogPriceHandler = app.ApplicationServices.GetService<IIntegrationEventHandler<ProductPriceChangedIntegrationEvent>>();
|
||||||
|
var eventBus = app.ApplicationServices.GetRequiredService<IEventBus>();
|
||||||
|
eventBus.Subscribe<ProductPriceChangedIntegrationEvent>(catalogPriceHandler);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected virtual void ConfigureAuth(IApplicationBuilder app)
|
||||||
|
{
|
||||||
|
var identityUrl = Configuration.GetValue<string>("IdentityUrl");
|
||||||
|
app.UseIdentityServerAuthentication(new IdentityServerAuthenticationOptions
|
||||||
|
{
|
||||||
|
Authority = identityUrl.ToString(),
|
||||||
|
ScopeName = "basket",
|
||||||
|
RequireHttpsMetadata = false
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
<Content Include="Pics\**\*;">
|
<Content Include="Pics\**\*;">
|
||||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
|
<Compile Include="IntegrationEvents\EventHandling\AnyFutureIntegrationEventHandler.cs.txt" />
|
||||||
<Content Update="web.config;">
|
<Content Update="web.config;">
|
||||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
@ -28,23 +29,25 @@
|
|||||||
|
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="1.1.0" />
|
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="1.1.2" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Diagnostics" Version="1.1.0" />
|
<PackageReference Include="Microsoft.AspNetCore.Diagnostics" Version="1.1.1" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Diagnostics.Abstractions" Version="1.1.0" />
|
<PackageReference Include="Microsoft.AspNetCore.Diagnostics.Abstractions" Version="1.1.1" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Server.IISIntegration" Version="1.1.0" />
|
<PackageReference Include="Microsoft.AspNetCore.Server.IISIntegration" Version="1.1.1" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="1.1.0" />
|
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="1.1.1" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="1.1.0" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="1.1.0" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="1.1.0" />
|
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="1.1.1" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="1.1.0" />
|
<PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="1.1.1" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="1.1.0" />
|
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="1.1.1" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="1.1.0" />
|
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="1.1.1" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="1.1.0" />
|
<PackageReference Include="Microsoft.Extensions.Logging" Version="1.1.1" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="1.1.0" />
|
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="1.1.1" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="1.1.0" />
|
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="1.1.1" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="1.1.0" />
|
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="1.1.1" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="1.1.0" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="1.1.1" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="1.1.0" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="1.1.1" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="1.1.0" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="1.1.1" />
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="1.1.1" />
|
||||||
|
<PackageReference Include="Newtonsoft.Json" Version="9.0.1" />
|
||||||
<PackageReference Include="Swashbuckle" Version="6.0.0-beta902" />
|
<PackageReference Include="Swashbuckle" Version="6.0.0-beta902" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
@ -52,6 +55,15 @@
|
|||||||
<DotNetCliToolReference Include="Microsoft.EntityFrameworkCore.Tools.DotNet" Version="1.0.0" />
|
<DotNetCliToolReference Include="Microsoft.EntityFrameworkCore.Tools.DotNet" Version="1.0.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\..\BuildingBlocks\EventBus\EventBusRabbitMQ\EventBusRabbitMQ.csproj" />
|
||||||
|
<ProjectReference Include="..\..\..\BuildingBlocks\EventBus\EventBus\EventBus.csproj" />
|
||||||
|
<ProjectReference Include="..\..\..\BuildingBlocks\HealthChecks\src\Microsoft.AspNetCore.HealthChecks\Microsoft.AspNetCore.HealthChecks.csproj" />
|
||||||
|
<ProjectReference Include="..\..\..\BuildingBlocks\HealthChecks\src\Microsoft.Extensions.HealthChecks.Data\Microsoft.Extensions.HealthChecks.Data.csproj" />
|
||||||
|
<ProjectReference Include="..\..\..\BuildingBlocks\HealthChecks\src\Microsoft.Extensions.HealthChecks\Microsoft.Extensions.HealthChecks.csproj" />
|
||||||
|
<ProjectReference Include="..\..\..\BuildingBlocks\EventBus\IntegrationEventLogEF\IntegrationEventLogEF.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Update="Dockerfile">
|
<None Update="Dockerfile">
|
||||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
@ -1,38 +1,51 @@
|
|||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions;
|
||||||
|
using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF.Services;
|
||||||
using Microsoft.eShopOnContainers.Services.Catalog.API.Infrastructure;
|
using Microsoft.eShopOnContainers.Services.Catalog.API.Infrastructure;
|
||||||
|
using Microsoft.eShopOnContainers.Services.Catalog.API.IntegrationEvents.Events;
|
||||||
using Microsoft.eShopOnContainers.Services.Catalog.API.Model;
|
using Microsoft.eShopOnContainers.Services.Catalog.API.Model;
|
||||||
using Microsoft.eShopOnContainers.Services.Catalog.API.ViewModel;
|
using Microsoft.eShopOnContainers.Services.Catalog.API.ViewModel;
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Data.Common;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events;
|
||||||
|
|
||||||
namespace Microsoft.eShopOnContainers.Services.Catalog.API.Controllers
|
namespace Microsoft.eShopOnContainers.Services.Catalog.API.Controllers
|
||||||
{
|
{
|
||||||
[Route("api/v1/[controller]")]
|
[Route("api/v1/[controller]")]
|
||||||
public class CatalogController : ControllerBase
|
public class CatalogController : ControllerBase
|
||||||
{
|
{
|
||||||
private readonly CatalogContext _context;
|
private readonly CatalogContext _catalogContext;
|
||||||
private readonly IOptionsSnapshot<Settings> _settings;
|
private readonly IOptionsSnapshot<Settings> _settings;
|
||||||
|
private readonly IEventBus _eventBus;
|
||||||
|
private readonly Func<DbConnection, IIntegrationEventLogService> _integrationEventLogServiceFactory;
|
||||||
|
|
||||||
public CatalogController(CatalogContext context, IOptionsSnapshot<Settings> settings)
|
public CatalogController(CatalogContext Context, IOptionsSnapshot<Settings> settings, IEventBus eventBus, Func<DbConnection, IIntegrationEventLogService> integrationEventLogServiceFactory)
|
||||||
{
|
{
|
||||||
_context = context;
|
_catalogContext = Context;
|
||||||
_settings = settings;
|
_settings = settings;
|
||||||
|
_eventBus = eventBus;
|
||||||
|
_integrationEventLogServiceFactory = integrationEventLogServiceFactory;
|
||||||
|
|
||||||
((DbContext)context).ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
|
((DbContext)Context).ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
|
||||||
}
|
}
|
||||||
|
|
||||||
// GET api/v1/[controller]/items[?pageSize=3&pageIndex=10]
|
// GET api/v1/[controller]/items[?pageSize=3&pageIndex=10]
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
[Route("[action]")]
|
[Route("[action]")]
|
||||||
public async Task<IActionResult> Items([FromQuery]int pageSize = 10, [FromQuery]int pageIndex = 0)
|
public async Task<IActionResult> Items([FromQuery]int pageSize = 10, [FromQuery]int pageIndex = 0)
|
||||||
|
|
||||||
{
|
{
|
||||||
var totalItems = await _context.CatalogItems
|
var totalItems = await _catalogContext.CatalogItems
|
||||||
.LongCountAsync();
|
.LongCountAsync();
|
||||||
|
|
||||||
var itemsOnPage = await _context.CatalogItems
|
var itemsOnPage = await _catalogContext.CatalogItems
|
||||||
.OrderBy(c=>c.Name)
|
.OrderBy(c=>c.Name)
|
||||||
.Skip(pageSize * pageIndex)
|
.Skip(pageSize * pageIndex)
|
||||||
.Take(pageSize)
|
.Take(pageSize)
|
||||||
@ -41,7 +54,7 @@ namespace Microsoft.eShopOnContainers.Services.Catalog.API.Controllers
|
|||||||
itemsOnPage = ComposePicUri(itemsOnPage);
|
itemsOnPage = ComposePicUri(itemsOnPage);
|
||||||
|
|
||||||
var model = new PaginatedItemsViewModel<CatalogItem>(
|
var model = new PaginatedItemsViewModel<CatalogItem>(
|
||||||
pageIndex, pageSize, totalItems, itemsOnPage);
|
pageIndex, pageSize, totalItems, itemsOnPage);
|
||||||
|
|
||||||
return Ok(model);
|
return Ok(model);
|
||||||
}
|
}
|
||||||
@ -52,11 +65,11 @@ namespace Microsoft.eShopOnContainers.Services.Catalog.API.Controllers
|
|||||||
public async Task<IActionResult> Items(string name, [FromQuery]int pageSize = 10, [FromQuery]int pageIndex = 0)
|
public async Task<IActionResult> Items(string name, [FromQuery]int pageSize = 10, [FromQuery]int pageIndex = 0)
|
||||||
{
|
{
|
||||||
|
|
||||||
var totalItems = await _context.CatalogItems
|
var totalItems = await _catalogContext.CatalogItems
|
||||||
.Where(c => c.Name.StartsWith(name))
|
.Where(c => c.Name.StartsWith(name))
|
||||||
.LongCountAsync();
|
.LongCountAsync();
|
||||||
|
|
||||||
var itemsOnPage = await _context.CatalogItems
|
var itemsOnPage = await _catalogContext.CatalogItems
|
||||||
.Where(c => c.Name.StartsWith(name))
|
.Where(c => c.Name.StartsWith(name))
|
||||||
.Skip(pageSize * pageIndex)
|
.Skip(pageSize * pageIndex)
|
||||||
.Take(pageSize)
|
.Take(pageSize)
|
||||||
@ -75,7 +88,7 @@ namespace Microsoft.eShopOnContainers.Services.Catalog.API.Controllers
|
|||||||
[Route("[action]/type/{catalogTypeId}/brand/{catalogBrandId}")]
|
[Route("[action]/type/{catalogTypeId}/brand/{catalogBrandId}")]
|
||||||
public async Task<IActionResult> Items(int? catalogTypeId, int? catalogBrandId, [FromQuery]int pageSize = 10, [FromQuery]int pageIndex = 0)
|
public async Task<IActionResult> Items(int? catalogTypeId, int? catalogBrandId, [FromQuery]int pageSize = 10, [FromQuery]int pageIndex = 0)
|
||||||
{
|
{
|
||||||
var root = (IQueryable<CatalogItem>)_context.CatalogItems;
|
var root = (IQueryable<CatalogItem>)_catalogContext.CatalogItems;
|
||||||
|
|
||||||
if (catalogTypeId.HasValue)
|
if (catalogTypeId.HasValue)
|
||||||
{
|
{
|
||||||
@ -99,7 +112,7 @@ namespace Microsoft.eShopOnContainers.Services.Catalog.API.Controllers
|
|||||||
|
|
||||||
var model = new PaginatedItemsViewModel<CatalogItem>(
|
var model = new PaginatedItemsViewModel<CatalogItem>(
|
||||||
pageIndex, pageSize, totalItems, itemsOnPage);
|
pageIndex, pageSize, totalItems, itemsOnPage);
|
||||||
|
|
||||||
return Ok(model);
|
return Ok(model);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -108,7 +121,7 @@ namespace Microsoft.eShopOnContainers.Services.Catalog.API.Controllers
|
|||||||
[Route("[action]")]
|
[Route("[action]")]
|
||||||
public async Task<IActionResult> CatalogTypes()
|
public async Task<IActionResult> CatalogTypes()
|
||||||
{
|
{
|
||||||
var items = await _context.CatalogTypes
|
var items = await _catalogContext.CatalogTypes
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
|
|
||||||
return Ok(items);
|
return Ok(items);
|
||||||
@ -119,12 +132,107 @@ namespace Microsoft.eShopOnContainers.Services.Catalog.API.Controllers
|
|||||||
[Route("[action]")]
|
[Route("[action]")]
|
||||||
public async Task<IActionResult> CatalogBrands()
|
public async Task<IActionResult> CatalogBrands()
|
||||||
{
|
{
|
||||||
var items = await _context.CatalogBrands
|
var items = await _catalogContext.CatalogBrands
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
|
|
||||||
return Ok(items);
|
return Ok(items);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//POST api/v1/[controller]/update
|
||||||
|
[Route("update")]
|
||||||
|
[HttpPost]
|
||||||
|
public async Task<IActionResult> UpdateProduct([FromBody]CatalogItem productToUpdate)
|
||||||
|
{
|
||||||
|
var catalogItem = await _catalogContext.CatalogItems.SingleOrDefaultAsync(i => i.Id == productToUpdate.Id);
|
||||||
|
if (catalogItem == null) return NotFound();
|
||||||
|
|
||||||
|
bool raiseProductPriceChangedEvent = false;
|
||||||
|
IntegrationEvent priceChangedEvent = null;
|
||||||
|
|
||||||
|
if (catalogItem.Price != productToUpdate.Price) raiseProductPriceChangedEvent = true;
|
||||||
|
|
||||||
|
if (raiseProductPriceChangedEvent) // Create event if price has changed
|
||||||
|
{
|
||||||
|
var oldPrice = catalogItem.Price;
|
||||||
|
priceChangedEvent = new ProductPriceChangedIntegrationEvent(catalogItem.Id, productToUpdate.Price, oldPrice);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Update current product
|
||||||
|
catalogItem = productToUpdate;
|
||||||
|
|
||||||
|
//Use of an EF Core resiliency strategy when using multiple DbContexts within an explicit BeginTransaction():
|
||||||
|
//See: https://docs.microsoft.com/en-us/ef/core/miscellaneous/connection-resiliency
|
||||||
|
var strategy = _catalogContext.Database.CreateExecutionStrategy();
|
||||||
|
var eventLogService = _integrationEventLogServiceFactory(_catalogContext.Database.GetDbConnection());
|
||||||
|
await strategy.ExecuteAsync(async () =>
|
||||||
|
{
|
||||||
|
// Achieving atomicity between original Catalog database operation and the IntegrationEventLog thanks to a local transaction
|
||||||
|
using (var transaction = _catalogContext.Database.BeginTransaction())
|
||||||
|
{
|
||||||
|
_catalogContext.CatalogItems.Update(catalogItem);
|
||||||
|
await _catalogContext.SaveChangesAsync();
|
||||||
|
|
||||||
|
//Save to EventLog only if product price changed
|
||||||
|
if (raiseProductPriceChangedEvent)
|
||||||
|
{
|
||||||
|
|
||||||
|
await eventLogService.SaveEventAsync(priceChangedEvent, _catalogContext.Database.CurrentTransaction.GetDbTransaction());
|
||||||
|
}
|
||||||
|
|
||||||
|
transaction.Commit();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
//Publish to Event Bus only if product price changed
|
||||||
|
if (raiseProductPriceChangedEvent)
|
||||||
|
{
|
||||||
|
_eventBus.Publish(priceChangedEvent);
|
||||||
|
await eventLogService.MarkEventAsPublishedAsync(priceChangedEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
//POST api/v1/[controller]/create
|
||||||
|
[Route("create")]
|
||||||
|
[HttpPost]
|
||||||
|
public async Task<IActionResult> CreateProduct([FromBody]CatalogItem product)
|
||||||
|
{
|
||||||
|
_catalogContext.CatalogItems.Add(
|
||||||
|
new CatalogItem
|
||||||
|
{
|
||||||
|
CatalogBrandId = product.CatalogBrandId,
|
||||||
|
CatalogTypeId = product.CatalogTypeId,
|
||||||
|
Description = product.Description,
|
||||||
|
Name = product.Name,
|
||||||
|
PictureUri = product.PictureUri,
|
||||||
|
Price = product.Price
|
||||||
|
});
|
||||||
|
|
||||||
|
await _catalogContext.SaveChangesAsync();
|
||||||
|
|
||||||
|
return Ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
//DELETE api/v1/[controller]/id
|
||||||
|
[Route("{id}")]
|
||||||
|
[HttpDelete]
|
||||||
|
public async Task<IActionResult> DeleteProduct(int id)
|
||||||
|
{
|
||||||
|
var product = _catalogContext.CatalogItems.SingleOrDefault(x => x.Id == id);
|
||||||
|
|
||||||
|
if (product == null)
|
||||||
|
{
|
||||||
|
return NotFound();
|
||||||
|
}
|
||||||
|
|
||||||
|
_catalogContext.CatalogItems.Remove(product);
|
||||||
|
await _catalogContext.SaveChangesAsync();
|
||||||
|
|
||||||
|
return Ok();
|
||||||
|
}
|
||||||
|
|
||||||
private List<CatalogItem> ComposePicUri(List<CatalogItem> items) {
|
private List<CatalogItem> ComposePicUri(List<CatalogItem> items) {
|
||||||
var baseUri = _settings.Value.ExternalCatalogBaseUrl;
|
var baseUri = _settings.Value.ExternalCatalogBaseUrl;
|
||||||
items.ForEach(x =>
|
items.ForEach(x =>
|
||||||
|
8
src/Services/Catalog/Catalog.API/Dockerfile.nanowin
Normal file
8
src/Services/Catalog/Catalog.API/Dockerfile.nanowin
Normal 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", "Catalog.API.dll"]
|
@ -0,0 +1,18 @@
|
|||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Catalog.API.Infrastructure.ActionResults
|
||||||
|
{
|
||||||
|
public class InternalServerErrorObjectResult : ObjectResult
|
||||||
|
{
|
||||||
|
public InternalServerErrorObjectResult(object error)
|
||||||
|
: base(error)
|
||||||
|
{
|
||||||
|
StatusCode = StatusCodes.Status500InternalServerError;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -3,21 +3,25 @@
|
|||||||
using EntityFrameworkCore.Metadata.Builders;
|
using EntityFrameworkCore.Metadata.Builders;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Model;
|
using Model;
|
||||||
|
using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF;
|
||||||
|
|
||||||
public class CatalogContext : DbContext
|
public class CatalogContext : DbContext
|
||||||
{
|
{
|
||||||
public CatalogContext(DbContextOptions options) : base(options)
|
public CatalogContext(DbContextOptions<CatalogContext> options) : base(options)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
public DbSet<CatalogItem> CatalogItems { get; set; }
|
public DbSet<CatalogItem> CatalogItems { get; set; }
|
||||||
public DbSet<CatalogBrand> CatalogBrands { get; set; }
|
public DbSet<CatalogBrand> CatalogBrands { get; set; }
|
||||||
public DbSet<CatalogType> CatalogTypes { get; set; }
|
public DbSet<CatalogType> CatalogTypes { get; set; }
|
||||||
|
//public DbSet<IntegrationEventLogEntry> IntegrationEventLog { get; set; }
|
||||||
|
|
||||||
protected override void OnModelCreating(ModelBuilder builder)
|
protected override void OnModelCreating(ModelBuilder builder)
|
||||||
{
|
{
|
||||||
builder.Entity<CatalogBrand>(ConfigureCatalogBrand);
|
builder.Entity<CatalogBrand>(ConfigureCatalogBrand);
|
||||||
builder.Entity<CatalogType>(ConfigureCatalogType);
|
builder.Entity<CatalogType>(ConfigureCatalogType);
|
||||||
builder.Entity<CatalogItem>(ConfigureCatalogItem);
|
builder.Entity<CatalogItem>(ConfigureCatalogItem);
|
||||||
}
|
//builder.Entity<IntegrationEventLogEntry>(ConfigureIntegrationEventLogEntry);
|
||||||
|
}
|
||||||
|
|
||||||
void ConfigureCatalogItem(EntityTypeBuilder<CatalogItem> builder)
|
void ConfigureCatalogItem(EntityTypeBuilder<CatalogItem> builder)
|
||||||
{
|
{
|
||||||
@ -75,5 +79,31 @@
|
|||||||
.IsRequired()
|
.IsRequired()
|
||||||
.HasMaxLength(100);
|
.HasMaxLength(100);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//void ConfigureIntegrationEventLogEntry(EntityTypeBuilder<IntegrationEventLogEntry> builder)
|
||||||
|
//{
|
||||||
|
// builder.ToTable("IntegrationEventLog");
|
||||||
|
|
||||||
|
// builder.HasKey(e => e.EventId);
|
||||||
|
|
||||||
|
// builder.Property(e => e.EventId)
|
||||||
|
// .IsRequired();
|
||||||
|
|
||||||
|
// builder.Property(e => e.Content)
|
||||||
|
// .IsRequired();
|
||||||
|
|
||||||
|
// builder.Property(e => e.CreationTime)
|
||||||
|
// .IsRequired();
|
||||||
|
|
||||||
|
// builder.Property(e => e.State)
|
||||||
|
// .IsRequired();
|
||||||
|
|
||||||
|
// builder.Property(e => e.TimesSent)
|
||||||
|
// .IsRequired();
|
||||||
|
|
||||||
|
// builder.Property(e => e.EventTypeName)
|
||||||
|
// .IsRequired();
|
||||||
|
|
||||||
|
//}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -70,14 +70,14 @@
|
|||||||
{
|
{
|
||||||
return new List<CatalogItem>()
|
return new List<CatalogItem>()
|
||||||
{
|
{
|
||||||
new CatalogItem() { CatalogTypeId=2,CatalogBrandId=2, Description = ".NET Bot Black Sweatshirt", Name = ".NET Bot Black Sweatshirt", Price = 19.5M, PictureUri = "http://externalcatalogbaseurltobereplaced/api/v1/pic/1" },
|
new CatalogItem() { CatalogTypeId=2,CatalogBrandId=2, Description = ".NET Bot Black Hoodie", Name = ".NET Bot Black Hoodie", Price = 19.5M, PictureUri = "http://externalcatalogbaseurltobereplaced/api/v1/pic/1" },
|
||||||
new CatalogItem() { CatalogTypeId=1,CatalogBrandId=2, Description = ".NET Black & White Mug", Name = ".NET Black & White Mug", Price= 8.50M, PictureUri = "http://externalcatalogbaseurltobereplaced/api/v1/pic/2" },
|
new CatalogItem() { CatalogTypeId=1,CatalogBrandId=2, Description = ".NET Black & White Mug", Name = ".NET Black & White Mug", Price= 8.50M, PictureUri = "http://externalcatalogbaseurltobereplaced/api/v1/pic/2" },
|
||||||
new CatalogItem() { CatalogTypeId=2,CatalogBrandId=5, Description = "Prism White T-Shirt", Name = "Prism White T-Shirt", Price = 12, PictureUri = "http://externalcatalogbaseurltobereplaced/api/v1/pic/3" },
|
new CatalogItem() { CatalogTypeId=2,CatalogBrandId=5, Description = "Prism White T-Shirt", Name = "Prism White T-Shirt", Price = 12, PictureUri = "http://externalcatalogbaseurltobereplaced/api/v1/pic/3" },
|
||||||
new CatalogItem() { CatalogTypeId=2,CatalogBrandId=2, Description = ".NET Foundation Sweatshirt", Name = ".NET Foundation Sweatshirt", Price = 12, PictureUri = "http://externalcatalogbaseurltobereplaced/api/v1/pic/4" },
|
new CatalogItem() { CatalogTypeId=2,CatalogBrandId=2, Description = ".NET Foundation T-shirt", Name = ".NET Foundation T-shirt", Price = 12, PictureUri = "http://externalcatalogbaseurltobereplaced/api/v1/pic/4" },
|
||||||
new CatalogItem() { CatalogTypeId=3,CatalogBrandId=5, Description = "Roslyn Red Sheet", Name = "Roslyn Red Sheet", Price = 8.5M, PictureUri = "http://externalcatalogbaseurltobereplaced/api/v1/pic/5" },
|
new CatalogItem() { CatalogTypeId=3,CatalogBrandId=5, Description = "Roslyn Red Sheet", Name = "Roslyn Red Sheet", Price = 8.5M, PictureUri = "http://externalcatalogbaseurltobereplaced/api/v1/pic/5" },
|
||||||
new CatalogItem() { CatalogTypeId=2,CatalogBrandId=2, Description = ".NET Blue Sweatshirt", Name = ".NET Blue Sweatshirt", Price = 12, PictureUri = "http://externalcatalogbaseurltobereplaced/api/v1/pic/6" },
|
new CatalogItem() { CatalogTypeId=2,CatalogBrandId=2, Description = ".NET Blue Hoodie", Name = ".NET Blue Hoodie", Price = 12, PictureUri = "http://externalcatalogbaseurltobereplaced/api/v1/pic/6" },
|
||||||
new CatalogItem() { CatalogTypeId=2,CatalogBrandId=5, Description = "Roslyn Red T-Shirt", Name = "Roslyn Red T-Shirt", Price = 12, PictureUri = "http://externalcatalogbaseurltobereplaced/api/v1/pic/7" },
|
new CatalogItem() { CatalogTypeId=2,CatalogBrandId=5, Description = "Roslyn Red T-Shirt", Name = "Roslyn Red T-Shirt", Price = 12, PictureUri = "http://externalcatalogbaseurltobereplaced/api/v1/pic/7" },
|
||||||
new CatalogItem() { CatalogTypeId=2,CatalogBrandId=5, Description = "Kudu Purple Sweatshirt", Name = "Kudu Purple Sweatshirt", Price = 8.5M, PictureUri = "http://externalcatalogbaseurltobereplaced/api/v1/pic/8" },
|
new CatalogItem() { CatalogTypeId=2,CatalogBrandId=5, Description = "Kudu Purple Hoodie", Name = "Kudu Purple Hoodie", Price = 8.5M, PictureUri = "http://externalcatalogbaseurltobereplaced/api/v1/pic/8" },
|
||||||
new CatalogItem() { CatalogTypeId=1,CatalogBrandId=5, Description = "Cup<T> White Mug", Name = "Cup<T> White Mug", Price = 12, PictureUri = "http://externalcatalogbaseurltobereplaced/api/v1/pic/9" },
|
new CatalogItem() { CatalogTypeId=1,CatalogBrandId=5, Description = "Cup<T> White Mug", Name = "Cup<T> White Mug", Price = 12, PictureUri = "http://externalcatalogbaseurltobereplaced/api/v1/pic/9" },
|
||||||
new CatalogItem() { CatalogTypeId=3,CatalogBrandId=2, Description = ".NET Foundation Sheet", Name = ".NET Foundation Sheet", Price = 12, PictureUri = "http://externalcatalogbaseurltobereplaced/api/v1/pic/10" },
|
new CatalogItem() { CatalogTypeId=3,CatalogBrandId=2, Description = ".NET Foundation Sheet", Name = ".NET Foundation Sheet", Price = 12, PictureUri = "http://externalcatalogbaseurltobereplaced/api/v1/pic/10" },
|
||||||
new CatalogItem() { CatalogTypeId=3,CatalogBrandId=2, Description = "Cup<T> Sheet", Name = "Cup<T> Sheet", Price = 8.5M, PictureUri = "http://externalcatalogbaseurltobereplaced/api/v1/pic/11" },
|
new CatalogItem() { CatalogTypeId=3,CatalogBrandId=2, Description = "Cup<T> Sheet", Name = "Cup<T> Sheet", Price = 8.5M, PictureUri = "http://externalcatalogbaseurltobereplaced/api/v1/pic/11" },
|
||||||
|
@ -0,0 +1,122 @@
|
|||||||
|
using System;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.eShopOnContainers.Services.Catalog.API.Infrastructure;
|
||||||
|
|
||||||
|
namespace Catalog.API.Infrastructure.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(CatalogContext))]
|
||||||
|
[Migration("20170314083211_AddEventTable")]
|
||||||
|
partial class AddEventTable
|
||||||
|
{
|
||||||
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
modelBuilder
|
||||||
|
.HasAnnotation("ProductVersion", "1.1.0-rtm-22752")
|
||||||
|
.HasAnnotation("SqlServer:Sequence:.catalog_brand_hilo", "'catalog_brand_hilo', '', '1', '10', '', '', 'Int64', 'False'")
|
||||||
|
.HasAnnotation("SqlServer:Sequence:.catalog_hilo", "'catalog_hilo', '', '1', '10', '', '', 'Int64', 'False'")
|
||||||
|
.HasAnnotation("SqlServer:Sequence:.catalog_type_hilo", "'catalog_type_hilo', '', '1', '10', '', '', 'Int64', 'False'")
|
||||||
|
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Catalog.API.Model.CatalogBrand", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasAnnotation("SqlServer:HiLoSequenceName", "catalog_brand_hilo")
|
||||||
|
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.SequenceHiLo);
|
||||||
|
|
||||||
|
b.Property<string>("Brand")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(100);
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("CatalogBrand");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Catalog.API.Model.CatalogItem", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasAnnotation("SqlServer:HiLoSequenceName", "catalog_hilo")
|
||||||
|
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.SequenceHiLo);
|
||||||
|
|
||||||
|
b.Property<int>("CatalogBrandId");
|
||||||
|
|
||||||
|
b.Property<int>("CatalogTypeId");
|
||||||
|
|
||||||
|
b.Property<string>("Description");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(50);
|
||||||
|
|
||||||
|
b.Property<string>("PictureUri");
|
||||||
|
|
||||||
|
b.Property<decimal>("Price");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("CatalogBrandId");
|
||||||
|
|
||||||
|
b.HasIndex("CatalogTypeId");
|
||||||
|
|
||||||
|
b.ToTable("Catalog");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Catalog.API.Model.CatalogType", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasAnnotation("SqlServer:HiLoSequenceName", "catalog_type_hilo")
|
||||||
|
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.SequenceHiLo);
|
||||||
|
|
||||||
|
b.Property<string>("Type")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(100);
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("CatalogType");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Common.Infrastructure.Data.IntegrationEvent", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("EventId")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<string>("Content")
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreationTime");
|
||||||
|
|
||||||
|
b.Property<string>("EventTypeName")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(200);
|
||||||
|
|
||||||
|
b.Property<int>("State");
|
||||||
|
|
||||||
|
b.Property<int>("TimesSent");
|
||||||
|
|
||||||
|
b.HasKey("EventId");
|
||||||
|
|
||||||
|
b.ToTable("IntegrationEvent");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Catalog.API.Model.CatalogItem", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Microsoft.eShopOnContainers.Services.Catalog.API.Model.CatalogBrand", "CatalogBrand")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("CatalogBrandId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
|
||||||
|
b.HasOne("Microsoft.eShopOnContainers.Services.Catalog.API.Model.CatalogType", "CatalogType")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("CatalogTypeId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
namespace Catalog.API.Infrastructure.Migrations
|
||||||
|
{
|
||||||
|
public partial class AddEventTable : Migration
|
||||||
|
{
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "IntegrationEvent",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
EventId = table.Column<Guid>(nullable: false),
|
||||||
|
Content = table.Column<string>(nullable: false),
|
||||||
|
CreationTime = table.Column<DateTime>(nullable: false),
|
||||||
|
EventTypeName = table.Column<string>(maxLength: 200, nullable: false),
|
||||||
|
State = table.Column<int>(nullable: false),
|
||||||
|
TimesSent = table.Column<int>(nullable: false)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_IntegrationEvent", x => x.EventId);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "IntegrationEvent");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,121 @@
|
|||||||
|
using System;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.eShopOnContainers.Services.Catalog.API.Infrastructure;
|
||||||
|
|
||||||
|
namespace Catalog.API.Infrastructure.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(CatalogContext))]
|
||||||
|
[Migration("20170316012921_RefactoringToIntegrationEventLog")]
|
||||||
|
partial class RefactoringToIntegrationEventLog
|
||||||
|
{
|
||||||
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
modelBuilder
|
||||||
|
.HasAnnotation("ProductVersion", "1.1.1")
|
||||||
|
.HasAnnotation("SqlServer:Sequence:.catalog_brand_hilo", "'catalog_brand_hilo', '', '1', '10', '', '', 'Int64', 'False'")
|
||||||
|
.HasAnnotation("SqlServer:Sequence:.catalog_hilo", "'catalog_hilo', '', '1', '10', '', '', 'Int64', 'False'")
|
||||||
|
.HasAnnotation("SqlServer:Sequence:.catalog_type_hilo", "'catalog_type_hilo', '', '1', '10', '', '', 'Int64', 'False'")
|
||||||
|
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Catalog.API.Model.CatalogBrand", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasAnnotation("SqlServer:HiLoSequenceName", "catalog_brand_hilo")
|
||||||
|
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.SequenceHiLo);
|
||||||
|
|
||||||
|
b.Property<string>("Brand")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(100);
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("CatalogBrand");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Catalog.API.Model.CatalogItem", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasAnnotation("SqlServer:HiLoSequenceName", "catalog_hilo")
|
||||||
|
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.SequenceHiLo);
|
||||||
|
|
||||||
|
b.Property<int>("CatalogBrandId");
|
||||||
|
|
||||||
|
b.Property<int>("CatalogTypeId");
|
||||||
|
|
||||||
|
b.Property<string>("Description");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(50);
|
||||||
|
|
||||||
|
b.Property<string>("PictureUri");
|
||||||
|
|
||||||
|
b.Property<decimal>("Price");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("CatalogBrandId");
|
||||||
|
|
||||||
|
b.HasIndex("CatalogTypeId");
|
||||||
|
|
||||||
|
b.ToTable("Catalog");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Catalog.API.Model.CatalogType", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasAnnotation("SqlServer:HiLoSequenceName", "catalog_type_hilo")
|
||||||
|
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.SequenceHiLo);
|
||||||
|
|
||||||
|
b.Property<string>("Type")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(100);
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("CatalogType");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Common.Infrastructure.Data.IntegrationEventLogEntry", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("EventId")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<string>("Content")
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreationTime");
|
||||||
|
|
||||||
|
b.Property<string>("EventTypeName")
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Property<int>("State");
|
||||||
|
|
||||||
|
b.Property<int>("TimesSent");
|
||||||
|
|
||||||
|
b.HasKey("EventId");
|
||||||
|
|
||||||
|
b.ToTable("IntegrationEventLog");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Catalog.API.Model.CatalogItem", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Microsoft.eShopOnContainers.Services.Catalog.API.Model.CatalogBrand", "CatalogBrand")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("CatalogBrandId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
|
||||||
|
b.HasOne("Microsoft.eShopOnContainers.Services.Catalog.API.Model.CatalogType", "CatalogType")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("CatalogTypeId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,53 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
namespace Catalog.API.Infrastructure.Migrations
|
||||||
|
{
|
||||||
|
public partial class RefactoringToIntegrationEventLog : Migration
|
||||||
|
{
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "IntegrationEvent");
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "IntegrationEventLog",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
EventId = table.Column<Guid>(nullable: false),
|
||||||
|
Content = table.Column<string>(nullable: false),
|
||||||
|
CreationTime = table.Column<DateTime>(nullable: false),
|
||||||
|
EventTypeName = table.Column<string>(nullable: false),
|
||||||
|
State = table.Column<int>(nullable: false),
|
||||||
|
TimesSent = table.Column<int>(nullable: false)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_IntegrationEventLog", x => x.EventId);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "IntegrationEventLog");
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "IntegrationEvent",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
EventId = table.Column<Guid>(nullable: false),
|
||||||
|
Content = table.Column<string>(nullable: false),
|
||||||
|
CreationTime = table.Column<DateTime>(nullable: false),
|
||||||
|
EventTypeName = table.Column<string>(maxLength: 200, nullable: false),
|
||||||
|
State = table.Column<int>(nullable: false),
|
||||||
|
TimesSent = table.Column<int>(nullable: false)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_IntegrationEvent", x => x.EventId);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,122 @@
|
|||||||
|
using System;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.eShopOnContainers.Services.Catalog.API.Infrastructure;
|
||||||
|
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events;
|
||||||
|
|
||||||
|
namespace Catalog.API.Infrastructure.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(CatalogContext))]
|
||||||
|
[Migration("20170316120022_RefactoringEventBusNamespaces")]
|
||||||
|
partial class RefactoringEventBusNamespaces
|
||||||
|
{
|
||||||
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
modelBuilder
|
||||||
|
.HasAnnotation("ProductVersion", "1.1.1")
|
||||||
|
.HasAnnotation("SqlServer:Sequence:.catalog_brand_hilo", "'catalog_brand_hilo', '', '1', '10', '', '', 'Int64', 'False'")
|
||||||
|
.HasAnnotation("SqlServer:Sequence:.catalog_hilo", "'catalog_hilo', '', '1', '10', '', '', 'Int64', 'False'")
|
||||||
|
.HasAnnotation("SqlServer:Sequence:.catalog_type_hilo", "'catalog_type_hilo', '', '1', '10', '', '', 'Int64', 'False'")
|
||||||
|
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events.IntegrationEventLogEntry", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("EventId")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<string>("Content")
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreationTime");
|
||||||
|
|
||||||
|
b.Property<string>("EventTypeName")
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Property<int>("State");
|
||||||
|
|
||||||
|
b.Property<int>("TimesSent");
|
||||||
|
|
||||||
|
b.HasKey("EventId");
|
||||||
|
|
||||||
|
b.ToTable("IntegrationEventLog");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Catalog.API.Model.CatalogBrand", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasAnnotation("SqlServer:HiLoSequenceName", "catalog_brand_hilo")
|
||||||
|
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.SequenceHiLo);
|
||||||
|
|
||||||
|
b.Property<string>("Brand")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(100);
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("CatalogBrand");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Catalog.API.Model.CatalogItem", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasAnnotation("SqlServer:HiLoSequenceName", "catalog_hilo")
|
||||||
|
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.SequenceHiLo);
|
||||||
|
|
||||||
|
b.Property<int>("CatalogBrandId");
|
||||||
|
|
||||||
|
b.Property<int>("CatalogTypeId");
|
||||||
|
|
||||||
|
b.Property<string>("Description");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(50);
|
||||||
|
|
||||||
|
b.Property<string>("PictureUri");
|
||||||
|
|
||||||
|
b.Property<decimal>("Price");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("CatalogBrandId");
|
||||||
|
|
||||||
|
b.HasIndex("CatalogTypeId");
|
||||||
|
|
||||||
|
b.ToTable("Catalog");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Catalog.API.Model.CatalogType", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasAnnotation("SqlServer:HiLoSequenceName", "catalog_type_hilo")
|
||||||
|
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.SequenceHiLo);
|
||||||
|
|
||||||
|
b.Property<string>("Type")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(100);
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("CatalogType");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Catalog.API.Model.CatalogItem", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Microsoft.eShopOnContainers.Services.Catalog.API.Model.CatalogBrand", "CatalogBrand")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("CatalogBrandId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
|
||||||
|
b.HasOne("Microsoft.eShopOnContainers.Services.Catalog.API.Model.CatalogType", "CatalogType")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("CatalogTypeId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
namespace Catalog.API.Infrastructure.Migrations
|
||||||
|
{
|
||||||
|
public partial class RefactoringEventBusNamespaces : Migration
|
||||||
|
{
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,99 @@
|
|||||||
|
using System;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.eShopOnContainers.Services.Catalog.API.Infrastructure;
|
||||||
|
|
||||||
|
namespace Catalog.API.Infrastructure.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(CatalogContext))]
|
||||||
|
[Migration("20170322124244_RemoveIntegrationEventLogs")]
|
||||||
|
partial class RemoveIntegrationEventLogs
|
||||||
|
{
|
||||||
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
modelBuilder
|
||||||
|
.HasAnnotation("ProductVersion", "1.1.1")
|
||||||
|
.HasAnnotation("SqlServer:Sequence:.catalog_brand_hilo", "'catalog_brand_hilo', '', '1', '10', '', '', 'Int64', 'False'")
|
||||||
|
.HasAnnotation("SqlServer:Sequence:.catalog_hilo", "'catalog_hilo', '', '1', '10', '', '', 'Int64', 'False'")
|
||||||
|
.HasAnnotation("SqlServer:Sequence:.catalog_type_hilo", "'catalog_type_hilo', '', '1', '10', '', '', 'Int64', 'False'")
|
||||||
|
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Catalog.API.Model.CatalogBrand", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasAnnotation("SqlServer:HiLoSequenceName", "catalog_brand_hilo")
|
||||||
|
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.SequenceHiLo);
|
||||||
|
|
||||||
|
b.Property<string>("Brand")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(100);
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("CatalogBrand");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Catalog.API.Model.CatalogItem", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasAnnotation("SqlServer:HiLoSequenceName", "catalog_hilo")
|
||||||
|
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.SequenceHiLo);
|
||||||
|
|
||||||
|
b.Property<int>("CatalogBrandId");
|
||||||
|
|
||||||
|
b.Property<int>("CatalogTypeId");
|
||||||
|
|
||||||
|
b.Property<string>("Description");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(50);
|
||||||
|
|
||||||
|
b.Property<string>("PictureUri");
|
||||||
|
|
||||||
|
b.Property<decimal>("Price");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("CatalogBrandId");
|
||||||
|
|
||||||
|
b.HasIndex("CatalogTypeId");
|
||||||
|
|
||||||
|
b.ToTable("Catalog");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Catalog.API.Model.CatalogType", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasAnnotation("SqlServer:HiLoSequenceName", "catalog_type_hilo")
|
||||||
|
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.SequenceHiLo);
|
||||||
|
|
||||||
|
b.Property<string>("Type")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(100);
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("CatalogType");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Catalog.API.Model.CatalogItem", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Microsoft.eShopOnContainers.Services.Catalog.API.Model.CatalogBrand", "CatalogBrand")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("CatalogBrandId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
|
||||||
|
b.HasOne("Microsoft.eShopOnContainers.Services.Catalog.API.Model.CatalogType", "CatalogType")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("CatalogTypeId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
namespace Catalog.API.Infrastructure.Migrations
|
||||||
|
{
|
||||||
|
public partial class RemoveIntegrationEventLogs : Migration
|
||||||
|
{
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "IntegrationEventLog");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "IntegrationEventLog",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
EventId = table.Column<Guid>(nullable: false),
|
||||||
|
Content = table.Column<string>(nullable: false),
|
||||||
|
CreationTime = table.Column<DateTime>(nullable: false),
|
||||||
|
EventTypeName = table.Column<string>(nullable: false),
|
||||||
|
State = table.Column<int>(nullable: false),
|
||||||
|
TimesSent = table.Column<int>(nullable: false)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_IntegrationEventLog", x => x.EventId);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -13,13 +13,13 @@ namespace Catalog.API.Infrastructure.Migrations
|
|||||||
protected override void BuildModel(ModelBuilder modelBuilder)
|
protected override void BuildModel(ModelBuilder modelBuilder)
|
||||||
{
|
{
|
||||||
modelBuilder
|
modelBuilder
|
||||||
.HasAnnotation("ProductVersion", "1.0.1")
|
.HasAnnotation("ProductVersion", "1.1.1")
|
||||||
.HasAnnotation("SqlServer:Sequence:.catalog_brand_hilo", "'catalog_brand_hilo', '', '1', '10', '', '', 'Int64', 'False'")
|
.HasAnnotation("SqlServer:Sequence:.catalog_brand_hilo", "'catalog_brand_hilo', '', '1', '10', '', '', 'Int64', 'False'")
|
||||||
.HasAnnotation("SqlServer:Sequence:.catalog_hilo", "'catalog_hilo', '', '1', '10', '', '', 'Int64', 'False'")
|
.HasAnnotation("SqlServer:Sequence:.catalog_hilo", "'catalog_hilo', '', '1', '10', '', '', 'Int64', 'False'")
|
||||||
.HasAnnotation("SqlServer:Sequence:.catalog_type_hilo", "'catalog_type_hilo', '', '1', '10', '', '', 'Int64', 'False'")
|
.HasAnnotation("SqlServer:Sequence:.catalog_type_hilo", "'catalog_type_hilo', '', '1', '10', '', '', 'Int64', 'False'")
|
||||||
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
|
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
|
||||||
|
|
||||||
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Catalog.API.Infrastructure.CatalogBrand", b =>
|
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Catalog.API.Model.CatalogBrand", b =>
|
||||||
{
|
{
|
||||||
b.Property<int>("Id")
|
b.Property<int>("Id")
|
||||||
.ValueGeneratedOnAdd()
|
.ValueGeneratedOnAdd()
|
||||||
@ -28,14 +28,14 @@ namespace Catalog.API.Infrastructure.Migrations
|
|||||||
|
|
||||||
b.Property<string>("Brand")
|
b.Property<string>("Brand")
|
||||||
.IsRequired()
|
.IsRequired()
|
||||||
.HasAnnotation("MaxLength", 100);
|
.HasMaxLength(100);
|
||||||
|
|
||||||
b.HasKey("Id");
|
b.HasKey("Id");
|
||||||
|
|
||||||
b.ToTable("CatalogBrand");
|
b.ToTable("CatalogBrand");
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Catalog.API.Infrastructure.CatalogItem", b =>
|
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Catalog.API.Model.CatalogItem", b =>
|
||||||
{
|
{
|
||||||
b.Property<int>("Id")
|
b.Property<int>("Id")
|
||||||
.ValueGeneratedOnAdd()
|
.ValueGeneratedOnAdd()
|
||||||
@ -50,7 +50,7 @@ namespace Catalog.API.Infrastructure.Migrations
|
|||||||
|
|
||||||
b.Property<string>("Name")
|
b.Property<string>("Name")
|
||||||
.IsRequired()
|
.IsRequired()
|
||||||
.HasAnnotation("MaxLength", 50);
|
.HasMaxLength(50);
|
||||||
|
|
||||||
b.Property<string>("PictureUri");
|
b.Property<string>("PictureUri");
|
||||||
|
|
||||||
@ -65,7 +65,7 @@ namespace Catalog.API.Infrastructure.Migrations
|
|||||||
b.ToTable("Catalog");
|
b.ToTable("Catalog");
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Catalog.API.Infrastructure.CatalogType", b =>
|
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Catalog.API.Model.CatalogType", b =>
|
||||||
{
|
{
|
||||||
b.Property<int>("Id")
|
b.Property<int>("Id")
|
||||||
.ValueGeneratedOnAdd()
|
.ValueGeneratedOnAdd()
|
||||||
@ -74,21 +74,21 @@ namespace Catalog.API.Infrastructure.Migrations
|
|||||||
|
|
||||||
b.Property<string>("Type")
|
b.Property<string>("Type")
|
||||||
.IsRequired()
|
.IsRequired()
|
||||||
.HasAnnotation("MaxLength", 100);
|
.HasMaxLength(100);
|
||||||
|
|
||||||
b.HasKey("Id");
|
b.HasKey("Id");
|
||||||
|
|
||||||
b.ToTable("CatalogType");
|
b.ToTable("CatalogType");
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Catalog.API.Infrastructure.CatalogItem", b =>
|
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Catalog.API.Model.CatalogItem", b =>
|
||||||
{
|
{
|
||||||
b.HasOne("Microsoft.eShopOnContainers.Services.Catalog.API.Infrastructure.CatalogBrand", "CatalogBrand")
|
b.HasOne("Microsoft.eShopOnContainers.Services.Catalog.API.Model.CatalogBrand", "CatalogBrand")
|
||||||
.WithMany()
|
.WithMany()
|
||||||
.HasForeignKey("CatalogBrandId")
|
.HasForeignKey("CatalogBrandId")
|
||||||
.OnDelete(DeleteBehavior.Cascade);
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
|
||||||
b.HasOne("Microsoft.eShopOnContainers.Services.Catalog.API.Infrastructure.CatalogType", "CatalogType")
|
b.HasOne("Microsoft.eShopOnContainers.Services.Catalog.API.Model.CatalogType", "CatalogType")
|
||||||
.WithMany()
|
.WithMany()
|
||||||
.HasForeignKey("CatalogTypeId")
|
.HasForeignKey("CatalogTypeId")
|
||||||
.OnDelete(DeleteBehavior.Cascade);
|
.OnDelete(DeleteBehavior.Cascade);
|
@ -0,0 +1,24 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Catalog.API.Infrastructure.Exceptions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Exception type for app exceptions
|
||||||
|
/// </summary>
|
||||||
|
public class CatalogDomainException : Exception
|
||||||
|
{
|
||||||
|
public CatalogDomainException()
|
||||||
|
{ }
|
||||||
|
|
||||||
|
public CatalogDomainException(string message)
|
||||||
|
: base(message)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
public CatalogDomainException(string message, Exception innerException)
|
||||||
|
: base(message, innerException)
|
||||||
|
{ }
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,63 @@
|
|||||||
|
using Catalog.API.Infrastructure.ActionResults;
|
||||||
|
using Catalog.API.Infrastructure.Exceptions;
|
||||||
|
using Microsoft.AspNetCore.Hosting;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.AspNetCore.Mvc.Filters;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using System.Net;
|
||||||
|
|
||||||
|
namespace Catalog.API.Infrastructure.Filters
|
||||||
|
{
|
||||||
|
public class HttpGlobalExceptionFilter : IExceptionFilter
|
||||||
|
{
|
||||||
|
private readonly IHostingEnvironment env;
|
||||||
|
private readonly ILogger<HttpGlobalExceptionFilter> logger;
|
||||||
|
|
||||||
|
public HttpGlobalExceptionFilter(IHostingEnvironment env, ILogger<HttpGlobalExceptionFilter> logger)
|
||||||
|
{
|
||||||
|
this.env = env;
|
||||||
|
this.logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnException(ExceptionContext context)
|
||||||
|
{
|
||||||
|
logger.LogError(new EventId(context.Exception.HResult),
|
||||||
|
context.Exception,
|
||||||
|
context.Exception.Message);
|
||||||
|
|
||||||
|
if (context.Exception.GetType() == typeof(CatalogDomainException))
|
||||||
|
{
|
||||||
|
var json = new JsonErrorResponse
|
||||||
|
{
|
||||||
|
Messages = new[] { context.Exception.Message }
|
||||||
|
};
|
||||||
|
|
||||||
|
context.Result = new BadRequestObjectResult(json);
|
||||||
|
context.HttpContext.Response.StatusCode = (int)HttpStatusCode.BadRequest;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var json = new JsonErrorResponse
|
||||||
|
{
|
||||||
|
Messages = new[] { "An error ocurr.Try it again." }
|
||||||
|
};
|
||||||
|
|
||||||
|
if (env.IsDevelopment())
|
||||||
|
{
|
||||||
|
json.DeveloperMeesage = context.Exception;
|
||||||
|
}
|
||||||
|
|
||||||
|
context.Result = new InternalServerErrorObjectResult(json);
|
||||||
|
context.HttpContext.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
|
||||||
|
}
|
||||||
|
context.ExceptionHandled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private class JsonErrorResponse
|
||||||
|
{
|
||||||
|
public string[] Messages { get; set; }
|
||||||
|
|
||||||
|
public object DeveloperMeesage { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,43 @@
|
|||||||
|
using System;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF;
|
||||||
|
|
||||||
|
namespace Catalog.API.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(IntegrationEventLogContext))]
|
||||||
|
[Migration("20170322145434_IntegrationEventInitial")]
|
||||||
|
partial class IntegrationEventInitial
|
||||||
|
{
|
||||||
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
modelBuilder
|
||||||
|
.HasAnnotation("ProductVersion", "1.1.1")
|
||||||
|
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF.IntegrationEventLogEntry", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("EventId")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<string>("Content")
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreationTime");
|
||||||
|
|
||||||
|
b.Property<string>("EventTypeName")
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Property<int>("State");
|
||||||
|
|
||||||
|
b.Property<int>("TimesSent");
|
||||||
|
|
||||||
|
b.HasKey("EventId");
|
||||||
|
|
||||||
|
b.ToTable("IntegrationEventLog");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
namespace Catalog.API.Migrations
|
||||||
|
{
|
||||||
|
public partial class IntegrationEventInitial : Migration
|
||||||
|
{
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "IntegrationEventLog",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
EventId = table.Column<Guid>(nullable: false),
|
||||||
|
Content = table.Column<string>(nullable: false),
|
||||||
|
CreationTime = table.Column<DateTime>(nullable: false),
|
||||||
|
EventTypeName = table.Column<string>(nullable: false),
|
||||||
|
State = table.Column<int>(nullable: false),
|
||||||
|
TimesSent = table.Column<int>(nullable: false)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_IntegrationEventLog", x => x.EventId);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "IntegrationEventLog");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,42 @@
|
|||||||
|
using System;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF;
|
||||||
|
|
||||||
|
namespace Catalog.API.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(IntegrationEventLogContext))]
|
||||||
|
partial class IntegrationEventLogContextModelSnapshot : ModelSnapshot
|
||||||
|
{
|
||||||
|
protected override void BuildModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
modelBuilder
|
||||||
|
.HasAnnotation("ProductVersion", "1.1.1")
|
||||||
|
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF.IntegrationEventLogEntry", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("EventId")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<string>("Content")
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreationTime");
|
||||||
|
|
||||||
|
b.Property<string>("EventTypeName")
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Property<int>("State");
|
||||||
|
|
||||||
|
b.Property<int>("TimesSent");
|
||||||
|
|
||||||
|
b.HasKey("EventId");
|
||||||
|
|
||||||
|
b.ToTable("IntegrationEventLog");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,3 @@
|
|||||||
|
|
||||||
|
|
||||||
|
// To implement ProductPriceChangedEvent.cs here
|
@ -0,0 +1,26 @@
|
|||||||
|
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Microsoft.eShopOnContainers.Services.Catalog.API.IntegrationEvents.Events
|
||||||
|
{
|
||||||
|
// Integration Events notes:
|
||||||
|
// An Event is “something that has happened in the past”, therefore its name has to be
|
||||||
|
// An Integration Event is an event that can cause side effects to other microsrvices, Bounded-Contexts or external systems.
|
||||||
|
public class ProductPriceChangedIntegrationEvent : IntegrationEvent
|
||||||
|
{
|
||||||
|
public int ProductId { get; private set; }
|
||||||
|
|
||||||
|
public decimal NewPrice { get; private set; }
|
||||||
|
|
||||||
|
public decimal OldPrice { get; private set; }
|
||||||
|
|
||||||
|
public ProductPriceChangedIntegrationEvent(int productId, decimal newPrice, decimal oldPrice)
|
||||||
|
{
|
||||||
|
ProductId = productId;
|
||||||
|
NewPrice = newPrice;
|
||||||
|
OldPrice = oldPrice;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -10,6 +10,7 @@ namespace Microsoft.eShopOnContainers.Services.Catalog.API
|
|||||||
{
|
{
|
||||||
var host = new WebHostBuilder()
|
var host = new WebHostBuilder()
|
||||||
.UseKestrel()
|
.UseKestrel()
|
||||||
|
.UseHealthChecks("/hc")
|
||||||
.UseIISIntegration()
|
.UseIISIntegration()
|
||||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
.UseContentRoot(Directory.GetCurrentDirectory())
|
||||||
.UseWebRoot("Pics")
|
.UseWebRoot("Pics")
|
||||||
|
@ -1,21 +1,25 @@
|
|||||||
namespace Microsoft.eShopOnContainers.Services.Catalog.API
|
namespace Microsoft.eShopOnContainers.Services.Catalog.API
|
||||||
{
|
{
|
||||||
using AspNetCore.Http;
|
using global::Catalog.API.Infrastructure.Filters;
|
||||||
using Extensions.FileProviders;
|
|
||||||
using Microsoft.AspNetCore.Builder;
|
using Microsoft.AspNetCore.Builder;
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions;
|
||||||
|
using Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ;
|
||||||
|
using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF;
|
||||||
|
using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF.Services;
|
||||||
using Microsoft.eShopOnContainers.Services.Catalog.API.Infrastructure;
|
using Microsoft.eShopOnContainers.Services.Catalog.API.Infrastructure;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.HealthChecks;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
using System;
|
using System;
|
||||||
using System.Data.SqlClient;
|
using System.Data.SqlClient;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Data.Common;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
public class Startup
|
public class Startup
|
||||||
{
|
{
|
||||||
@ -40,12 +44,30 @@
|
|||||||
|
|
||||||
public void ConfigureServices(IServiceCollection services)
|
public void ConfigureServices(IServiceCollection services)
|
||||||
{
|
{
|
||||||
services.AddDbContext<CatalogContext>(c =>
|
// Add framework services.
|
||||||
|
|
||||||
|
services.AddHealthChecks(checks =>
|
||||||
{
|
{
|
||||||
c.UseSqlServer(Configuration["ConnectionString"]);
|
checks.AddUrlCheck(Configuration["ExternalCatalogBaseUrl"]);
|
||||||
|
});
|
||||||
|
|
||||||
|
services.AddMvc(options =>
|
||||||
|
{
|
||||||
|
options.Filters.Add(typeof(HttpGlobalExceptionFilter));
|
||||||
|
}).AddControllersAsServices();
|
||||||
|
|
||||||
|
services.AddDbContext<CatalogContext>(options =>
|
||||||
|
{
|
||||||
|
options.UseSqlServer(Configuration["ConnectionString"],
|
||||||
|
sqlServerOptionsAction: sqlOptions =>
|
||||||
|
{
|
||||||
|
sqlOptions.MigrationsAssembly(typeof(Startup).GetTypeInfo().Assembly.GetName().Name);
|
||||||
|
//Configuring Connection Resiliency: https://docs.microsoft.com/en-us/ef/core/miscellaneous/connection-resiliency
|
||||||
|
sqlOptions.EnableRetryOnFailure(maxRetryCount: 5, maxRetryDelay: TimeSpan.FromSeconds(30), errorNumbersToAdd: null);
|
||||||
|
});
|
||||||
// Changing default behavior when client evaluation occurs to throw.
|
// Changing default behavior when client evaluation occurs to throw.
|
||||||
// Default in EF Core would be to log a warning when client evaluation is performed.
|
// Default in EF Core would be to log a warning when client evaluation is performed.
|
||||||
c.ConfigureWarnings(warnings => warnings.Throw(RelationalEventId.QueryClientEvaluationWarning));
|
options.ConfigureWarnings(warnings => warnings.Throw(RelationalEventId.QueryClientEvaluationWarning));
|
||||||
//Check Client vs. Server evaluation: https://docs.microsoft.com/en-us/ef/core/querying/client-eval
|
//Check Client vs. Server evaluation: https://docs.microsoft.com/en-us/ef/core/querying/client-eval
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -74,18 +96,18 @@
|
|||||||
.AllowCredentials());
|
.AllowCredentials());
|
||||||
});
|
});
|
||||||
|
|
||||||
services.AddMvc();
|
services.AddTransient<Func<DbConnection, IIntegrationEventLogService>>(
|
||||||
|
sp => (DbConnection c) => new IntegrationEventLogService(c));
|
||||||
|
|
||||||
|
var serviceProvider = services.BuildServiceProvider();
|
||||||
|
var configuration = serviceProvider.GetRequiredService<IOptionsSnapshot<Settings>>().Value;
|
||||||
|
services.AddSingleton<IEventBus>(new EventBusRabbitMQ(configuration.EventBusConnection));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
|
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
|
||||||
{
|
{
|
||||||
//Configure logs
|
//Configure logs
|
||||||
|
|
||||||
if (env.IsDevelopment())
|
|
||||||
{
|
|
||||||
app.UseDeveloperExceptionPage();
|
|
||||||
}
|
|
||||||
|
|
||||||
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
|
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
|
||||||
loggerFactory.AddDebug();
|
loggerFactory.AddDebug();
|
||||||
|
|
||||||
@ -102,7 +124,13 @@
|
|||||||
WaitForSqlAvailability(context, loggerFactory);
|
WaitForSqlAvailability(context, loggerFactory);
|
||||||
//Seed Data
|
//Seed Data
|
||||||
CatalogContextSeed.SeedAsync(app, loggerFactory)
|
CatalogContextSeed.SeedAsync(app, loggerFactory)
|
||||||
.Wait();
|
.Wait();
|
||||||
|
|
||||||
|
var integrationEventLogContext = new IntegrationEventLogContext(
|
||||||
|
new DbContextOptionsBuilder<IntegrationEventLogContext>()
|
||||||
|
.UseSqlServer(Configuration["ConnectionString"], b => b.MigrationsAssembly("Catalog.API"))
|
||||||
|
.Options);
|
||||||
|
integrationEventLogContext.Database.Migrate();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void WaitForSqlAvailability(CatalogContext ctx, ILoggerFactory loggerFactory, int? retry = 0)
|
private void WaitForSqlAvailability(CatalogContext ctx, ILoggerFactory loggerFactory, int? retry = 0)
|
||||||
@ -125,6 +153,8 @@
|
|||||||
finally {
|
finally {
|
||||||
ctx.Database.CloseConnection();
|
ctx.Database.CloseConnection();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,5 +9,6 @@ namespace Microsoft.eShopOnContainers.Services.Catalog.API
|
|||||||
public class Settings
|
public class Settings
|
||||||
{
|
{
|
||||||
public string ExternalCatalogBaseUrl {get;set;}
|
public string ExternalCatalogBaseUrl {get;set;}
|
||||||
|
public string EventBusConnection { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
8
src/Services/Identity/Identity.API/Dockerfile.nanowin
Normal file
8
src/Services/Identity/Identity.API/Dockerfile.nanowin
Normal 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", "Identity.API.dll"]
|
@ -57,6 +57,12 @@
|
|||||||
<DotNetCliToolReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Tools" Version="1.0.0-msbuild3-final" />
|
<DotNetCliToolReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Tools" Version="1.0.0-msbuild3-final" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\..\BuildingBlocks\HealthChecks\src\Microsoft.AspNetCore.HealthChecks\Microsoft.AspNetCore.HealthChecks.csproj" />
|
||||||
|
<ProjectReference Include="..\..\..\BuildingBlocks\HealthChecks\src\Microsoft.Extensions.HealthChecks.Data\Microsoft.Extensions.HealthChecks.Data.csproj" />
|
||||||
|
<ProjectReference Include="..\..\..\BuildingBlocks\HealthChecks\src\Microsoft.Extensions.HealthChecks\Microsoft.Extensions.HealthChecks.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Update="Dockerfile">
|
<None Update="Dockerfile">
|
||||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
@ -9,6 +9,7 @@ namespace eShopOnContainers.Identity
|
|||||||
{
|
{
|
||||||
var host = new WebHostBuilder()
|
var host = new WebHostBuilder()
|
||||||
.UseKestrel()
|
.UseKestrel()
|
||||||
|
.UseHealthChecks("/hc")
|
||||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
.UseContentRoot(Directory.GetCurrentDirectory())
|
||||||
.UseIISIntegration()
|
.UseIISIntegration()
|
||||||
.UseStartup<Startup>()
|
.UseStartup<Startup>()
|
||||||
|
@ -17,6 +17,7 @@ using IdentityServer4.Services;
|
|||||||
using System.Threading;
|
using System.Threading;
|
||||||
using Microsoft.eShopOnContainers.Services.Catalog.API.Infrastructure;
|
using Microsoft.eShopOnContainers.Services.Catalog.API.Infrastructure;
|
||||||
using Microsoft.AspNetCore.Identity;
|
using Microsoft.AspNetCore.Identity;
|
||||||
|
using Microsoft.Extensions.HealthChecks;
|
||||||
|
|
||||||
namespace eShopOnContainers.Identity
|
namespace eShopOnContainers.Identity
|
||||||
{
|
{
|
||||||
@ -43,7 +44,8 @@ namespace eShopOnContainers.Identity
|
|||||||
|
|
||||||
// This method gets called by the runtime. Use this method to add services to the container.
|
// This method gets called by the runtime. Use this method to add services to the container.
|
||||||
public void ConfigureServices(IServiceCollection services)
|
public void ConfigureServices(IServiceCollection services)
|
||||||
{
|
{
|
||||||
|
|
||||||
// Add framework services.
|
// Add framework services.
|
||||||
services.AddDbContext<ApplicationDbContext>(options =>
|
services.AddDbContext<ApplicationDbContext>(options =>
|
||||||
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
|
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
|
||||||
@ -56,6 +58,11 @@ namespace eShopOnContainers.Identity
|
|||||||
|
|
||||||
services.AddMvc();
|
services.AddMvc();
|
||||||
|
|
||||||
|
services.AddHealthChecks(checks =>
|
||||||
|
{
|
||||||
|
checks.AddSqlCheck("Identity_Db", Configuration.GetConnectionString("DefaultConnection"));
|
||||||
|
});
|
||||||
|
|
||||||
services.AddTransient<IEmailSender, AuthMessageSender>();
|
services.AddTransient<IEmailSender, AuthMessageSender>();
|
||||||
services.AddTransient<ISmsSender, AuthMessageSender>();
|
services.AddTransient<ISmsSender, AuthMessageSender>();
|
||||||
services.AddTransient<ILoginService<ApplicationUser>, EFLoginService>();
|
services.AddTransient<ILoginService<ApplicationUser>, EFLoginService>();
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user