Merge branch 'dev' into IntegrationEventLogService-refactor
# Conflicts: # src/Services/Catalog/Catalog.API/Controllers/CatalogController.cs # src/Services/Catalog/Catalog.API/Startup.cs
This commit is contained in:
commit
395768d574
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, []}]}].
|
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
|
||||||
|
|
@ -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:
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
FROM microsoft/dotnet:1.1-runtime-nanoserver
|
FROM microsoft/dotnet:1.1-runtime-nanoserver
|
||||||
|
SHELL ["powershell"]
|
||||||
ARG source
|
ARG source
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
RUN set-itemproperty -path 'HKLM:\SYSTEM\CurrentControlSet\Services\Dnscache\Parameters' -Name ServerPriorityTimeLimit -Value 0 -Type DWord
|
RUN set-itemproperty -path 'HKLM:\SYSTEM\CurrentControlSet\Services\Dnscache\Parameters' -Name ServerPriorityTimeLimit -Value 0 -Type DWord
|
||||||
|
@ -20,11 +20,11 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API.IntegrationEvents.Even
|
|||||||
foreach (var id in userIds)
|
foreach (var id in userIds)
|
||||||
{
|
{
|
||||||
var basket = await _repository.GetBasket(id);
|
var basket = await _repository.GetBasket(id);
|
||||||
await UpdateBasket(@event.ProductId, @event.NewPrice, basket);
|
await UpdatePriceInBasketItems(@event.ProductId, @event.NewPrice, basket);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task UpdateBasket(int productId, decimal newPrice, CustomerBasket basket)
|
private async Task UpdatePriceInBasketItems(int productId, decimal newPrice, CustomerBasket basket)
|
||||||
{
|
{
|
||||||
var itemsToUpdate = basket?.Items?.Where(x => int.Parse(x.ProductId) == productId).ToList();
|
var itemsToUpdate = basket?.Items?.Where(x => int.Parse(x.ProductId) == productId).ToList();
|
||||||
if (itemsToUpdate != null)
|
if (itemsToUpdate != null)
|
||||||
|
@ -14,6 +14,7 @@ using System.Collections.Generic;
|
|||||||
using System.Data.Common;
|
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
|
||||||
{
|
{
|
||||||
@ -137,40 +138,58 @@ namespace Microsoft.eShopOnContainers.Services.Catalog.API.Controllers
|
|||||||
return Ok(items);
|
return Ok(items);
|
||||||
}
|
}
|
||||||
|
|
||||||
//POST api/v1/[controller]/edit
|
//POST api/v1/[controller]/update
|
||||||
[Route("edit")]
|
[Route("update")]
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
public async Task<IActionResult> EditProduct([FromBody]CatalogItem product)
|
public async Task<IActionResult> UpdateProduct([FromBody]CatalogItem productToUpdate)
|
||||||
{
|
{
|
||||||
var item = await _catalogContext.CatalogItems.SingleOrDefaultAsync(i => i.Id == product.Id);
|
var catalogItem = await _catalogContext.CatalogItems.SingleOrDefaultAsync(i => i.Id == productToUpdate.Id);
|
||||||
|
if (catalogItem == null) return NotFound();
|
||||||
|
|
||||||
if (item == null)
|
bool raiseProductPriceChangedEvent = false;
|
||||||
|
IntegrationEvent priceChangedEvent = null;
|
||||||
|
|
||||||
|
if (catalogItem.Price != productToUpdate.Price) raiseProductPriceChangedEvent = true;
|
||||||
|
|
||||||
|
if (raiseProductPriceChangedEvent) // Create event if price has changed
|
||||||
{
|
{
|
||||||
return NotFound();
|
var oldPrice = catalogItem.Price;
|
||||||
|
priceChangedEvent = new ProductPriceChangedIntegrationEvent(catalogItem.Id, productToUpdate.Price, oldPrice);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (item.Price != product.Price)
|
//Update current product
|
||||||
{
|
catalogItem = productToUpdate;
|
||||||
var oldPrice = item.Price;
|
|
||||||
item.Price = product.Price;
|
|
||||||
var @event = new ProductPriceChangedIntegrationEvent(item.Id, item.Price, oldPrice);
|
|
||||||
var eventLogService = _integrationEventLogServiceFactory(_catalogContext.Database.GetDbConnection());
|
|
||||||
|
|
||||||
|
//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())
|
using (var transaction = _catalogContext.Database.BeginTransaction())
|
||||||
{
|
{
|
||||||
_catalogContext.CatalogItems.Update(item);
|
_catalogContext.CatalogItems.Update(catalogItem);
|
||||||
await _catalogContext.SaveChangesAsync();
|
await _catalogContext.SaveChangesAsync();
|
||||||
|
|
||||||
|
//Save to EventLog only if product price changed
|
||||||
|
if (raiseProductPriceChangedEvent)
|
||||||
|
{
|
||||||
|
|
||||||
await eventLogService.SaveEventAsync(@event, _catalogContext.Database.CurrentTransaction.GetDbTransaction());
|
await eventLogService.SaveEventAsync(priceChangedEvent, _catalogContext.Database.CurrentTransaction.GetDbTransaction());
|
||||||
|
}
|
||||||
|
|
||||||
transaction.Commit();
|
transaction.Commit();
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
_eventBus.Publish(@event);
|
|
||||||
|
|
||||||
await eventLogService.MarkEventAsPublishedAsync(@event);
|
//Publish to Event Bus only if product price changed
|
||||||
}
|
if (raiseProductPriceChangedEvent)
|
||||||
|
{
|
||||||
|
_eventBus.Publish(priceChangedEvent);
|
||||||
|
await eventLogService.MarkEventAsPublishedAsync(priceChangedEvent);
|
||||||
|
}
|
||||||
|
|
||||||
return Ok();
|
return Ok();
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
FROM microsoft/dotnet:1.1-runtime-nanoserver
|
FROM microsoft/dotnet:1.1-runtime-nanoserver
|
||||||
|
SHELL ["powershell"]
|
||||||
ARG source
|
ARG source
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
RUN set-itemproperty -path 'HKLM:\SYSTEM\CurrentControlSet\Services\Dnscache\Parameters' -Name ServerPriorityTimeLimit -Value 0 -Type DWord
|
RUN set-itemproperty -path 'HKLM:\SYSTEM\CurrentControlSet\Services\Dnscache\Parameters' -Name ServerPriorityTimeLimit -Value 0 -Type DWord
|
||||||
|
@ -84,14 +84,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" },
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
using System;
|
using System;
|
||||||
using System.Data.Common;
|
using System.Data.Common;
|
||||||
|
using System.Data.SqlClient;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
|
||||||
public class Startup
|
public class Startup
|
||||||
@ -40,15 +41,37 @@
|
|||||||
|
|
||||||
public void ConfigureServices(IServiceCollection services)
|
public void ConfigureServices(IServiceCollection services)
|
||||||
{
|
{
|
||||||
services.AddDbContext<CatalogContext>(c =>
|
//Using the same SqlConnection for both DbContexts (CatalogContext and IntegrationEventLogContext)
|
||||||
|
//var sqlConnection = new SqlConnection(Configuration["ConnectionString"]);
|
||||||
|
|
||||||
|
services.AddDbContext<CatalogContext>(options =>
|
||||||
{
|
{
|
||||||
c.UseSqlServer(Configuration["ConnectionString"]);
|
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
|
||||||
});
|
});
|
||||||
|
|
||||||
|
//services.AddDbContext<IntegrationEventLogContext>(options =>
|
||||||
|
//{
|
||||||
|
// options.UseSqlServer(sqlConnection,
|
||||||
|
// 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);
|
||||||
|
// });
|
||||||
|
|
||||||
|
// options.ConfigureWarnings(warnings => warnings.Throw(RelationalEventId.QueryClientEvaluationWarning));
|
||||||
|
//});
|
||||||
|
|
||||||
services.Configure<Settings>(Configuration);
|
services.Configure<Settings>(Configuration);
|
||||||
|
|
||||||
// Add framework services.
|
// Add framework services.
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
FROM microsoft/dotnet:1.1-runtime-nanoserver
|
FROM microsoft/dotnet:1.1-runtime-nanoserver
|
||||||
|
SHELL ["powershell"]
|
||||||
ARG source
|
ARG source
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
RUN set-itemproperty -path 'HKLM:\SYSTEM\CurrentControlSet\Services\Dnscache\Parameters' -Name ServerPriorityTimeLimit -Value 0 -Type DWord
|
RUN set-itemproperty -path 'HKLM:\SYSTEM\CurrentControlSet\Services\Dnscache\Parameters' -Name ServerPriorityTimeLimit -Value 0 -Type DWord
|
||||||
|
@ -45,6 +45,15 @@
|
|||||||
<p>
|
<p>
|
||||||
<a asp-action="Register" asp-route-returnurl="@ViewData["ReturnUrl"]" class="text">Register as a new user?</a>
|
<a asp-action="Register" asp-route-returnurl="@ViewData["ReturnUrl"]" class="text">Register as a new user?</a>
|
||||||
</p>
|
</p>
|
||||||
|
<p>
|
||||||
|
Note that for demo purposes you don't need to register and can login with these credentials:
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
User: <b>demouser@microsoft.com</b>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Password: <b>Pass@word1</b>
|
||||||
|
</p>
|
||||||
</form>
|
</form>
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
FROM microsoft/dotnet:1.1-runtime-nanoserver
|
FROM microsoft/dotnet:1.1-runtime-nanoserver
|
||||||
|
SHELL ["powershell"]
|
||||||
ARG source
|
ARG source
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
RUN set-itemproperty -path 'HKLM:\SYSTEM\CurrentControlSet\Services\Dnscache\Parameters' -Name ServerPriorityTimeLimit -Value 0 -Type DWord
|
RUN set-itemproperty -path 'HKLM:\SYSTEM\CurrentControlSet\Services\Dnscache\Parameters' -Name ServerPriorityTimeLimit -Value 0 -Type DWord
|
||||||
|
@ -52,10 +52,14 @@
|
|||||||
services.AddEntityFrameworkSqlServer()
|
services.AddEntityFrameworkSqlServer()
|
||||||
.AddDbContext<OrderingContext>(options =>
|
.AddDbContext<OrderingContext>(options =>
|
||||||
{
|
{
|
||||||
options.UseSqlServer(Configuration["ConnectionString"],
|
options.UseSqlServer(Configuration["ConnectionString"],
|
||||||
sqlop => sqlop.MigrationsAssembly(typeof(Startup).GetTypeInfo().Assembly.GetName().Name));
|
sqlServerOptionsAction: sqlOptions =>
|
||||||
|
{
|
||||||
|
sqlOptions.MigrationsAssembly(typeof(Startup).GetTypeInfo().Assembly.GetName().Name);
|
||||||
|
sqlOptions.EnableRetryOnFailure(maxRetryCount: 5, maxRetryDelay: TimeSpan.FromSeconds(30), errorNumbersToAdd: null);
|
||||||
|
});
|
||||||
},
|
},
|
||||||
ServiceLifetime.Scoped //DbContext is shared across the HTTP request scope (graph of objects started in the HTTP request)
|
ServiceLifetime.Scoped //Showing explicitly that the DbContext is shared across the HTTP request scope (graph of objects started in the HTTP request)
|
||||||
);
|
);
|
||||||
|
|
||||||
services.AddSwaggerGen();
|
services.AddSwaggerGen();
|
||||||
|
@ -246,7 +246,8 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Infrastructure
|
|||||||
await _mediator.DispatchDomainEventsAsync(this);
|
await _mediator.DispatchDomainEventsAsync(this);
|
||||||
|
|
||||||
|
|
||||||
// After executing this line all the changes performed thought the DbContext will be commited
|
// After executing this line all the changes (from the Command Handler and Domain Event Handlers)
|
||||||
|
// performed thought the DbContext will be commited
|
||||||
var result = await base.SaveChangesAsync();
|
var result = await base.SaveChangesAsync();
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
FROM microsoft/dotnet:1.1-runtime-nanoserver
|
FROM microsoft/dotnet:1.1-runtime-nanoserver
|
||||||
|
SHELL ["powershell"]
|
||||||
ARG source
|
ARG source
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
RUN set-itemproperty -path 'HKLM:\SYSTEM\CurrentControlSet\Services\Dnscache\Parameters' -Name ServerPriorityTimeLimit -Value 0 -Type DWord
|
RUN set-itemproperty -path 'HKLM:\SYSTEM\CurrentControlSet\Services\Dnscache\Parameters' -Name ServerPriorityTimeLimit -Value 0 -Type DWord
|
||||||
|
@ -44,7 +44,16 @@
|
|||||||
<p>
|
<p>
|
||||||
<a asp-action="Register" asp-route-returnurl="@ViewData["ReturnUrl"]" class="text">Register as a new user?</a>
|
<a asp-action="Register" asp-route-returnurl="@ViewData["ReturnUrl"]" class="text">Register as a new user?</a>
|
||||||
</p>
|
</p>
|
||||||
</form>
|
<p>
|
||||||
|
Note that for demo purposes you don't need to register and can login with these credentials:
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
User: <b>demouser@microsoft.com</b>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Password: <b>Pass@word1</b>
|
||||||
|
</p>
|
||||||
|
</form>
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -38,7 +38,7 @@
|
|||||||
<div class="esh-basket-items--border row">
|
<div class="esh-basket-items--border row">
|
||||||
@if (item.OldUnitPrice != 0)
|
@if (item.OldUnitPrice != 0)
|
||||||
{
|
{
|
||||||
<div class="alert alert-warning esh-basket-margin12" role="alert"> The price of the item has changed.Old price was @item.OldUnitPrice $</div>
|
<div class="alert alert-warning esh-basket-margin12" role="alert"> Note that the price of this article changed in our Catalog. The old price when you originally added it to the basket was @item.OldUnitPrice $</div>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
<br/>
|
<br/>
|
||||||
|
2
src/Web/WebMVC/wwwroot/css/site.min.css
vendored
2
src/Web/WebMVC/wwwroot/css/site.min.css
vendored
File diff suppressed because one or more lines are too long
@ -29,7 +29,7 @@
|
|||||||
</article>
|
</article>
|
||||||
<br/>
|
<br/>
|
||||||
<div class="esh-basket-items-margin-left1 row">
|
<div class="esh-basket-items-margin-left1 row">
|
||||||
<div class="alert alert-warning" role="alert" *ngIf="item.oldUnitPrice > 0"> The price of the item has changed.Old price was {{item.oldUnitPrice}} $</div>
|
<div class="alert alert-warning" role="alert" *ngIf="item.oldUnitPrice > 0"> Note that the price of this article changed in our Catalog. The old price when you originally added it to the basket was {{item.oldUnitPrice}} $</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
FROM microsoft/dotnet:1.1-runtime-nanoserver
|
FROM microsoft/dotnet:1.1-runtime-nanoserver
|
||||||
|
SHELL ["powershell"]
|
||||||
ARG source
|
ARG source
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
RUN set-itemproperty -path 'HKLM:\SYSTEM\CurrentControlSet\Services\Dnscache\Parameters' -Name ServerPriorityTimeLimit -Value 0 -Type DWord
|
RUN set-itemproperty -path 'HKLM:\SYSTEM\CurrentControlSet\Services\Dnscache\Parameters' -Name ServerPriorityTimeLimit -Value 0 -Type DWord
|
||||||
|
@ -0,0 +1,18 @@
|
|||||||
|
using Microsoft.AspNetCore.TestHost;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace FunctionalTests.Extensions
|
||||||
|
{
|
||||||
|
static class HttpClientExtensions
|
||||||
|
{
|
||||||
|
public static HttpClient CreateIdempotentClient(this TestServer server)
|
||||||
|
{
|
||||||
|
var client = server.CreateClient();
|
||||||
|
client.DefaultRequestHeaders.Add("x-requestid", Guid.NewGuid().ToString());
|
||||||
|
return client;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -34,7 +34,7 @@ namespace FunctionalTests.Services.Catalog
|
|||||||
|
|
||||||
public static class Post
|
public static class Post
|
||||||
{
|
{
|
||||||
public static string UpdateCatalogProduct = "api/v1/catalog/edit";
|
public static string UpdateCatalogProduct = "api/v1/catalog/update";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands;
|
using FunctionalTests.Extensions;
|
||||||
|
using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands;
|
||||||
using Microsoft.eShopOnContainers.WebMVC.ViewModels;
|
using Microsoft.eShopOnContainers.WebMVC.ViewModels;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using System;
|
using System;
|
||||||
@ -19,7 +20,7 @@ namespace FunctionalTests.Services.Ordering
|
|||||||
{
|
{
|
||||||
using (var server = CreateServer())
|
using (var server = CreateServer())
|
||||||
{
|
{
|
||||||
var client = server.CreateClient();
|
var client = server.CreateIdempotentClient();
|
||||||
|
|
||||||
// GIVEN an order is created
|
// GIVEN an order is created
|
||||||
await client.PostAsync(Post.AddNewOrder, new StringContent(BuildOrder(), UTF8Encoding.UTF8, "application/json"));
|
await client.PostAsync(Post.AddNewOrder, new StringContent(BuildOrder(), UTF8Encoding.UTF8, "application/json"));
|
||||||
@ -62,7 +63,7 @@ namespace FunctionalTests.Services.Ordering
|
|||||||
order.AddOrderItem(new OrderItemDTO()
|
order.AddOrderItem(new OrderItemDTO()
|
||||||
{
|
{
|
||||||
ProductId = 1,
|
ProductId = 1,
|
||||||
Discount = 12M,
|
Discount = 8M,
|
||||||
UnitPrice = 10,
|
UnitPrice = 10,
|
||||||
Units = 1,
|
Units = 1,
|
||||||
ProductName = "Some name"
|
ProductName = "Some name"
|
||||||
|
@ -0,0 +1,18 @@
|
|||||||
|
using Microsoft.AspNetCore.TestHost;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace IntegrationTests.Services.Extensions
|
||||||
|
{
|
||||||
|
static class HttpClientExtensions
|
||||||
|
{
|
||||||
|
public static HttpClient CreateIdempotentClient(this TestServer server)
|
||||||
|
{
|
||||||
|
var client = server.CreateClient();
|
||||||
|
client.DefaultRequestHeaders.Add("x-requestid", Guid.NewGuid().ToString());
|
||||||
|
return client;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,7 @@
|
|||||||
namespace IntegrationTests.Services.Ordering
|
namespace IntegrationTests.Services.Ordering
|
||||||
{
|
{
|
||||||
|
using IntegrationTests.Services.Extensions;
|
||||||
|
using Microsoft.AspNetCore.TestHost;
|
||||||
using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands;
|
using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using System;
|
using System;
|
||||||
@ -28,9 +30,9 @@
|
|||||||
public async Task AddNewOrder_add_new_order_and_response_ok_status_code()
|
public async Task AddNewOrder_add_new_order_and_response_ok_status_code()
|
||||||
{
|
{
|
||||||
using (var server = CreateServer())
|
using (var server = CreateServer())
|
||||||
{
|
{
|
||||||
var content = new StringContent(BuildOrder(), UTF8Encoding.UTF8, "application/json");
|
var content = new StringContent(BuildOrder(), UTF8Encoding.UTF8, "application/json");
|
||||||
var response = await server.CreateClient()
|
var response = await server.CreateIdempotentClient()
|
||||||
.PostAsync(Post.AddNewOrder, content);
|
.PostAsync(Post.AddNewOrder, content);
|
||||||
|
|
||||||
response.EnsureSuccessStatusCode();
|
response.EnsureSuccessStatusCode();
|
||||||
@ -44,7 +46,7 @@
|
|||||||
{
|
{
|
||||||
var content = new StringContent(BuildOrderWithInvalidExperationTime(), UTF8Encoding.UTF8, "application/json");
|
var content = new StringContent(BuildOrderWithInvalidExperationTime(), UTF8Encoding.UTF8, "application/json");
|
||||||
|
|
||||||
var response = await server.CreateClient()
|
var response = await server.CreateIdempotentClient()
|
||||||
.PostAsync(Post.AddNewOrder, content);
|
.PostAsync(Post.AddNewOrder, content);
|
||||||
|
|
||||||
Assert.True(response.StatusCode == System.Net.HttpStatusCode.BadRequest);
|
Assert.True(response.StatusCode == System.Net.HttpStatusCode.BadRequest);
|
||||||
@ -102,5 +104,5 @@
|
|||||||
|
|
||||||
return JsonConvert.SerializeObject(order);
|
return JsonConvert.SerializeObject(order);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user