diff --git a/Directory.Packages.props b/Directory.Packages.props
index c803dc53..5e641f50 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -54,6 +54,16 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/Everything.sln b/Everything.sln
index fb13a7c1..b228d63a 100644
--- a/Everything.sln
+++ b/Everything.sln
@@ -29,9 +29,14 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnitTests", "tests\UnitTest
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{7EFE7D65-5C2D-4D83-B034-D06B2D37564E}"
ProjectSection(SolutionItems) = preProject
+ Directory.Packages.props = Directory.Packages.props
README.md = README.md
EndProjectSection
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "eShopWeb.AppHost", "src\eShopWeb.AppHost\eShopWeb.AppHost.csproj", "{E3079820-FF6C-4CC7-9CBB-8DF68237299F}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "eShopWeb.AspireServiceDefaults", "src\eShopWeb.AspireServiceDefaults\eShopWeb.AspireServiceDefaults.csproj", "{7DB219F4-4ABC-45D6-A5F7-B938769D5319}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -78,6 +83,14 @@ Global
{EAD6CF0B-2979-462C-BBB9-AF723B1EB570}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EAD6CF0B-2979-462C-BBB9-AF723B1EB570}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EAD6CF0B-2979-462C-BBB9-AF723B1EB570}.Release|Any CPU.Build.0 = Release|Any CPU
+ {E3079820-FF6C-4CC7-9CBB-8DF68237299F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {E3079820-FF6C-4CC7-9CBB-8DF68237299F}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {E3079820-FF6C-4CC7-9CBB-8DF68237299F}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {E3079820-FF6C-4CC7-9CBB-8DF68237299F}.Release|Any CPU.Build.0 = Release|Any CPU
+ {7DB219F4-4ABC-45D6-A5F7-B938769D5319}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {7DB219F4-4ABC-45D6-A5F7-B938769D5319}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {7DB219F4-4ABC-45D6-A5F7-B938769D5319}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {7DB219F4-4ABC-45D6-A5F7-B938769D5319}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -93,5 +106,10 @@ Global
{D6829485-DD9C-42CE-BEDE-4EB0E81021AC} = {BAA5312D-B54C-42D6-A3B9-504DD12F8250}
{698594AE-78D3-429F-B5CC-3A6F6BCE397A} = {BAA5312D-B54C-42D6-A3B9-504DD12F8250}
{EAD6CF0B-2979-462C-BBB9-AF723B1EB570} = {BAA5312D-B54C-42D6-A3B9-504DD12F8250}
+ {E3079820-FF6C-4CC7-9CBB-8DF68237299F} = {8FF16BDB-352E-42A2-A25F-0B5BC3A17FD7}
+ {7DB219F4-4ABC-45D6-A5F7-B938769D5319} = {8FF16BDB-352E-42A2-A25F-0B5BC3A17FD7}
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {CC66E299-A176-4667-95E3-CCDA89AAC6D0}
EndGlobalSection
EndGlobal
diff --git a/src/BlazorAdmin/Program.cs b/src/BlazorAdmin/Program.cs
index a6d4354d..7fb8c29d 100644
--- a/src/BlazorAdmin/Program.cs
+++ b/src/BlazorAdmin/Program.cs
@@ -14,13 +14,14 @@
using Microsoft.Extensions.Logging;
var builder = WebAssemblyHostBuilder.CreateDefault(args);
+
builder.RootComponents.Add("#admin");
builder.RootComponents.Add("head::after");
var configSection = builder.Configuration.GetRequiredSection(BaseUrlConfiguration.CONFIG_NAME);
builder.Services.Configure(configSection);
-builder.Services.AddScoped(sp => new HttpClient() { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
+builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
builder.Services.AddScoped();
builder.Services.AddScoped();
diff --git a/src/BlazorAdmin/Properties/launchSettings.json b/src/BlazorAdmin/Properties/launchSettings.json
index 6480448e..ed29accb 100644
--- a/src/BlazorAdmin/Properties/launchSettings.json
+++ b/src/BlazorAdmin/Properties/launchSettings.json
@@ -12,7 +12,7 @@
"commandName": "IISExpress",
"launchBrowser": true,
"inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}",
- "applicationUrl": "https://localhost:5001;http://localhost:5000",
+ "applicationUrl": "https://localhost:5011;http://localhost:5010",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
@@ -21,7 +21,7 @@
"commandName": "Project",
"launchBrowser": true,
"inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}",
- "applicationUrl": "https://localhost:5001;http://localhost:5000",
+ "applicationUrl": "https://localhost:5011;http://localhost:5010",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
diff --git a/src/BlazorAdmin/Services/CatalogLookupDataService.cs b/src/BlazorAdmin/Services/CatalogLookupDataService.cs
index fa06b160..e6c0823f 100644
--- a/src/BlazorAdmin/Services/CatalogLookupDataService.cs
+++ b/src/BlazorAdmin/Services/CatalogLookupDataService.cs
@@ -35,7 +35,7 @@ public CatalogLookupDataService(HttpClient httpClient,
public async Task> List()
{
var endpointName = typeof(TLookupData).GetCustomAttribute().Name;
- _logger.LogInformation($"Fetching {typeof(TLookupData).Name} from API. Enpoint : {endpointName}");
+ _logger.LogInformation($"Fetching {typeof(TLookupData).Name} from API Endpoint : {endpointName}");
var response = await _httpClient.GetFromJsonAsync($"{_apiUrl}{endpointName}");
return response.List;
diff --git a/src/PublicApi/AuthEndpoints/AuthenticateEndpoint.cs b/src/PublicApi/AuthEndpoints/AuthenticateEndpoint.cs
index e6f25cea..6ac3850d 100644
--- a/src/PublicApi/AuthEndpoints/AuthenticateEndpoint.cs
+++ b/src/PublicApi/AuthEndpoints/AuthenticateEndpoint.cs
@@ -12,18 +12,10 @@ namespace Microsoft.eShopWeb.PublicApi.AuthEndpoints;
///
/// Authenticates a user
///
-public class AuthenticateEndpoint : Endpoint
-{
- private readonly SignInManager _signInManager;
- private readonly ITokenClaimsService _tokenClaimsService;
-
- public AuthenticateEndpoint(SignInManager signInManager,
+public class AuthenticateEndpoint(SignInManager signInManager,
ITokenClaimsService tokenClaimsService)
- {
- _signInManager = signInManager;
- _tokenClaimsService = tokenClaimsService;
- }
-
+ : Endpoint
+{
public override void Configure()
{
Post("api/authenticate");
@@ -43,7 +35,7 @@ public override async Task ExecuteAsync(AuthenticateReques
// This doesn't count login failures towards account lockout
// To enable password failures to trigger account lockout, set lockoutOnFailure: true
//var result = await _signInManager.PasswordSignInAsync(Input.Email, Input.Password, Input.RememberMe, lockoutOnFailure: true);
- var result = await _signInManager.PasswordSignInAsync(request.Username, request.Password, false, true);
+ var result = await signInManager.PasswordSignInAsync(request.Username, request.Password, false, true);
response.Result = result.Succeeded;
response.IsLockedOut = result.IsLockedOut;
@@ -53,7 +45,7 @@ public override async Task ExecuteAsync(AuthenticateReques
if (result.Succeeded)
{
- response.Token = await _tokenClaimsService.GetTokenAsync(request.Username);
+ response.Token = await tokenClaimsService.GetTokenAsync(request.Username);
}
return response;
diff --git a/src/PublicApi/CatalogBrandEndpoints/CatalogBrandListEndpoint.cs b/src/PublicApi/CatalogBrandEndpoints/CatalogBrandListEndpoint.cs
index 8444dcdc..e7fa3451 100644
--- a/src/PublicApi/CatalogBrandEndpoints/CatalogBrandListEndpoint.cs
+++ b/src/PublicApi/CatalogBrandEndpoints/CatalogBrandListEndpoint.cs
@@ -11,17 +11,9 @@ namespace Microsoft.eShopWeb.PublicApi.CatalogBrandEndpoints;
///
/// List Catalog Brands
///
-public class CatalogBrandListEndpoint : EndpointWithoutRequest
+public class CatalogBrandListEndpoint(IRepository catalogBrandRepository, AutoMapper.IMapper mapper)
+ : EndpointWithoutRequest
{
- private readonly IRepository _catalogBrandRepository;
- private readonly AutoMapper.IMapper _mapper;
-
- public CatalogBrandListEndpoint(IRepository catalogBrandRepository, AutoMapper.IMapper mapper)
- {
- _catalogBrandRepository = catalogBrandRepository;
- _mapper = mapper;
- }
-
public override void Configure()
{
Get("api/catalog-brands");
@@ -35,9 +27,9 @@ public override async Task ExecuteAsync(CancellationT
{
var response = new ListCatalogBrandsResponse();
- var items = await _catalogBrandRepository.ListAsync(ct);
+ var items = await catalogBrandRepository.ListAsync(ct);
- response.CatalogBrands.AddRange(items.Select(_mapper.Map));
+ response.CatalogBrands.AddRange(items.Select(mapper.Map));
return response;
}
diff --git a/src/PublicApi/CatalogItemEndpoints/CatalogItemGetByIdEndpoint.cs b/src/PublicApi/CatalogItemEndpoints/CatalogItemGetByIdEndpoint.cs
index d2b8c303..a70eab19 100644
--- a/src/PublicApi/CatalogItemEndpoints/CatalogItemGetByIdEndpoint.cs
+++ b/src/PublicApi/CatalogItemEndpoints/CatalogItemGetByIdEndpoint.cs
@@ -11,18 +11,9 @@ namespace Microsoft.eShopWeb.PublicApi.CatalogItemEndpoints;
///
/// Get a Catalog Item by Id
///
-public class CatalogItemGetByIdEndpoint
+public class CatalogItemGetByIdEndpoint(IRepository itemRepository, IUriComposer uriComposer)
: Endpoint, NotFound>>
{
- private readonly IRepository _itemRepository;
- private readonly IUriComposer _uriComposer;
-
- public CatalogItemGetByIdEndpoint(IRepository itemRepository, IUriComposer uriComposer)
- {
- _itemRepository = itemRepository;
- _uriComposer = uriComposer;
- }
-
public override void Configure()
{
Get("api/catalog-items/{catalogItemId}");
@@ -36,7 +27,7 @@ public override async Task, NotFound>> Ex
{
var response = new GetByIdCatalogItemResponse(request.CorrelationId());
- var item = await _itemRepository.GetByIdAsync(request.CatalogItemId, ct);
+ var item = await itemRepository.GetByIdAsync(request.CatalogItemId, ct);
if (item is null)
return TypedResults.NotFound();
@@ -47,7 +38,7 @@ public override async Task, NotFound>> Ex
CatalogTypeId = item.CatalogTypeId,
Description = item.Description,
Name = item.Name,
- PictureUri = _uriComposer.ComposePicUri(item.PictureUri),
+ PictureUri = uriComposer.ComposePicUri(item.PictureUri),
Price = item.Price
};
return TypedResults.Ok(response);
diff --git a/src/PublicApi/CatalogItemEndpoints/CatalogItemListPagedEndpoint.cs b/src/PublicApi/CatalogItemEndpoints/CatalogItemListPagedEndpoint.cs
index eb894336..bd33bd86 100644
--- a/src/PublicApi/CatalogItemEndpoints/CatalogItemListPagedEndpoint.cs
+++ b/src/PublicApi/CatalogItemEndpoints/CatalogItemListPagedEndpoint.cs
@@ -13,19 +13,10 @@ namespace Microsoft.eShopWeb.PublicApi.CatalogItemEndpoints;
///
/// List Catalog Items (paged)
///
-public class CatalogItemListPagedEndpoint : Endpoint
+public class CatalogItemListPagedEndpoint(IRepository itemRepository, IUriComposer uriComposer,
+ AutoMapper.IMapper mapper)
+ : Endpoint
{
- private readonly IRepository _itemRepository;
- private readonly IUriComposer _uriComposer;
- private readonly AutoMapper.IMapper _mapper;
-
- public CatalogItemListPagedEndpoint(IRepository itemRepository, IUriComposer uriComposer, AutoMapper.IMapper mapper)
- {
- _itemRepository = itemRepository;
- _uriComposer = uriComposer;
- _mapper = mapper;
- }
-
public override void Configure()
{
Get("api/catalog-items");
@@ -42,7 +33,7 @@ public override async Task ExecuteAsync(ListPagedC
var response = new ListPagedCatalogItemResponse(request.CorrelationId());
var filterSpec = new CatalogFilterSpecification(request.CatalogBrandId, request.CatalogTypeId);
- int totalItems = await _itemRepository.CountAsync(filterSpec, ct);
+ int totalItems = await itemRepository.CountAsync(filterSpec, ct);
var pagedSpec = new CatalogFilterPaginatedSpecification(
skip: request.PageIndex * request.PageSize,
@@ -50,12 +41,12 @@ public override async Task ExecuteAsync(ListPagedC
brandId: request.CatalogBrandId,
typeId: request.CatalogTypeId);
- var items = await _itemRepository.ListAsync(pagedSpec, ct);
+ var items = await itemRepository.ListAsync(pagedSpec, ct);
- response.CatalogItems.AddRange(items.Select(_mapper.Map));
+ response.CatalogItems.AddRange(items.Select(mapper.Map));
foreach (CatalogItemDto item in response.CatalogItems)
{
- item.PictureUri = _uriComposer.ComposePicUri(item.PictureUri);
+ item.PictureUri = uriComposer.ComposePicUri(item.PictureUri);
}
if (request.PageSize > 0)
diff --git a/src/PublicApi/CatalogItemEndpoints/CreateCatalogItemEndpoint.cs b/src/PublicApi/CatalogItemEndpoints/CreateCatalogItemEndpoint.cs
index 12ee6dc0..c974d761 100644
--- a/src/PublicApi/CatalogItemEndpoints/CreateCatalogItemEndpoint.cs
+++ b/src/PublicApi/CatalogItemEndpoints/CreateCatalogItemEndpoint.cs
@@ -13,17 +13,9 @@ namespace Microsoft.eShopWeb.PublicApi.CatalogItemEndpoints;
///
/// Creates a new Catalog Item
///
-public class CreateCatalogItemEndpoint : Endpoint
+public class CreateCatalogItemEndpoint(IRepository itemRepository, IUriComposer uriComposer)
+ : Endpoint
{
- private readonly IRepository _itemRepository;
- private readonly IUriComposer _uriComposer;
-
- public CreateCatalogItemEndpoint(IRepository itemRepository, IUriComposer uriComposer)
- {
- _itemRepository = itemRepository;
- _uriComposer = uriComposer;
- }
-
public override void Configure()
{
Post("api/catalog-items");
@@ -39,14 +31,14 @@ public override async Task HandleAsync(CreateCatalogItemRequest request, Cancell
var response = new CreateCatalogItemResponse(request.CorrelationId());
var catalogItemNameSpecification = new CatalogItemNameSpecification(request.Name);
- var existingCataloogItem = await _itemRepository.CountAsync(catalogItemNameSpecification, ct);
+ var existingCataloogItem = await itemRepository.CountAsync(catalogItemNameSpecification, ct);
if (existingCataloogItem > 0)
{
throw new DuplicateException($"A catalogItem with name {request.Name} already exists");
}
var newItem = new CatalogItem(request.CatalogTypeId, request.CatalogBrandId, request.Description, request.Name, request.Price, request.PictureUri);
- newItem = await _itemRepository.AddAsync(newItem, ct);
+ newItem = await itemRepository.AddAsync(newItem, ct);
if (newItem.Id != 0)
{
@@ -55,7 +47,7 @@ public override async Task HandleAsync(CreateCatalogItemRequest request, Cancell
// In production, we recommend uploading to a blob storage and deliver the image via CDN after a verification process.
newItem.UpdatePictureUri("eCatalog-item-default.png");
- await _itemRepository.UpdateAsync(newItem, ct);
+ await itemRepository.UpdateAsync(newItem, ct);
}
var dto = new CatalogItemDto
@@ -65,7 +57,7 @@ public override async Task HandleAsync(CreateCatalogItemRequest request, Cancell
CatalogTypeId = newItem.CatalogTypeId,
Description = newItem.Description,
Name = newItem.Name,
- PictureUri = _uriComposer.ComposePicUri(newItem.PictureUri),
+ PictureUri = uriComposer.ComposePicUri(newItem.PictureUri),
Price = newItem.Price
};
response.CatalogItem = dto;
diff --git a/src/PublicApi/CatalogItemEndpoints/DeleteCatalogItemEndpoint.cs b/src/PublicApi/CatalogItemEndpoints/DeleteCatalogItemEndpoint.cs
index 1dc992eb..2279ade4 100644
--- a/src/PublicApi/CatalogItemEndpoints/DeleteCatalogItemEndpoint.cs
+++ b/src/PublicApi/CatalogItemEndpoints/DeleteCatalogItemEndpoint.cs
@@ -12,15 +12,8 @@ namespace Microsoft.eShopWeb.PublicApi.CatalogItemEndpoints;
///
/// Deletes a Catalog Item
///
-public class DeleteCatalogItemEndpoint : Endpoint, NotFound>>
+public class DeleteCatalogItemEndpoint(IRepository itemRepository) : Endpoint, NotFound>>
{
- private readonly IRepository _itemRepository;
-
- public DeleteCatalogItemEndpoint(IRepository itemRepository)
- {
- _itemRepository = itemRepository;
- }
-
public override void Configure()
{
Delete("api/catalog-items/{catalogItemId}");
@@ -35,11 +28,11 @@ public override async Task, NotFound>> Exe
{
var response = new DeleteCatalogItemResponse(request.CorrelationId());
- var itemToDelete = await _itemRepository.GetByIdAsync(request.CatalogItemId, ct);
+ var itemToDelete = await itemRepository.GetByIdAsync(request.CatalogItemId, ct);
if (itemToDelete is null)
return TypedResults.NotFound();
- await _itemRepository.DeleteAsync(itemToDelete, ct);
+ await itemRepository.DeleteAsync(itemToDelete, ct);
return TypedResults.Ok(response);
}
diff --git a/src/PublicApi/CatalogItemEndpoints/UpdateCatalogItemEndpoint.cs b/src/PublicApi/CatalogItemEndpoints/UpdateCatalogItemEndpoint.cs
index ff23009b..aa6fd614 100644
--- a/src/PublicApi/CatalogItemEndpoints/UpdateCatalogItemEndpoint.cs
+++ b/src/PublicApi/CatalogItemEndpoints/UpdateCatalogItemEndpoint.cs
@@ -12,17 +12,9 @@ namespace Microsoft.eShopWeb.PublicApi.CatalogItemEndpoints;
///
/// Updates a Catalog Item
///
-public class UpdateCatalogItemEndpoint : Endpoint, NotFound>>
+public class UpdateCatalogItemEndpoint(IRepository itemRepository, IUriComposer uriComposer)
+ : Endpoint, NotFound>>
{
- private readonly IRepository _itemRepository;
- private readonly IUriComposer _uriComposer;
-
- public UpdateCatalogItemEndpoint(IRepository itemRepository, IUriComposer uriComposer)
- {
- _itemRepository = itemRepository;
- _uriComposer = uriComposer;
- }
-
public override void Configure()
{
Put("api/catalog-items");
@@ -37,7 +29,7 @@ public override async Task, NotFound>> Exe
{
var response = new UpdateCatalogItemResponse(request.CorrelationId());
- var existingItem = await _itemRepository.GetByIdAsync(request.Id, ct);
+ var existingItem = await itemRepository.GetByIdAsync(request.Id, ct);
if (existingItem == null)
{
return TypedResults.NotFound();
@@ -48,7 +40,7 @@ public override async Task, NotFound>> Exe
existingItem.UpdateBrand(request.CatalogBrandId);
existingItem.UpdateType(request.CatalogTypeId);
- await _itemRepository.UpdateAsync(existingItem, ct);
+ await itemRepository.UpdateAsync(existingItem, ct);
var dto = new CatalogItemDto
{
@@ -57,7 +49,7 @@ public override async Task, NotFound>> Exe
CatalogTypeId = existingItem.CatalogTypeId,
Description = existingItem.Description,
Name = existingItem.Name,
- PictureUri = _uriComposer.ComposePicUri(existingItem.PictureUri),
+ PictureUri = uriComposer.ComposePicUri(existingItem.PictureUri),
Price = existingItem.Price
};
response.CatalogItem = dto;
diff --git a/src/PublicApi/CatalogTypeEndpoints/CatalogTypeListEndpoint.cs b/src/PublicApi/CatalogTypeEndpoints/CatalogTypeListEndpoint.cs
index f0e21c53..7d8ac2c7 100644
--- a/src/PublicApi/CatalogTypeEndpoints/CatalogTypeListEndpoint.cs
+++ b/src/PublicApi/CatalogTypeEndpoints/CatalogTypeListEndpoint.cs
@@ -11,18 +11,9 @@ namespace Microsoft.eShopWeb.PublicApi.CatalogTypeEndpoints;
///
/// List Catalog Types
///
-public class CatalogTypeListEndpoint : EndpointWithoutRequest
+public class CatalogTypeListEndpoint(IRepository catalogTypeRepository, AutoMapper.IMapper mapper)
+ : EndpointWithoutRequest
{
- private readonly IRepository _catalogTypeRepository;
- private readonly AutoMapper.IMapper _mapper;
-
- public CatalogTypeListEndpoint(IRepository catalogTypeRepository, AutoMapper.IMapper mapper)
- {
- _catalogTypeRepository = catalogTypeRepository;
- _mapper = mapper;
-
- }
-
public override void Configure()
{
Get("api/catalog-types");
@@ -36,9 +27,9 @@ public override async Task ExecuteAsync(CancellationTo
{
var response = new ListCatalogTypesResponse();
- var items = await _catalogTypeRepository.ListAsync(ct);
+ var items = await catalogTypeRepository.ListAsync(ct);
- response.CatalogTypes.AddRange(items.Select(_mapper.Map));
+ response.CatalogTypes.AddRange(items.Select(mapper.Map));
return response;
}
diff --git a/src/PublicApi/Program.cs b/src/PublicApi/Program.cs
index 4d15ca74..bf517fb1 100644
--- a/src/PublicApi/Program.cs
+++ b/src/PublicApi/Program.cs
@@ -14,6 +14,9 @@
var builder = WebApplication.CreateBuilder(args);
+// Add service defaults & Aspire components.
+builder.AddAspireServiceDefaults();
+
builder.Services.AddFastEndpoints();
// Use to force loading of appsettings.json of test project
diff --git a/src/PublicApi/Properties/launchSettings.json b/src/PublicApi/Properties/launchSettings.json
index c44d516f..24081361 100644
--- a/src/PublicApi/Properties/launchSettings.json
+++ b/src/PublicApi/Properties/launchSettings.json
@@ -6,7 +6,8 @@
"launchUrl": "swagger",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
- }
+ },
+ "applicationUrl": "https://localhost:5099;http://localhost:5098"
},
"PublicApi": {
"commandName": "Project",
diff --git a/src/PublicApi/PublicApi.csproj b/src/PublicApi/PublicApi.csproj
index c6644a33..c5224b4d 100644
--- a/src/PublicApi/PublicApi.csproj
+++ b/src/PublicApi/PublicApi.csproj
@@ -32,6 +32,7 @@
+
diff --git a/src/Web/Configuration/BaseUrlConfiguration.cs b/src/Web/Configuration/BaseUrlConfiguration.cs
index 57f54df5..fe729b66 100644
--- a/src/Web/Configuration/BaseUrlConfiguration.cs
+++ b/src/Web/Configuration/BaseUrlConfiguration.cs
@@ -5,5 +5,4 @@ public class BaseUrlConfiguration
public const string CONFIG_NAME = "baseUrls";
public string ApiBase { get; set; } = string.Empty;
- public string WebBase { get; set; } = string.Empty;
}
diff --git a/src/Web/Extensions/ServiceCollectionExtensions.cs b/src/Web/Extensions/ServiceCollectionExtensions.cs
index 76fcba41..3a2c21f5 100644
--- a/src/Web/Extensions/ServiceCollectionExtensions.cs
+++ b/src/Web/Extensions/ServiceCollectionExtensions.cs
@@ -63,12 +63,11 @@ public static void AddBlazor(this IServiceCollection services, ConfigurationMana
{
var configSection = configuration.GetRequiredSection(BaseUrlConfiguration.CONFIG_NAME);
services.Configure(configSection);
- var baseUrlConfig = configSection.Get();
// Blazor Admin Required Services for Prerendering
services.AddScoped(s => new HttpClient
{
- BaseAddress = new Uri(baseUrlConfig!.WebBase)
+ BaseAddress = new Uri("https+http://blazoradmin")
});
// add blazor services
diff --git a/src/Web/Program.cs b/src/Web/Program.cs
index 8d5cd6bd..f30f93de 100644
--- a/src/Web/Program.cs
+++ b/src/Web/Program.cs
@@ -10,6 +10,9 @@
var builder = WebApplication.CreateBuilder(args);
+// Add service defaults & Aspire components.
+builder.AddAspireServiceDefaults();
+
builder.Services.AddDatabaseContexts(builder.Environment, builder.Configuration);
builder.Services.AddCookieSettings();
diff --git a/src/Web/Web.csproj b/src/Web/Web.csproj
index bf78d144..03cae8bb 100644
--- a/src/Web/Web.csproj
+++ b/src/Web/Web.csproj
@@ -42,6 +42,7 @@
+
diff --git a/src/Web/appsettings.Development.json b/src/Web/appsettings.Development.json
index bd6e47b6..f5275c28 100644
--- a/src/Web/appsettings.Development.json
+++ b/src/Web/appsettings.Development.json
@@ -1,7 +1,6 @@
{
"baseUrls": {
- "apiBase": "https://localhost:5099/api/",
- "webBase": "https://localhost:44315/"
+ "apiBase": "https://localhost:5099/api/"
},
"Logging": {
"LogLevel": {
diff --git a/src/Web/appsettings.Docker.json b/src/Web/appsettings.Docker.json
index 07ea75ea..f4c05627 100644
--- a/src/Web/appsettings.Docker.json
+++ b/src/Web/appsettings.Docker.json
@@ -4,8 +4,7 @@
"IdentityConnection": "Server=sqlserver,1433;Integrated Security=true;Initial Catalog=Microsoft.eShopOnWeb.Identity;User Id=sa;Password=@someThingComplicated1234;Trusted_Connection=false;TrustServerCertificate=true;"
},
"baseUrls": {
- "apiBase": "http://localhost:5200/api/",
- "webBase": "http://host.docker.internal:5106/"
+ "apiBase": "http://localhost:5200/api/"
},
"Logging": {
"LogLevel": {
diff --git a/src/Web/appsettings.json b/src/Web/appsettings.json
index c2bc6592..9a201d43 100644
--- a/src/Web/appsettings.json
+++ b/src/Web/appsettings.json
@@ -1,7 +1,6 @@
{
"baseUrls": {
- "apiBase": "https://localhost:5099/api/",
- "webBase": "https://localhost:44315/"
+ "apiBase": "https://localhost:5099/api/"
},
"ConnectionStrings": {
"CatalogConnection": "Server=(localdb)\\mssqllocaldb;Integrated Security=true;Initial Catalog=Microsoft.eShopOnWeb.CatalogDb;",
diff --git a/src/eShopWeb.AppHost/Program.cs b/src/eShopWeb.AppHost/Program.cs
new file mode 100644
index 00000000..b17f22f3
--- /dev/null
+++ b/src/eShopWeb.AppHost/Program.cs
@@ -0,0 +1,9 @@
+var builder = DistributedApplication.CreateBuilder(args);
+
+builder
+ .AddProject(nameof(Projects.PublicApi).ToLower());
+
+builder
+ .AddProject(nameof(Projects.Web).ToLower());
+
+builder.Build().Run();
diff --git a/src/eShopWeb.AppHost/Properties/launchSettings.json b/src/eShopWeb.AppHost/Properties/launchSettings.json
new file mode 100644
index 00000000..67077308
--- /dev/null
+++ b/src/eShopWeb.AppHost/Properties/launchSettings.json
@@ -0,0 +1,29 @@
+{
+ "$schema": "https://json.schemastore.org/launchsettings.json",
+ "profiles": {
+ "https": {
+ "commandName": "Project",
+ "dotnetRunMessages": true,
+ "launchBrowser": true,
+ "applicationUrl": "https://localhost:17177;http://localhost:15038",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development",
+ "DOTNET_ENVIRONMENT": "Development",
+ "DOTNET_DASHBOARD_OTLP_ENDPOINT_URL": "https://localhost:21066",
+ "DOTNET_RESOURCE_SERVICE_ENDPOINT_URL": "https://localhost:22107"
+ }
+ },
+ "http": {
+ "commandName": "Project",
+ "dotnetRunMessages": true,
+ "launchBrowser": true,
+ "applicationUrl": "http://localhost:15038",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development",
+ "DOTNET_ENVIRONMENT": "Development",
+ "DOTNET_DASHBOARD_OTLP_ENDPOINT_URL": "http://localhost:19018",
+ "DOTNET_RESOURCE_SERVICE_ENDPOINT_URL": "http://localhost:20071"
+ }
+ }
+ }
+}
diff --git a/src/eShopWeb.AppHost/appsettings.Development.json b/src/eShopWeb.AppHost/appsettings.Development.json
new file mode 100644
index 00000000..0c208ae9
--- /dev/null
+++ b/src/eShopWeb.AppHost/appsettings.Development.json
@@ -0,0 +1,8 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft.AspNetCore": "Warning"
+ }
+ }
+}
diff --git a/src/eShopWeb.AppHost/appsettings.json b/src/eShopWeb.AppHost/appsettings.json
new file mode 100644
index 00000000..31c092aa
--- /dev/null
+++ b/src/eShopWeb.AppHost/appsettings.json
@@ -0,0 +1,9 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft.AspNetCore": "Warning",
+ "Aspire.Hosting.Dcp": "Warning"
+ }
+ }
+}
diff --git a/src/eShopWeb.AppHost/eShopWeb.AppHost.csproj b/src/eShopWeb.AppHost/eShopWeb.AppHost.csproj
new file mode 100644
index 00000000..73768c84
--- /dev/null
+++ b/src/eShopWeb.AppHost/eShopWeb.AppHost.csproj
@@ -0,0 +1,22 @@
+
+
+
+ Exe
+ net8.0
+ enable
+ enable
+ true
+ 5d5c1626-3c2a-4ec3-96b3-240241479084
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/eShopWeb.AspireServiceDefaults/Extensions.cs b/src/eShopWeb.AspireServiceDefaults/Extensions.cs
new file mode 100644
index 00000000..ec658674
--- /dev/null
+++ b/src/eShopWeb.AspireServiceDefaults/Extensions.cs
@@ -0,0 +1,126 @@
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Diagnostics.HealthChecks;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Diagnostics.HealthChecks;
+using Microsoft.Extensions.Logging;
+using OpenTelemetry;
+using OpenTelemetry.Metrics;
+using OpenTelemetry.Trace;
+
+namespace Microsoft.Extensions.Hosting;
+// Adds common .NET Aspire services: service discovery, resilience, health checks, and OpenTelemetry.
+// This project should be referenced by each service project in your solution.
+// To learn more about using this project, see https://aka.ms/dotnet/aspire/service-defaults
+public static class Extensions
+{
+ public static IHostApplicationBuilder AddAspireServiceDefaults(this IHostApplicationBuilder builder)
+ {
+ builder.ConfigureOpenTelemetry();
+
+ builder.AddDefaultHealthChecks();
+
+ builder.Services.AddServiceDiscovery();
+
+ builder.Services.ConfigureHttpClientDefaults(http =>
+ {
+ // Turn on resilience by default
+ http.AddStandardResilienceHandler();
+
+ // Turn on service discovery by default
+ http.AddServiceDiscovery();
+ });
+
+ // Uncomment the following to restrict the allowed schemes for service discovery.
+ // builder.Services.Configure(options =>
+ // {
+ // options.AllowedSchemes = ["https"];
+ // });
+
+ return builder;
+ }
+
+ public static IHostApplicationBuilder ConfigureOpenTelemetry(this IHostApplicationBuilder builder)
+ {
+ builder.Logging.AddOpenTelemetry(logging =>
+ {
+ logging.IncludeFormattedMessage = true;
+ logging.IncludeScopes = true;
+ });
+
+ builder.Services.AddOpenTelemetry()
+ .WithMetrics(metrics =>
+ {
+ metrics.AddAspNetCoreInstrumentation()
+ .AddHttpClientInstrumentation()
+ .AddRuntimeInstrumentation()
+ .AddMeter(
+ "Microsoft.AspNetCore.Hosting",
+ "Microsoft.AspNetCore.Server.Kestrel",
+ "System.Net.Http"
+ );
+ })
+ .WithTracing(tracing =>
+ {
+ if (builder.Environment.IsDevelopment())
+ {
+ tracing.SetSampler();
+ }
+ tracing.AddAspNetCoreInstrumentation()
+ .AddHttpClientInstrumentation();
+ });
+
+ builder.AddOpenTelemetryExporters();
+
+ return builder;
+ }
+
+ private static IHostApplicationBuilder AddOpenTelemetryExporters(this IHostApplicationBuilder builder)
+ {
+ var useOtlpExporter = !string.IsNullOrWhiteSpace(builder.Configuration["OTEL_EXPORTER_OTLP_ENDPOINT"]);
+
+ if (useOtlpExporter)
+ {
+ builder.Services.AddOpenTelemetry().UseOtlpExporter();
+ }
+
+ builder.Services.AddOpenTelemetry().WithMetrics(x => x.AddPrometheusExporter());
+ // Uncomment the following lines to enable the Azure Monitor exporter (requires the Azure.Monitor.OpenTelemetry.AspNetCore package)
+ //if (!string.IsNullOrEmpty(builder.Configuration["APPLICATIONINSIGHTS_CONNECTION_STRING"]))
+ //{
+ // builder.Services.AddOpenTelemetry()
+ // .UseAzureMonitor();
+ //}
+
+ return builder;
+ }
+
+ public static IHostApplicationBuilder AddDefaultHealthChecks(this IHostApplicationBuilder builder)
+ {
+ builder.Services.AddHealthChecks()
+ // Add a default liveness check to ensure app is responsive
+ .AddCheck("self", () => HealthCheckResult.Healthy(), ["live"]);
+
+ return builder;
+ }
+
+ public static WebApplication MapDefaultEndpoints(this WebApplication app)
+ {
+ app.MapPrometheusScrapingEndpoint();
+
+ // Adding health checks endpoints to applications in non-development environments has security implications.
+ // See https://aka.ms/dotnet/aspire/healthchecks for details before enabling these endpoints in non-development environments.
+ if (app.Environment.IsDevelopment())
+ {
+ // All health checks must pass for app to be considered ready to accept traffic after starting
+ app.MapHealthChecks("/health");
+
+ // Only health checks tagged with the "live" tag must pass for app to be considered alive
+ app.MapHealthChecks("/alive", new HealthCheckOptions
+ {
+ Predicate = r => r.Tags.Contains("live")
+ });
+ }
+
+ return app;
+ }
+}
diff --git a/src/eShopWeb.AspireServiceDefaults/eShopWeb.AspireServiceDefaults.csproj b/src/eShopWeb.AspireServiceDefaults/eShopWeb.AspireServiceDefaults.csproj
new file mode 100644
index 00000000..4a91dfba
--- /dev/null
+++ b/src/eShopWeb.AspireServiceDefaults/eShopWeb.AspireServiceDefaults.csproj
@@ -0,0 +1,23 @@
+
+
+
+ net8.0
+ enable
+ enable
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+