From d556d3282905cb2778c21a50a7f5da4683a8e0b4 Mon Sep 17 00:00:00 2001 From: daniel-c-harvey Date: Thu, 4 Sep 2025 09:48:58 -0400 Subject: [PATCH] Inject framework HttpClient to support prerendering behavior on server instead of baking in the HttpClient on the client project --- DeepDrftModels/Entities/TrackEntity.cs | 6 ++-- DeepDrftWeb.Client/Clients/TrackClient.cs | 30 +++++++++++--------- DeepDrftWeb.Client/DeepDrftWeb.Client.csproj | 1 + DeepDrftWeb.Client/Program.cs | 5 +++- DeepDrftWeb.Client/Startup.cs | 6 +--- DeepDrftWeb/DeepDrftWeb.csproj | 5 ---- DeepDrftWeb/Program.cs | 10 ++++--- DeepDrftWeb/Startup.cs | 26 +++++++++++++++++ DeepDrftWeb/appsettings.Development.json | 3 +- 9 files changed, 59 insertions(+), 33 deletions(-) diff --git a/DeepDrftModels/Entities/TrackEntity.cs b/DeepDrftModels/Entities/TrackEntity.cs index ee82ef7..9c0ae77 100644 --- a/DeepDrftModels/Entities/TrackEntity.cs +++ b/DeepDrftModels/Entities/TrackEntity.cs @@ -3,9 +3,9 @@ public class TrackEntity { public long Id { get; set; } - public string MediaPath { get; set; } - public string TrackName { get; set; } - public string Artist { get; set; } + public required string MediaPath { get; set; } + public required string TrackName { get; set; } + public required string Artist { get; set; } public string? Album { get; set; } public string? Genre { get; set; } public DateOnly? ReleaseDate { get; set; } diff --git a/DeepDrftWeb.Client/Clients/TrackClient.cs b/DeepDrftWeb.Client/Clients/TrackClient.cs index 68f363e..11c14e8 100644 --- a/DeepDrftWeb.Client/Clients/TrackClient.cs +++ b/DeepDrftWeb.Client/Clients/TrackClient.cs @@ -3,12 +3,18 @@ using DeepDrftModels.Models; using NetBlocks.Models; using System.Text.Json; using System.Web; +using Microsoft.AspNetCore.Http; namespace DeepDrftWeb.Client.Clients; -public class TrackClient : ApiClient +public class TrackClient { - public TrackClient(ClientConfig config) : base(config) { } + private readonly HttpClient _http; + + public TrackClient(HttpClient http) + { + _http = http; + } public async Task>> GetPage( int pageNumber, @@ -16,24 +22,20 @@ public class TrackClient : ApiClient string? sortColumn = null, bool sortDescending = false) { - var uriBuilder = new UriBuilder(http.BaseAddress!) - { - Path = "api/track/page" + var queryArgs = new Dictionary(){ + ["pageNumber"] = pageNumber.ToString(), + ["pageSize"] = pageSize.ToString() }; - - var query = HttpUtility.ParseQueryString(string.Empty); - query["pageNumber"] = pageNumber.ToString(); - query["pageSize"] = pageSize.ToString(); if (!string.IsNullOrEmpty(sortColumn)) - query["sortColumn"] = sortColumn; + queryArgs["sortColumn"] = sortColumn; if (sortDescending) - query["sortDescending"] = "true"; + queryArgs["sortDescending"] = "true"; - uriBuilder.Query = query.ToString(); - - var response = await http.GetAsync(uriBuilder.Uri); + string query = QueryString.Create(queryArgs).ToString(); + + var response = await _http.GetAsync($"api/track/page{query}"); var json = await response.Content.ReadAsStringAsync(); var dto = JsonSerializer.Deserialize>>(json, new JsonSerializerOptions diff --git a/DeepDrftWeb.Client/DeepDrftWeb.Client.csproj b/DeepDrftWeb.Client/DeepDrftWeb.Client.csproj index 0dddea3..252cb11 100644 --- a/DeepDrftWeb.Client/DeepDrftWeb.Client.csproj +++ b/DeepDrftWeb.Client/DeepDrftWeb.Client.csproj @@ -10,6 +10,7 @@ + diff --git a/DeepDrftWeb.Client/Program.cs b/DeepDrftWeb.Client/Program.cs index 36a64fe..eb7e4e0 100644 --- a/DeepDrftWeb.Client/Program.cs +++ b/DeepDrftWeb.Client/Program.cs @@ -4,8 +4,11 @@ using MudBlazor.Services; var builder = WebAssemblyHostBuilder.CreateDefault(args); +Console.WriteLine(builder.HostEnvironment.BaseAddress); +builder.Services.AddScoped(_ => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) }); + builder.Services.AddMudServices(); -Startup.ConfigureDomainServices(builder.Services, builder.HostEnvironment.BaseAddress); +Startup.ConfigureDomainServices(builder.Services); await builder.Build().RunAsync(); diff --git a/DeepDrftWeb.Client/Startup.cs b/DeepDrftWeb.Client/Startup.cs index 3a7c015..be03d76 100644 --- a/DeepDrftWeb.Client/Startup.cs +++ b/DeepDrftWeb.Client/Startup.cs @@ -7,13 +7,9 @@ namespace DeepDrftWeb.Client; public static class Startup { - public static void ConfigureDomainServices(IServiceCollection services, string baseAddress) + public static void ConfigureDomainServices(IServiceCollection services) { - // HTTP Client for Server API - services.AddScoped(_ => new HttpClient { BaseAddress = new Uri(baseAddress) }); - // Track Client - services.AddSingleton(new ClientConfig(baseAddress)); services.AddScoped(); services.AddScoped(); } diff --git a/DeepDrftWeb/DeepDrftWeb.csproj b/DeepDrftWeb/DeepDrftWeb.csproj index 9985ab1..58c8c02 100644 --- a/DeepDrftWeb/DeepDrftWeb.csproj +++ b/DeepDrftWeb/DeepDrftWeb.csproj @@ -24,9 +24,4 @@ - - - - - \ No newline at end of file diff --git a/DeepDrftWeb/Program.cs b/DeepDrftWeb/Program.cs index 2ad406d..4c0db10 100644 --- a/DeepDrftWeb/Program.cs +++ b/DeepDrftWeb/Program.cs @@ -1,18 +1,20 @@ using DeepDrftWeb; using MudBlazor.Services; using DeepDrftWeb.Components; -using DeepDrftWeb.Data; -using Microsoft.EntityFrameworkCore; var builder = WebApplication.CreateBuilder(args); // Add MudBlazor services builder.Services.AddMudServices(); +// Add HttpClient services for prerendering +builder.Services.AddHttpClient("DeepDrft.API", client => client.BaseAddress = new Uri(Startup.GetKestrelUrl(builder))); +builder.Services.AddScoped(sp => + sp.GetRequiredService().CreateClient("DeepDrft.API")); + Startup.ConfigureDomainServices(builder); -var hostUrl = builder.Configuration.GetValue("ASPNETCORE_URLS")?.Split(';').First() ?? throw new Exception("ASPNETCORE_URLS undefined"); -DeepDrftWeb.Client.Startup.ConfigureDomainServices(builder.Services, hostUrl); +DeepDrftWeb.Client.Startup.ConfigureDomainServices(builder.Services); builder.Services.AddControllers(); diff --git a/DeepDrftWeb/Startup.cs b/DeepDrftWeb/Startup.cs index a61d3b1..f1c46d8 100644 --- a/DeepDrftWeb/Startup.cs +++ b/DeepDrftWeb/Startup.cs @@ -16,6 +16,32 @@ public static class Startup // Add Track services builder.Services.AddScoped(); builder.Services.AddScoped(); + } + + public static string GetKestrelUrl(this WebApplicationBuilder builder) + { + // Check all the places Kestrel URL can be configured + var urls = builder.Configuration["ASPNETCORE_URLS"] + ?? builder.Configuration["urls"]; + + if (!string.IsNullOrEmpty(urls)) + { + return urls.Split(';')[0].Trim(); + } + // Check Kestrel endpoints configuration + var kestrelSection = builder.Configuration.GetSection("Kestrel:Endpoints"); + var firstEndpoint = kestrelSection.GetChildren().FirstOrDefault(); + var endpointUrl = firstEndpoint?["Url"]; + + if (!string.IsNullOrEmpty(endpointUrl)) + { + return endpointUrl; + } + + // ASP.NET Core defaults + return builder.Environment.IsDevelopment() + ? "https://localhost:5001" + : "http://localhost:5000"; } } \ No newline at end of file diff --git a/DeepDrftWeb/appsettings.Development.json b/DeepDrftWeb/appsettings.Development.json index 0c208ae..f8063ef 100644 --- a/DeepDrftWeb/appsettings.Development.json +++ b/DeepDrftWeb/appsettings.Development.json @@ -4,5 +4,6 @@ "Default": "Information", "Microsoft.AspNetCore": "Warning" } - } + }, + "DetailedErrors": true }