-
Notifications
You must be signed in to change notification settings - Fork 36
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
8d7143c
commit d6502f8
Showing
37 changed files
with
2,185 additions
and
0 deletions.
There are no files selected for viewing
21 changes: 21 additions & 0 deletions
21
labs/1-Create-Catalog-API/end/Catalog.API/Catalog.API.csproj
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
<Project Sdk="Microsoft.NET.Sdk.Web"> | ||
|
||
<PropertyGroup> | ||
<TargetFramework>net8.0</TargetFramework> | ||
<Nullable>enable</Nullable> | ||
<ImplicitUsings>enable</ImplicitUsings> | ||
<InvariantGlobalization>true</InvariantGlobalization> | ||
<ManagePackageVersionsCentrally>false</ManagePackageVersionsCentrally> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="8.0.1" /> | ||
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" /> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<ProjectReference Include="..\Catalog.Data\Catalog.Data.csproj" /> | ||
<ProjectReference Include="..\eShop.ServiceDefaults\eShop.ServiceDefaults.csproj" /> | ||
</ItemGroup> | ||
|
||
</Project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
@Catalog.API_HostAddress = http://localhost:5180 | ||
|
||
GET {{Catalog.API_HostAddress}}/items/ | ||
Accept: application/json | ||
|
||
### |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
using eShop.Catalog.API.Model; | ||
using eShop.Catalog.Data; | ||
using Microsoft.EntityFrameworkCore; | ||
|
||
namespace Microsoft.AspNetCore.Builder; | ||
|
||
public static class CatalogApi | ||
{ | ||
public static IEndpointRouteBuilder MapCatalogApi(this IEndpointRouteBuilder app) | ||
{ | ||
app.MapGet("/items", async ([AsParameters] PaginationRequest paginationRequest, CatalogDbContext db) => | ||
{ | ||
var pageSize = paginationRequest.PageSize; | ||
var pageIndex = paginationRequest.PageIndex; | ||
|
||
var totalItems = await db.CatalogItems | ||
.LongCountAsync(); | ||
|
||
var itemsOnPage = await db.CatalogItems | ||
.OrderBy(c => c.Name) | ||
.Skip(pageSize * pageIndex) | ||
.Take(pageSize) | ||
.AsNoTracking() | ||
.ToListAsync(); | ||
|
||
return new PaginatedItems<CatalogItem>(pageIndex, pageSize, totalItems, itemsOnPage); | ||
}); | ||
|
||
return app; | ||
} | ||
} |
13 changes: 13 additions & 0 deletions
13
labs/1-Create-Catalog-API/end/Catalog.API/Model/PaginatedItems.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
namespace eShop.Catalog.API.Model; | ||
|
||
public class PaginatedItems<TItem>(int pageIndex, int pageSize, long count, IEnumerable<TItem> data) | ||
where TItem : class | ||
{ | ||
public int PageIndex { get; } = pageIndex; | ||
|
||
public int PageSize { get; } = pageSize; | ||
|
||
public long Count { get; } = count; | ||
|
||
public IEnumerable<TItem> Data { get; } = data; | ||
} |
8 changes: 8 additions & 0 deletions
8
labs/1-Create-Catalog-API/end/Catalog.API/Model/PaginationRequest.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
namespace eShop.Catalog.API.Model; | ||
|
||
public readonly struct PaginationRequest(int pageSize = 5, int pageIndex = 0) | ||
{ | ||
public readonly int PageSize { get; } = pageSize; | ||
|
||
public readonly int PageIndex { get; } = pageIndex; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
using eShop.Catalog.Data; | ||
|
||
var builder = WebApplication.CreateBuilder(args); | ||
|
||
builder.AddServiceDefaults(); | ||
|
||
builder.AddNpgsqlDbContext<CatalogDbContext>("CatalogDB"); | ||
|
||
// Add services to the container. | ||
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle | ||
builder.Services.AddEndpointsApiExplorer(); | ||
builder.Services.AddSwaggerGen(); | ||
|
||
var app = builder.Build(); | ||
|
||
app.MapDefaultEndpoints(); | ||
|
||
// Configure the HTTP request pipeline. | ||
if (app.Environment.IsDevelopment()) | ||
{ | ||
app.UseSwagger(); | ||
app.UseSwaggerUI(); | ||
} | ||
|
||
app.MapCatalogApi(); | ||
|
||
app.Run(); | ||
|
31 changes: 31 additions & 0 deletions
31
labs/1-Create-Catalog-API/end/Catalog.API/Properties/launchSettings.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
{ | ||
"$schema": "http://json.schemastore.org/launchsettings.json", | ||
"iisSettings": { | ||
"windowsAuthentication": false, | ||
"anonymousAuthentication": true, | ||
"iisExpress": { | ||
"applicationUrl": "http://localhost:63531", | ||
"sslPort": 0 | ||
} | ||
}, | ||
"profiles": { | ||
"http": { | ||
"commandName": "Project", | ||
"dotnetRunMessages": true, | ||
"launchBrowser": true, | ||
"launchUrl": "swagger", | ||
"applicationUrl": "http://localhost:5180", | ||
"environmentVariables": { | ||
"ASPNETCORE_ENVIRONMENT": "Development" | ||
} | ||
}, | ||
"IIS Express": { | ||
"commandName": "IISExpress", | ||
"launchBrowser": true, | ||
"launchUrl": "swagger", | ||
"environmentVariables": { | ||
"ASPNETCORE_ENVIRONMENT": "Development" | ||
} | ||
} | ||
} | ||
} |
8 changes: 8 additions & 0 deletions
8
labs/1-Create-Catalog-API/end/Catalog.API/appsettings.Development.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
{ | ||
"Logging": { | ||
"LogLevel": { | ||
"Default": "Information", | ||
"Microsoft.AspNetCore": "Warning" | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
{ | ||
"Logging": { | ||
"LogLevel": { | ||
"Default": "Information", | ||
"Microsoft.AspNetCore": "Warning" | ||
} | ||
}, | ||
"AllowedHosts": "*" | ||
} |
33 changes: 33 additions & 0 deletions
33
labs/1-Create-Catalog-API/end/Catalog.Data.Manager/Catalog.Data.Manager.csproj
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
<Project Sdk="Microsoft.NET.Sdk.Web"> | ||
|
||
<PropertyGroup> | ||
<TargetFramework>net8.0</TargetFramework> | ||
<RootNamespace>eShop.Catalog.Data.Manager</RootNamespace> | ||
<Nullable>enable</Nullable> | ||
<ImplicitUsings>enable</ImplicitUsings> | ||
<ManagePackageVersionsCentrally>false</ManagePackageVersionsCentrally> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<ProjectReference Include="..\Catalog.Data\Catalog.Data.csproj" /> | ||
<ProjectReference Include="..\eShop.ServiceDefaults\eShop.ServiceDefaults.csproj" /> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<PackageReference Include="Aspire.Npgsql.EntityFrameworkCore.PostgreSQL" Version="8.0.0-preview.3.24081.13" /> | ||
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.1"> | ||
<PrivateAssets>all</PrivateAssets> | ||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> | ||
</PackageReference> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<Compile Include="..\Shared\ActivityExtensions.cs" Link="Extensions\ActivityExtensions.cs" /> | ||
<Compile Include="..\Shared\MigrateDbContextExtensions.cs" Link="Extensions\MigrateDbContextExtensions.cs" /> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<Folder Include="Migrations\" /> | ||
</ItemGroup> | ||
|
||
</Project> |
70 changes: 70 additions & 0 deletions
70
labs/1-Create-Catalog-API/end/Catalog.Data.Manager/CatalogContextSeed.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
using System.Text.Json; | ||
using Microsoft.EntityFrameworkCore; | ||
using Npgsql; | ||
|
||
namespace eShop.Catalog.Data.Manager; | ||
|
||
public partial class CatalogContextSeed(IWebHostEnvironment env, ILogger<CatalogContextSeed> logger) | ||
: IDbSeeder<CatalogDbContext> | ||
{ | ||
public async Task SeedAsync(CatalogDbContext context) | ||
{ | ||
var contentRootPath = env.ContentRootPath; | ||
var picturePath = env.WebRootPath; | ||
|
||
// Workaround from https://github.com/npgsql/efcore.pg/issues/292#issuecomment-388608426 | ||
context.Database.OpenConnection(); | ||
((NpgsqlConnection)context.Database.GetDbConnection()).ReloadTypes(); | ||
|
||
if (!context.CatalogItems.Any()) | ||
{ | ||
var sourcePath = Path.Combine(contentRootPath, "Setup", "catalog.json"); | ||
var sourceJson = File.ReadAllText(sourcePath); | ||
var sourceItems = JsonSerializer.Deserialize<CatalogSourceEntry[]>(sourceJson) | ||
?? throw new InvalidOperationException($"Seed data file was found but it contained no data: '{sourcePath}'"); | ||
|
||
context.CatalogBrands.RemoveRange(context.CatalogBrands); | ||
await context.CatalogBrands.AddRangeAsync(sourceItems.Select(x => x.Brand).Distinct() | ||
.Select(brandName => new CatalogBrand { Brand = brandName })); | ||
logger.LogInformation("Seeded catalog with {NumBrands} brands", context.CatalogBrands.Count()); | ||
|
||
context.CatalogTypes.RemoveRange(context.CatalogTypes); | ||
await context.CatalogTypes.AddRangeAsync(sourceItems.Select(x => x.Type).Distinct() | ||
.Select(typeName => new CatalogType { Type = typeName })); | ||
logger.LogInformation("Seeded catalog with {NumTypes} types", context.CatalogTypes.Count()); | ||
|
||
await context.SaveChangesAsync(); | ||
|
||
var brandIdsByName = await context.CatalogBrands.ToDictionaryAsync(x => x.Brand, x => x.Id); | ||
var typeIdsByName = await context.CatalogTypes.ToDictionaryAsync(x => x.Type, x => x.Id); | ||
|
||
await context.CatalogItems.AddRangeAsync(sourceItems.Select(source => new CatalogItem | ||
{ | ||
Id = source.Id, | ||
Name = source.Name, | ||
Description = source.Description, | ||
Price = source.Price, | ||
CatalogBrandId = brandIdsByName[source.Brand], | ||
CatalogTypeId = typeIdsByName[source.Type], | ||
AvailableStock = 100, | ||
MaxStockThreshold = 200, | ||
RestockThreshold = 10, | ||
PictureFileName = $"{source.Id}.webp" | ||
})); | ||
|
||
logger.LogInformation("Seeded catalog with {NumItems} items", context.CatalogItems.Count()); | ||
|
||
await context.SaveChangesAsync(); | ||
} | ||
} | ||
|
||
private class CatalogSourceEntry | ||
{ | ||
public int Id { get; set; } | ||
public required string Type { get; set; } | ||
public required string Brand { get; set; } | ||
public required string Name { get; set; } | ||
public required string Description { get; set; } | ||
public decimal Price { get; set; } | ||
} | ||
} |
Oops, something went wrong.