@ -1,160 +0,0 @@ | |||
######################################################################################################### | |||
# This "expanded Script" can be used when debugging issues when building the .NET Core bits | |||
# as it is easier to follow and debug than when using a loop (like in the optimized build-bits.ps1) | |||
######################################################################################################### | |||
Param([string] $rootPath) | |||
$scriptPath = Split-Path $script:MyInvocation.MyCommand.Path | |||
Write-Host "Current script directory is $scriptPath" -ForegroundColor Yellow | |||
if ([string]::IsNullOrEmpty($rootPath)) { | |||
$rootPath = "$scriptPath\.." | |||
} | |||
Write-Host "Root path used is $rootPath" -ForegroundColor Yellow | |||
# *** WebMVC paths *** | |||
$webMVCPath = $rootPath + "\src\Web\WebMVC" | |||
$webMVCPathToProject = $webMVCPath + "\WebMVC.csproj" | |||
Write-Host "webMVCPathToProject is $webMVCPathToProject" -ForegroundColor Yellow | |||
$webMVCPathToPub = $webMVCPath + "\obj\Docker\publish" | |||
Write-Host "webMVCPathToPub is $webMVCPathToPub" -ForegroundColor Yellow | |||
# *** WebSPA paths *** | |||
$webSPAPath = $rootPath + "\src\Web\WebSPA" | |||
$webSPAPathToProject = $webSPAPath + "\WebSPA.csproj" | |||
Write-Host "webSPAPathToProject is $webSPAPathToProject" -ForegroundColor Yellow | |||
$webSPAPathToPub = $webSPAPath + "\obj\Docker\publish" | |||
Write-Host "webSPAPathToPub is $webSPAPathToPub" -ForegroundColor Yellow | |||
# *** IdentitySvc paths *** | |||
$identitySvcPath = $rootPath + "\src\Services\Identity\Identity.API" | |||
$identitySvcToProject = $identitySvcPath + "\Identity.API.csproj" | |||
Write-Host "identitySvcToProject is $identitySvcToProject" -ForegroundColor Yellow | |||
$identitySvcPathToPub = $identitySvcPath + "\obj\Docker\publish" | |||
Write-Host "identitySvcPathToPub is $identitySvcPathToPub" -ForegroundColor Yellow | |||
# *** Catalog paths *** | |||
$catalogPath = $rootPath + "\src\Services\Catalog\Catalog.API" | |||
$catalogPathToProject = $catalogPath + "\Catalog.API.csproj" | |||
Write-Host "catalogPathToProject is $catalogPathToProject" -ForegroundColor Yellow | |||
$catalogPathToPub = $catalogPath + "\obj\Docker\publish" | |||
Write-Host "catalogPathToPub is $catalogPathToPub" -ForegroundColor Yellow | |||
# *** Ordering paths *** | |||
$orderingPath = $rootPath + "\src\Services\Ordering\Ordering.API" | |||
$orderingPathToProject = $orderingPath + "\Ordering.API.csproj" | |||
Write-Host "orderingPathToProject is $orderingPathToProject" -ForegroundColor Yellow | |||
$orderingPathToPub = $orderingPath + "\obj\Docker\publish" | |||
Write-Host "orderingPathToPub is $orderingPathToPub" -ForegroundColor Yellow | |||
# *** Basket paths *** | |||
$basketPath = $rootPath + "\src\Services\Basket\Basket.API" | |||
$basketPathToProject = $basketPath + "\Basket.API.csproj" | |||
Write-Host "basketPathToProject is $basketPathToProject" -ForegroundColor Yellow | |||
$basketPathToPub = $basketPath + "\obj\Docker\publish" | |||
Write-Host "basketPathToPub is $basketPathToPub" -ForegroundColor Yellow | |||
######################################################################################## | |||
# Delete old eShop dotnet publish bits | |||
######################################################################################## | |||
# Write-Host "Deleting previous dotnet publish bits from all projects" -ForegroundColor Blue | |||
remove-item -path $WebMVCPathToPub -Force -Recurse -ErrorAction SilentlyContinue | |||
remove-item -path $webSPAPathToPub -Force -Recurse -ErrorAction SilentlyContinue | |||
remove-item -path $identitySvcPathToPub -Force -Recurse -ErrorAction SilentlyContinue | |||
remove-item -path $catalogPathToPub -Force -Recurse -ErrorAction SilentlyContinue | |||
remove-item -path $orderingPathToPub -Force -Recurse -ErrorAction SilentlyContinue | |||
remove-item -path $basketPathToPub -Force -Recurse -ErrorAction SilentlyContinue | |||
######################################################################################## | |||
# Building DotNet bits | |||
######################################################################################## | |||
# WebMVC: Build dotnet bits | |||
Write-Host "WebMVC: Restore Dependencies, dotnet build and dotnet publish" -ForegroundColor Blue | |||
dotnet restore $WebMVCPathToProject | |||
dotnet build $WebMVCPathToProject | |||
dotnet publish $WebMVCPathToProject -o $WebMVCPathToPub | |||
# WebSPA: Build dotnet bits | |||
Write-Host "WebSPA: Installing npm dependencies" | |||
#TEMP COMMENT--- Start-Process -WorkingDirectory $webSPAPath -NoNewWindow -Wait npm i | |||
Write-Host "WebSPA: Restore Dependencies, dotnet build and dotnet publish" -ForegroundColor Blue | |||
dotnet restore $webSPAPathToProject | |||
dotnet build $webSPAPathToProject | |||
dotnet publish $webSPAPathToProject -o $webSPAPathToPub | |||
# Identity Service: Build dotnet bits | |||
Write-Host "Identity Service: Restore Dependencies, dotnet build and dotnet publish" -ForegroundColor Blue | |||
dotnet restore $identitySvcToProject | |||
dotnet build $identitySvcToProject | |||
dotnet publish $identitySvcToProject -o $identitySvcPathToPub | |||
# Catalog Service: Build dotnet bits | |||
Write-Host "Catalog Service: Restore Dependencies, dotnet build and dotnet publish" -ForegroundColor Blue | |||
dotnet restore $catalogPathToProject | |||
dotnet build $catalogPathToProject | |||
dotnet publish $catalogPathToProject -o $catalogPathToPub | |||
# Ordering Service: Build dotnet bits | |||
Write-Host "Ordering Service: Restore Dependencies, dotnet build and dotnet publish" -ForegroundColor Blue | |||
dotnet restore $orderingPathToProject | |||
dotnet build $orderingPathToProject | |||
dotnet publish $orderingPathToProject -o $orderingPathToPub | |||
# Basket Service: Build dotnet bits | |||
Write-Host "Basket Service: Restore Dependencies, dotnet build and dotnet publish" -ForegroundColor Blue | |||
dotnet restore $basketPathToProject | |||
dotnet build $basketPathToProject | |||
dotnet publish $basketPathToProject -o $basketPathToPub | |||
######################################################################################## | |||
# Delete old eShop Docker images | |||
######################################################################################## | |||
$imagesToDelete = docker images --filter=reference="eshop/*" -q | |||
If (-Not $imagesToDelete) {Write-Host "Not deleting eShop images as there are no eShop images in the current local Docker repo."} | |||
Else | |||
{ | |||
# Delete all containers | |||
Write-Host "Deleting all containers in local Docker Host" | |||
docker rm $(docker ps -a -q) -f | |||
# Delete all eshop images | |||
Write-Host "Deleting eShop images in local Docker repo" | |||
Write-Host $imagesToDelete | |||
docker rmi $(docker images --filter=reference="eshop/*" -q) -f | |||
} | |||
######################################################################################## | |||
# Build new eShop images | |||
######################################################################################## | |||
# WE DON'T NEED DOCKER BUILD AS WE CAN RUN "DOCKER-COMPOSE BUILD" OR "DOCKER-COMPOSE UP" AND IT WILL BUILD ALL THE IMAGES IN THE .YML FOR US | |||
#*** build docker images *** | |||
# docker build -t eshop/web $webPathToPub | |||
# docker build -t eshop/catalog.api $catalogPathToPub | |||
# docker build -t eshop/ordering.api $orderingApiPathToPub | |||
# docker build -t eshop/basket.api $basketPathToPub | |||
# docker build -t eshop/webspa $webSPAPathToPub | |||
# docker build -t eshop/identity $identitySvcPathToPub |
@ -0,0 +1,37 @@ | |||
using Microsoft.EntityFrameworkCore; | |||
using Microsoft.EntityFrameworkCore.Storage; | |||
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; | |||
using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF.Services; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Data.Common; | |||
using System.Text; | |||
using System.Threading.Tasks; | |||
namespace Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF.Utilities | |||
{ | |||
public class ResilientTransaction | |||
{ | |||
private DbContext _context; | |||
private ResilientTransaction(DbContext context) => | |||
_context = context ?? throw new ArgumentNullException(nameof(context)); | |||
public static ResilientTransaction New (DbContext context) => | |||
new ResilientTransaction(context); | |||
public async Task ExecuteAsync(Func<Task> action) | |||
{ | |||
//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 = _context.Database.CreateExecutionStrategy(); | |||
await strategy.ExecuteAsync(async () => | |||
{ | |||
using (var transaction = _context.Database.BeginTransaction()) | |||
{ | |||
await action(); | |||
transaction.Commit(); | |||
} | |||
}); | |||
} | |||
} | |||
} |
@ -0,0 +1,14 @@ | |||
<Project Sdk="Microsoft.NET.Sdk"> | |||
<PropertyGroup> | |||
<TargetFramework>netstandard1.4</TargetFramework> | |||
<RootNamespace>Microsoft.eShopOnContainers.BuildingBlocks.Resilience.Http</RootNamespace> | |||
</PropertyGroup> | |||
<ItemGroup> | |||
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="1.1.0" /> | |||
<PackageReference Include="Newtonsoft.Json" Version="9.0.1" /> | |||
<PackageReference Include="Polly" Version="5.0.6" /> | |||
</ItemGroup> | |||
</Project> |
@ -0,0 +1,10 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Text; | |||
namespace Microsoft.eShopOnContainers.BuildingBlocks.Resilience.Http | |||
{ | |||
public class ResiliencePolicy | |||
{ | |||
} | |||
} |
@ -0,0 +1,23 @@ | |||
using System; | |||
using System.Globalization; | |||
using Xamarin.Forms; | |||
namespace eShopOnContainers.Core.Converters | |||
{ | |||
public class WebNavigatedEventArgsConverter : IValueConverter | |||
{ | |||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) | |||
{ | |||
var eventArgs = value as WebNavigatedEventArgs; | |||
if (eventArgs == null) | |||
throw new ArgumentException("Expected WebNavigatedEventArgs as value", "value"); | |||
return eventArgs.Url; | |||
} | |||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) | |||
{ | |||
throw new NotImplementedException(); | |||
} | |||
} | |||
} |
@ -0,0 +1,27 @@ | |||
using Basket.API.IntegrationEvents.Events; | |||
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; | |||
using Microsoft.eShopOnContainers.Services.Basket.API.Model; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using System.Threading.Tasks; | |||
namespace Basket.API.IntegrationEvents.EventHandling | |||
{ | |||
public class OrderStartedIntegrationEventHandler : IIntegrationEventHandler<OrderStartedIntegrationEvent> | |||
{ | |||
private readonly IBasketRepository _repository; | |||
public OrderStartedIntegrationEventHandler(IBasketRepository repository) | |||
{ | |||
_repository = repository; | |||
} | |||
public async Task Handle(OrderStartedIntegrationEvent @event) | |||
{ | |||
await _repository.DeleteBasketAsync(@event.UserId.ToString()); | |||
} | |||
} | |||
} | |||
@ -0,0 +1,19 @@ | |||
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using System.Threading.Tasks; | |||
namespace 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 OrderStartedIntegrationEvent : IntegrationEvent | |||
{ | |||
public string UserId { get; } | |||
public OrderStartedIntegrationEvent(string userId) => | |||
UserId = userId; | |||
} | |||
} |
@ -0,0 +1,48 @@ | |||
using Microsoft.EntityFrameworkCore; | |||
using Microsoft.EntityFrameworkCore.Storage; | |||
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; | |||
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; | |||
using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF.Services; | |||
using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF.Utilities; | |||
using Microsoft.eShopOnContainers.Services.Catalog.API.Infrastructure; | |||
using System; | |||
using System.Data.Common; | |||
using System.Threading.Tasks; | |||
namespace Catalog.API.IntegrationEvents | |||
{ | |||
public class CatalogIntegrationEventService : ICatalogIntegrationEventService | |||
{ | |||
private readonly Func<DbConnection, IIntegrationEventLogService> _integrationEventLogServiceFactory; | |||
private readonly IEventBus _eventBus; | |||
private readonly CatalogContext _catalogContext; | |||
private readonly IIntegrationEventLogService _eventLogService; | |||
public CatalogIntegrationEventService(IEventBus eventBus, CatalogContext catalogContext, | |||
Func<DbConnection, IIntegrationEventLogService> integrationEventLogServiceFactory) | |||
{ | |||
_catalogContext = catalogContext ?? throw new ArgumentNullException(nameof(catalogContext)); | |||
_integrationEventLogServiceFactory = integrationEventLogServiceFactory ?? throw new ArgumentNullException(nameof(integrationEventLogServiceFactory)); | |||
_eventBus = eventBus ?? throw new ArgumentNullException(nameof(eventBus)); | |||
_eventLogService = _integrationEventLogServiceFactory(_catalogContext.Database.GetDbConnection()); | |||
} | |||
public async Task PublishThroughEventBusAsync(IntegrationEvent evt) | |||
{ | |||
_eventBus.Publish(evt); | |||
await _eventLogService.MarkEventAsPublishedAsync(evt); | |||
} | |||
public async Task SaveEventAndCatalogContextChangesAsync(IntegrationEvent evt) | |||
{ | |||
//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 | |||
await ResilientTransaction.New(_catalogContext) | |||
.ExecuteAsync(async () => { | |||
// Achieving atomicity between original catalog database operation and the IntegrationEventLog thanks to a local transaction | |||
await _catalogContext.SaveChangesAsync(); | |||
await _eventLogService.SaveEventAsync(evt, _catalogContext.Database.CurrentTransaction.GetDbTransaction()); | |||
}); | |||
} | |||
} | |||
} |
@ -0,0 +1,14 @@ | |||
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using System.Threading.Tasks; | |||
namespace Catalog.API.IntegrationEvents | |||
{ | |||
public interface ICatalogIntegrationEventService | |||
{ | |||
Task SaveEventAndCatalogContextChangesAsync(IntegrationEvent evt); | |||
Task PublishThroughEventBusAsync(IntegrationEvent evt); | |||
} | |||
} |
@ -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 Ordering.API.Infrastructure.IntegrationEventMigrations | |||
{ | |||
[DbContext(typeof(IntegrationEventLogContext))] | |||
[Migration("20170330131634_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 Ordering.API.Infrastructure.IntegrationEventMigrations | |||
{ | |||
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 Ordering.API.Infrastructure.IntegrationEventMigrations | |||
{ | |||
[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,244 @@ | |||
using System; | |||
using Microsoft.EntityFrameworkCore; | |||
using Microsoft.EntityFrameworkCore.Infrastructure; | |||
using Microsoft.EntityFrameworkCore.Metadata; | |||
using Microsoft.EntityFrameworkCore.Migrations; | |||
using Microsoft.eShopOnContainers.Services.Ordering.Infrastructure; | |||
namespace Ordering.API.Migrations | |||
{ | |||
[DbContext(typeof(OrderingContext))] | |||
[Migration("20170403082405_NoBuyerPropertyInOrder")] | |||
partial class NoBuyerPropertyInOrder | |||
{ | |||
protected override void BuildTargetModel(ModelBuilder modelBuilder) | |||
{ | |||
modelBuilder | |||
.HasAnnotation("ProductVersion", "1.1.0-rtm-22752") | |||
.HasAnnotation("SqlServer:Sequence:.orderitemseq", "'orderitemseq', '', '1', '10', '', '', 'Int64', 'False'") | |||
.HasAnnotation("SqlServer:Sequence:ordering.buyerseq", "'buyerseq', 'ordering', '1', '10', '', '', 'Int64', 'False'") | |||
.HasAnnotation("SqlServer:Sequence:ordering.orderseq", "'orderseq', 'ordering', '1', '10', '', '', 'Int64', 'False'") | |||
.HasAnnotation("SqlServer:Sequence:ordering.paymentseq", "'paymentseq', 'ordering', '1', '10', '', '', 'Int64', 'False'") | |||
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); | |||
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.BuyerAggregate.Buyer", b => | |||
{ | |||
b.Property<int>("Id") | |||
.ValueGeneratedOnAdd() | |||
.HasAnnotation("SqlServer:HiLoSequenceName", "buyerseq") | |||
.HasAnnotation("SqlServer:HiLoSequenceSchema", "ordering") | |||
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.SequenceHiLo); | |||
b.Property<string>("IdentityGuid") | |||
.IsRequired() | |||
.HasMaxLength(200); | |||
b.HasKey("Id"); | |||
b.HasIndex("IdentityGuid") | |||
.IsUnique(); | |||
b.ToTable("buyers","ordering"); | |||
}); | |||
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.BuyerAggregate.CardType", b => | |||
{ | |||
b.Property<int>("Id") | |||
.HasDefaultValue(1); | |||
b.Property<string>("Name") | |||
.IsRequired() | |||
.HasMaxLength(200); | |||
b.HasKey("Id"); | |||
b.ToTable("cardtypes","ordering"); | |||
}); | |||
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.BuyerAggregate.PaymentMethod", b => | |||
{ | |||
b.Property<int>("Id") | |||
.ValueGeneratedOnAdd() | |||
.HasAnnotation("SqlServer:HiLoSequenceName", "paymentseq") | |||
.HasAnnotation("SqlServer:HiLoSequenceSchema", "ordering") | |||
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.SequenceHiLo); | |||
b.Property<string>("Alias") | |||
.IsRequired() | |||
.HasMaxLength(200); | |||
b.Property<int>("BuyerId"); | |||
b.Property<string>("CardHolderName") | |||
.IsRequired() | |||
.HasMaxLength(200); | |||
b.Property<string>("CardNumber") | |||
.IsRequired() | |||
.HasMaxLength(25); | |||
b.Property<int>("CardTypeId"); | |||
b.Property<DateTime>("Expiration"); | |||
b.HasKey("Id"); | |||
b.HasIndex("BuyerId"); | |||
b.HasIndex("CardTypeId"); | |||
b.ToTable("paymentmethods","ordering"); | |||
}); | |||
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate.Address", b => | |||
{ | |||
b.Property<int>("Id") | |||
.ValueGeneratedOnAdd(); | |||
b.Property<string>("City"); | |||
b.Property<string>("Country"); | |||
b.Property<string>("State"); | |||
b.Property<string>("Street"); | |||
b.Property<string>("ZipCode"); | |||
b.HasKey("Id"); | |||
b.ToTable("address","ordering"); | |||
}); | |||
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate.Order", b => | |||
{ | |||
b.Property<int>("Id") | |||
.ValueGeneratedOnAdd() | |||
.HasAnnotation("SqlServer:HiLoSequenceName", "orderseq") | |||
.HasAnnotation("SqlServer:HiLoSequenceSchema", "ordering") | |||
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.SequenceHiLo); | |||
b.Property<int?>("AddressId"); | |||
b.Property<int?>("BuyerId"); | |||
b.Property<DateTime>("OrderDate"); | |||
b.Property<int>("OrderStatusId"); | |||
b.Property<int?>("PaymentMethodId"); | |||
b.HasKey("Id"); | |||
b.HasIndex("AddressId"); | |||
b.HasIndex("BuyerId"); | |||
b.HasIndex("OrderStatusId"); | |||
b.HasIndex("PaymentMethodId"); | |||
b.ToTable("orders","ordering"); | |||
}); | |||
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate.OrderItem", b => | |||
{ | |||
b.Property<int>("Id") | |||
.ValueGeneratedOnAdd() | |||
.HasAnnotation("SqlServer:HiLoSequenceName", "orderitemseq") | |||
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.SequenceHiLo); | |||
b.Property<decimal>("Discount"); | |||
b.Property<int>("OrderId"); | |||
b.Property<string>("PictureUrl"); | |||
b.Property<int>("ProductId"); | |||
b.Property<string>("ProductName") | |||
.IsRequired(); | |||
b.Property<decimal>("UnitPrice"); | |||
b.Property<int>("Units"); | |||
b.HasKey("Id"); | |||
b.HasIndex("OrderId"); | |||
b.ToTable("orderItems","ordering"); | |||
}); | |||
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate.OrderStatus", b => | |||
{ | |||
b.Property<int>("Id") | |||
.HasDefaultValue(1); | |||
b.Property<string>("Name") | |||
.IsRequired() | |||
.HasMaxLength(200); | |||
b.HasKey("Id"); | |||
b.ToTable("orderstatus","ordering"); | |||
}); | |||
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Ordering.Infrastructure.ClientRequest", b => | |||
{ | |||
b.Property<Guid>("Id") | |||
.ValueGeneratedOnAdd(); | |||
b.Property<string>("Name") | |||
.IsRequired(); | |||
b.Property<DateTime>("Time"); | |||
b.HasKey("Id"); | |||
b.ToTable("requests","ordering"); | |||
}); | |||
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.BuyerAggregate.PaymentMethod", b => | |||
{ | |||
b.HasOne("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.BuyerAggregate.Buyer") | |||
.WithMany("PaymentMethods") | |||
.HasForeignKey("BuyerId") | |||
.OnDelete(DeleteBehavior.Cascade); | |||
b.HasOne("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.BuyerAggregate.CardType", "CardType") | |||
.WithMany() | |||
.HasForeignKey("CardTypeId") | |||
.OnDelete(DeleteBehavior.Cascade); | |||
}); | |||
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate.Order", b => | |||
{ | |||
b.HasOne("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate.Address", "Address") | |||
.WithMany() | |||
.HasForeignKey("AddressId"); | |||
b.HasOne("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.BuyerAggregate.Buyer") | |||
.WithMany() | |||
.HasForeignKey("BuyerId"); | |||
b.HasOne("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate.OrderStatus", "OrderStatus") | |||
.WithMany() | |||
.HasForeignKey("OrderStatusId") | |||
.OnDelete(DeleteBehavior.Cascade); | |||
b.HasOne("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.BuyerAggregate.PaymentMethod", "PaymentMethod") | |||
.WithMany() | |||
.HasForeignKey("PaymentMethodId"); | |||
}); | |||
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate.OrderItem", b => | |||
{ | |||
b.HasOne("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate.Order") | |||
.WithMany("OrderItems") | |||
.HasForeignKey("OrderId") | |||
.OnDelete(DeleteBehavior.Cascade); | |||
}); | |||
} | |||
} | |||
} |
@ -0,0 +1,19 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using Microsoft.EntityFrameworkCore.Migrations; | |||
namespace Ordering.API.Migrations | |||
{ | |||
public partial class NoBuyerPropertyInOrder : Migration | |||
{ | |||
protected override void Up(MigrationBuilder migrationBuilder) | |||
{ | |||
} | |||
protected override void Down(MigrationBuilder migrationBuilder) | |||
{ | |||
} | |||
} | |||
} |
@ -0,0 +1,244 @@ | |||
using System; | |||
using Microsoft.EntityFrameworkCore; | |||
using Microsoft.EntityFrameworkCore.Infrastructure; | |||
using Microsoft.EntityFrameworkCore.Metadata; | |||
using Microsoft.EntityFrameworkCore.Migrations; | |||
using Microsoft.eShopOnContainers.Services.Ordering.Infrastructure; | |||
namespace Ordering.API.Migrations | |||
{ | |||
[DbContext(typeof(OrderingContext))] | |||
[Migration("20170405110939_NoPaymentMethodPropertyInOrder")] | |||
partial class NoPaymentMethodPropertyInOrder | |||
{ | |||
protected override void BuildTargetModel(ModelBuilder modelBuilder) | |||
{ | |||
modelBuilder | |||
.HasAnnotation("ProductVersion", "1.1.1") | |||
.HasAnnotation("SqlServer:Sequence:.orderitemseq", "'orderitemseq', '', '1', '10', '', '', 'Int64', 'False'") | |||
.HasAnnotation("SqlServer:Sequence:ordering.buyerseq", "'buyerseq', 'ordering', '1', '10', '', '', 'Int64', 'False'") | |||
.HasAnnotation("SqlServer:Sequence:ordering.orderseq", "'orderseq', 'ordering', '1', '10', '', '', 'Int64', 'False'") | |||
.HasAnnotation("SqlServer:Sequence:ordering.paymentseq", "'paymentseq', 'ordering', '1', '10', '', '', 'Int64', 'False'") | |||
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); | |||
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.BuyerAggregate.Buyer", b => | |||
{ | |||
b.Property<int>("Id") | |||
.ValueGeneratedOnAdd() | |||
.HasAnnotation("SqlServer:HiLoSequenceName", "buyerseq") | |||
.HasAnnotation("SqlServer:HiLoSequenceSchema", "ordering") | |||
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.SequenceHiLo); | |||
b.Property<string>("IdentityGuid") | |||
.IsRequired() | |||
.HasMaxLength(200); | |||
b.HasKey("Id"); | |||
b.HasIndex("IdentityGuid") | |||
.IsUnique(); | |||
b.ToTable("buyers","ordering"); | |||
}); | |||
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.BuyerAggregate.CardType", b => | |||
{ | |||
b.Property<int>("Id") | |||
.HasDefaultValue(1); | |||
b.Property<string>("Name") | |||
.IsRequired() | |||
.HasMaxLength(200); | |||
b.HasKey("Id"); | |||
b.ToTable("cardtypes","ordering"); | |||
}); | |||
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.BuyerAggregate.PaymentMethod", b => | |||
{ | |||
b.Property<int>("Id") | |||
.ValueGeneratedOnAdd() | |||
.HasAnnotation("SqlServer:HiLoSequenceName", "paymentseq") | |||
.HasAnnotation("SqlServer:HiLoSequenceSchema", "ordering") | |||
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.SequenceHiLo); | |||
b.Property<string>("Alias") | |||
.IsRequired() | |||
.HasMaxLength(200); | |||
b.Property<int>("BuyerId"); | |||
b.Property<string>("CardHolderName") | |||
.IsRequired() | |||
.HasMaxLength(200); | |||
b.Property<string>("CardNumber") | |||
.IsRequired() | |||
.HasMaxLength(25); | |||
b.Property<int>("CardTypeId"); | |||
b.Property<DateTime>("Expiration"); | |||
b.HasKey("Id"); | |||
b.HasIndex("BuyerId"); | |||
b.HasIndex("CardTypeId"); | |||
b.ToTable("paymentmethods","ordering"); | |||
}); | |||
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate.Address", b => | |||
{ | |||
b.Property<int>("Id") | |||
.ValueGeneratedOnAdd(); | |||
b.Property<string>("City"); | |||
b.Property<string>("Country"); | |||
b.Property<string>("State"); | |||
b.Property<string>("Street"); | |||
b.Property<string>("ZipCode"); | |||
b.HasKey("Id"); | |||
b.ToTable("address","ordering"); | |||
}); | |||
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate.Order", b => | |||
{ | |||
b.Property<int>("Id") | |||
.ValueGeneratedOnAdd() | |||
.HasAnnotation("SqlServer:HiLoSequenceName", "orderseq") | |||
.HasAnnotation("SqlServer:HiLoSequenceSchema", "ordering") | |||
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.SequenceHiLo); | |||
b.Property<int?>("AddressId"); | |||
b.Property<int?>("BuyerId"); | |||
b.Property<DateTime>("OrderDate"); | |||
b.Property<int>("OrderStatusId"); | |||
b.Property<int?>("PaymentMethodId"); | |||
b.HasKey("Id"); | |||
b.HasIndex("AddressId"); | |||
b.HasIndex("BuyerId"); | |||
b.HasIndex("OrderStatusId"); | |||
b.HasIndex("PaymentMethodId"); | |||
b.ToTable("orders","ordering"); | |||
}); | |||
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate.OrderItem", b => | |||
{ | |||
b.Property<int>("Id") | |||
.ValueGeneratedOnAdd() | |||
.HasAnnotation("SqlServer:HiLoSequenceName", "orderitemseq") | |||
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.SequenceHiLo); | |||
b.Property<decimal>("Discount"); | |||
b.Property<int>("OrderId"); | |||
b.Property<string>("PictureUrl"); | |||
b.Property<int>("ProductId"); | |||
b.Property<string>("ProductName") | |||
.IsRequired(); | |||
b.Property<decimal>("UnitPrice"); | |||
b.Property<int>("Units"); | |||
b.HasKey("Id"); | |||
b.HasIndex("OrderId"); | |||
b.ToTable("orderItems","ordering"); | |||
}); | |||
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate.OrderStatus", b => | |||
{ | |||
b.Property<int>("Id") | |||
.HasDefaultValue(1); | |||
b.Property<string>("Name") | |||
.IsRequired() | |||
.HasMaxLength(200); | |||
b.HasKey("Id"); | |||
b.ToTable("orderstatus","ordering"); | |||
}); | |||
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Ordering.Infrastructure.ClientRequest", b => | |||
{ | |||
b.Property<Guid>("Id") | |||
.ValueGeneratedOnAdd(); | |||
b.Property<string>("Name") | |||
.IsRequired(); | |||
b.Property<DateTime>("Time"); | |||
b.HasKey("Id"); | |||
b.ToTable("requests","ordering"); | |||
}); | |||
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.BuyerAggregate.PaymentMethod", b => | |||
{ | |||
b.HasOne("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.BuyerAggregate.Buyer") | |||
.WithMany("PaymentMethods") | |||
.HasForeignKey("BuyerId") | |||
.OnDelete(DeleteBehavior.Cascade); | |||
b.HasOne("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.BuyerAggregate.CardType", "CardType") | |||
.WithMany() | |||
.HasForeignKey("CardTypeId") | |||
.OnDelete(DeleteBehavior.Cascade); | |||
}); | |||
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate.Order", b => | |||
{ | |||
b.HasOne("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate.Address", "Address") | |||
.WithMany() | |||
.HasForeignKey("AddressId"); | |||
b.HasOne("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.BuyerAggregate.Buyer") | |||
.WithMany() | |||
.HasForeignKey("BuyerId"); | |||
b.HasOne("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate.OrderStatus", "OrderStatus") | |||
.WithMany() | |||
.HasForeignKey("OrderStatusId") | |||
.OnDelete(DeleteBehavior.Cascade); | |||
b.HasOne("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.BuyerAggregate.PaymentMethod") | |||
.WithMany() | |||
.HasForeignKey("PaymentMethodId"); | |||
}); | |||
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate.OrderItem", b => | |||
{ | |||
b.HasOne("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate.Order") | |||
.WithMany("OrderItems") | |||
.HasForeignKey("OrderId") | |||
.OnDelete(DeleteBehavior.Cascade); | |||
}); | |||
} | |||
} | |||
} |
@ -0,0 +1,19 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using Microsoft.EntityFrameworkCore.Migrations; | |||
namespace Ordering.API.Migrations | |||
{ | |||
public partial class NoPaymentMethodPropertyInOrder : Migration | |||
{ | |||
protected override void Up(MigrationBuilder migrationBuilder) | |||
{ | |||
} | |||
protected override void Down(MigrationBuilder migrationBuilder) | |||
{ | |||
} | |||
} | |||
} |
@ -0,0 +1,19 @@ | |||
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using System.Threading.Tasks; | |||
namespace Ordering.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 OrderStartedIntegrationEvent : IntegrationEvent | |||
{ | |||
public string UserId { get; } | |||
public OrderStartedIntegrationEvent(string userId) => | |||
UserId = userId; | |||
} | |||
} |
@ -0,0 +1,14 @@ | |||
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using System.Threading.Tasks; | |||
namespace Ordering.API.IntegrationEvents | |||
{ | |||
public interface IOrderingIntegrationEventService | |||
{ | |||
Task SaveEventAndOrderingContextChangesAsync(IntegrationEvent evt); | |||
Task PublishThroughEventBusAsync(IntegrationEvent evt); | |||
} | |||
} |
@ -0,0 +1,49 @@ | |||
using Microsoft.EntityFrameworkCore; | |||
using Microsoft.EntityFrameworkCore.Storage; | |||
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; | |||
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; | |||
using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF.Services; | |||
using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF.Utilities; | |||
using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate; | |||
using Microsoft.eShopOnContainers.Services.Ordering.Infrastructure; | |||
using System; | |||
using System.Data.Common; | |||
using System.Threading.Tasks; | |||
namespace Ordering.API.IntegrationEvents | |||
{ | |||
public class OrderingIntegrationEventService : IOrderingIntegrationEventService | |||
{ | |||
private readonly Func<DbConnection, IIntegrationEventLogService> _integrationEventLogServiceFactory; | |||
private readonly IEventBus _eventBus; | |||
private readonly OrderingContext _orderingContext; | |||
private readonly IIntegrationEventLogService _eventLogService; | |||
public OrderingIntegrationEventService (IEventBus eventBus, OrderingContext orderingContext, | |||
Func<DbConnection, IIntegrationEventLogService> integrationEventLogServiceFactory) | |||
{ | |||
_orderingContext = orderingContext ?? throw new ArgumentNullException(nameof(orderingContext)); | |||
_integrationEventLogServiceFactory = integrationEventLogServiceFactory ?? throw new ArgumentNullException(nameof(integrationEventLogServiceFactory)); | |||
_eventBus = eventBus ?? throw new ArgumentNullException(nameof(eventBus)); | |||
_eventLogService = _integrationEventLogServiceFactory(_orderingContext.Database.GetDbConnection()); | |||
} | |||
public async Task PublishThroughEventBusAsync(IntegrationEvent evt) | |||
{ | |||
_eventBus.Publish(evt); | |||
await _eventLogService.MarkEventAsPublishedAsync(evt); | |||
} | |||
public async Task SaveEventAndOrderingContextChangesAsync(IntegrationEvent evt) | |||
{ | |||
//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 | |||
await ResilientTransaction.New(_orderingContext) | |||
.ExecuteAsync(async () => { | |||
// Achieving atomicity between original ordering database operation and the IntegrationEventLog thanks to a local transaction | |||
await _orderingContext.SaveChangesAsync(); | |||
await _eventLogService.SaveEventAsync(evt, _orderingContext.Database.CurrentTransaction.GetDbTransaction()); | |||
}); | |||
} | |||
} | |||
} |
@ -0,0 +1,10 @@ | |||
using Microsoft.eShopOnContainers.BuildingBlocks.Resilience.Http; | |||
using System; | |||
namespace Microsoft.eShopOnContainers.WebMVC.Infrastructure | |||
{ | |||
public interface IResilientHttpClientFactory | |||
{ | |||
ResilientHttpClient CreateResilientHttpClient(); | |||
} | |||
} |
@ -0,0 +1,59 @@ | |||
using Microsoft.eShopOnContainers.BuildingBlocks.Resilience.Http; | |||
using Microsoft.Extensions.Logging; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using System.Threading.Tasks; | |||
using Polly; | |||
using System.Net.Http; | |||
namespace Microsoft.eShopOnContainers.WebMVC.Infrastructure | |||
{ | |||
public class ResilientHttpClientFactory : IResilientHttpClientFactory | |||
{ | |||
private readonly ILogger<ResilientHttpClient> _logger; | |||
public ResilientHttpClientFactory(ILogger<ResilientHttpClient> logger) | |||
=>_logger = logger; | |||
public ResilientHttpClient CreateResilientHttpClient() | |||
=> new ResilientHttpClient(CreatePolicies(), _logger); | |||
private Policy[] CreatePolicies() | |||
=> new Policy[] | |||
{ | |||
Policy.Handle<HttpRequestException>() | |||
.WaitAndRetryAsync( | |||
// number of retries | |||
6, | |||
// exponential backofff | |||
retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)), | |||
// on retry | |||
(exception, timeSpan, retryCount, context) => | |||
{ | |||
var msg = $"Retry {retryCount} implemented with Polly's RetryPolicy " + | |||
$"of {context.PolicyKey} " + | |||
$"at {context.ExecutionKey}, " + | |||
$"due to: {exception}."; | |||
_logger.LogWarning(msg); | |||
_logger.LogDebug(msg); | |||
}), | |||
Policy.Handle<HttpRequestException>() | |||
.CircuitBreakerAsync( | |||
// number of exceptions before breaking circuit | |||
5, | |||
// time circuit opened before retry | |||
TimeSpan.FromMinutes(1), | |||
(exception, duration) => | |||
{ | |||
// on circuit opened | |||
_logger.LogTrace("Circuit breaker opened"); | |||
}, | |||
() => | |||
{ | |||
// on circuit closed | |||
_logger.LogTrace("Circuit breaker reset"); | |||
})}; | |||
} | |||
} |
@ -0,0 +1,20 @@ | |||
using Microsoft.Extensions.HealthChecks; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using System.Threading.Tasks; | |||
namespace WebStatus.Viewmodels | |||
{ | |||
public class NamedCheckResult | |||
{ | |||
public string Name { get; } | |||
public IHealthCheckResult Result { get; } | |||
public NamedCheckResult(string name, IHealthCheckResult result) | |||
{ | |||
Name = name; | |||
Result = result; | |||
} | |||
} | |||
} |
@ -0,0 +1,7 @@ | |||
{ | |||
"ConnectionString": "Server=tcp:127.0.0.1,5433;Initial Catalog=Microsoft.eShopOnContainers.Services.CatalogDb;User Id=sa;Password=Pass@word", | |||
"ExternalCatalogBaseUrl": "http://localhost:5101", | |||
"IdentityUrl": "http://localhost:5105", | |||
"isTest": "true", | |||
"EventBusConnection": "localhost" | |||
} |
@ -0,0 +1,7 @@ | |||
{ | |||
"ConnectionString": "Server=tcp:127.0.0.1,5433;Initial Catalog=Microsoft.eShopOnContainers.Services.CatalogDb;User Id=sa;Password=Pass@word", | |||
"ExternalCatalogBaseUrl": "http://localhost:5101", | |||
"IdentityUrl": "http://localhost:5105", | |||
"isTest": "true", | |||
"EventBusConnection": "localhost" | |||
} |