Address remaining Blazor integration PR feedback#17384
Conversation
0fa6022 to
910da9e
Compare
|
🚀 Dogfood this PR with:
curl -fsSL https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.sh | bash -s -- 17384Or
iex "& { $(irm https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.ps1) } 17384" |
9b4238d to
4be1b69
Compare
There was a problem hiding this comment.
Pull request overview
Note
Copilot was unable to run its full agentic suite in this review.
This PR refactors how the Blazor gateway generates the WASM client configuration response, aiming to produce deployer-configurable manifest expressions while keeping dev-time behavior working, and also improves gateway publish/build inputs (image tag stamping, file locations).
Changes:
- Replace the per-app
IValueProviderconfig generator with aReferenceExpression-based JSON builder using a gateway-origin placeholder. - Improve manifest processing robustness (explicit deserialization failure) and make the
index.htmlroute match case-insensitive. - Stamp/control the .NET Docker image tag via assembly metadata and adjust where gateway/publish artifacts are written/copied.
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| src/Aspire.Hosting.Blazor/Scripts/Gateway.cs.in | Tighten nullability for ConfigResponse emission in the gateway script. |
| src/Aspire.Hosting.Blazor/Manifests/EndpointsManifestTransformer.cs | Add explicit deserialize failure and case-insensitive index.html detection. |
| src/Aspire.Hosting.Blazor/GatewayOriginReference.cs | New helper to emit a deployer-resolvable origin placeholder while resolving dev-time values. |
| src/Aspire.Hosting.Blazor/GatewayConfigurationBuilder.cs | Major refactor: build config JSON as a ReferenceExpression and remove logger-based warning path. |
| src/Aspire.Hosting.Blazor/BlazorHostedExtensions.cs | Adjust call site for the new config builder signature. |
| src/Aspire.Hosting.Blazor/BlazorGatewayExtensions.cs | Add [ResourceName], change artifact paths, and revise .NET image tag resolution logic. |
| src/Aspire.Hosting.Blazor/Aspire.Hosting.Blazor.csproj | Add BlazorGatewayDotNetImageTag property and stamp it into assembly metadata. |
| playground/BlazorStandalone/README.md | Documentation wording update (“Aspire” instead of “.NET Aspire”). |
| playground/BlazorHosted/README.md | Documentation wording update (“Aspire” instead of “.NET Aspire”). |
PR feedback from microsoft#15691: - Add [ResourceName] attribute to all Add* API name parameters - Replace null-forgiving operator with explicit throw in EndpointsManifestTransformer - Use StringComparison.OrdinalIgnoreCase for route comparison - Fix '.NET Aspire' phrasing in README files Docker Compose publish fixes for Blazor gateway: - Add GatewayOriginReference (IValueProvider + IManifestExpressionProvider) - Use ReferenceExpression for ConfigResponse so publishers emit proper placeholders - Use TextEncoderSettings to escape braces in JSON string values - Simplify Gateway.cs.in (serve ConfigResponse directly, no Replace logic) - Add System.Text.Unicode dependency for brace-escaping encoder Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
4be1b69 to
ae9ce87
Compare
JamesNK
left a comment
There was a problem hiding this comment.
One issue found: missing OTLP misconfiguration warning in the hosted Blazor path (BlazorHostedExtensions.cs). The rest of the changes look correct.
The standalone gateway path already logged a warning when telemetry proxying was requested but no HTTP OTLP endpoint could be resolved. The hosted model (ProxyBlazorTelemetry via BlazorHostedExtensions) was missing the equivalent diagnostic. - Add LogWarning in BlazorHostedExtensions.EnsureEnvironmentCallback - Add tests verifying the warning fires (and does not fire) in both scenarios Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Use the standard OpenTelemetry environment variable name instead of a custom Aspire-specific one. The value remains a relative path that the WASM client resolves against its page origin to stay same-origin. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Replace private ListLogger and LogMessage with shared TestSink and TestLogger from Microsoft.Extensions.Logging.Testing. Also moves the OTLP warning in the standalone gateway path before the build step so it is testable, and adds two tests for that path. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The gateway and hosted server YARP proxies forward /_otlp/* requests to the dashboard. Without filtering, those forwarding requests are themselves traced and exported, creating recursive telemetry entries. - Gateway (Gateway.cs.in): Simplified filter to use Contains for /_otlp/ paths (handles prefix-mounted apps like /app/_otlp/...). Removed IsStaticAssetOrOtlpRequest helper since static asset requests don't go through YARP. - Hosted server (Program.cs): Added PostConfigure to wrap existing OTEL filters with /_otlp/ and /v1/ exclusions. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
Fixed the OTLP proxy trace feedback loop in b11bae8 — added trace filtering for both gateway (\Gateway.cs.in) and hosted server (\Program.cs). The gateway filters /_otlp/\ from ASP.NET Core traces and /v1/\ from HttpClient traces. The hosted server uses \PostConfigure\ to wrap existing filters with the same exclusions. Verified both scenarios manually — OTLP proxy traffic no longer appears in dashboard traces. |
|
Let me know if the issue above is something to fix and if you want to fix it now. Or we can just merge now and I'll backport this to the release branch. |
We can merge now |
| /// </summary> | ||
| internal sealed class GatewayOriginReference(EndpointReference endpoint) : IValueProvider, IManifestExpressionProvider | ||
| { | ||
| public string ValueExpression => $"{{{endpoint.Resource.Name}.bindings.{endpoint.EndpointName}.url}}"; |
There was a problem hiding this comment.
When I tried aspire publish with docker compose, the endpoint url was resolving to the internal docker host URL as opposed to the "public" one and the deployed app was failing. The only way I found to solve it is to make it an expression that then gets converted into a parameter in the docker compose file and populated with the appropriate value.
There was a problem hiding this comment.
Ah this problem. Did you try other targets as well?
There was a problem hiding this comment.
I did try ACA in the original prototype, but as far as I remember, it didn't have this problem. I believe there is something unique to the docker-compose support, where it picks the internal endpoint over the public one.
To be very clear and fair, I'm a bit on an unsecure footing in this area of aspire yet.
I can try other targets in the following days too, but which ones would you recommend me to try?
PR Testing ReportPR Information
CLI Version Verification
Changes AnalyzedFiles Changed
Change Categories
Test Scenarios ExecutedScenario 1: PR CLI install/version verificationObjective: Install the PR CLI from the dogfood command and verify it matches the PR head commit. Steps:
Evidence:
Observations:
Scenario 2: Empty AppHost baselineObjective: Verify PR CLI can create and run a fresh C# Aspire AppHost after the container receives the required .NET SDK. Steps:
Evidence:
Observations:
Scenario 3: Standalone Blazor gateway service proxy smokeObjective: Create a fresh standalone Blazor WASM + Web API app, attach it to Steps:
Evidence:
Observations:
{"webAssembly":{"environment":{"services__weatherapi__https__0":"https://localhost:38077/store/_api/weatherapi","services__weatherapi__http__0":"https://localhost:38077/store/_api/weatherapi"}}}Scenario 4: Standalone Blazor gateway telemetry configObjective: Verify Steps:
Evidence:
Expected:
Actual:
{"webAssembly":{"environment":{"services__weatherapi__https__0":"https://localhost:40909/store/_api/weatherapi","services__weatherapi__http__0":"https://localhost:40909/store/_api/weatherapi"}}}Analysis:
Scenario 5: Hosted Blazor telemetry configObjective: Verify Steps:
Evidence:
Expected:
Actual:
{"webAssembly":{"environment":{"services__weatherapi__http__0":"http://localhost:44627/_api/weatherapi"}}}Analysis:
Scenario 6: Existing output directory negative caseObjective: Verify non-interactive Steps:
Evidence:
Observed outcome:
Scenario 7: Publish pipeline boundaryObjective: Exercise Steps:
Evidence:
Observations:
Summary
Overall ResultIssues found. The PR build installs and basic Blazor gateway service proxying works, but both standalone and hosted telemetry-proxy scenarios failed to emit the expected browser-visible OTLP configuration keys. This appears to prevent WASM client telemetry from being configured through the gateway under the tested CLI/dashboard setup. RecommendationInvestigate why |
|
Re-running the failed jobs in the CI workflow for this pull request because 1 job was identified as retry-safe transient failures in the CI run attempt.
|
|
/backport to release/13.4 |
|
Started backporting to |






Summary
Addresses remaining unresolved review threads from #15691 and adds Docker Compose publish support for the Blazor gateway.
PR Feedback Fixes
[ResourceName]attribute toAddBlazorGateway,AddBlazorWasmProject<T>, andAddBlazorWasmAppname parameters?? throwinEndpointsManifestTransformerStringComparison.OrdinalIgnoreCasefor route comparison"Aspire:Store:Path"magic string to a constDocker Compose Publish Support
The
ClientConfigValueProviderclass (IValueProvider + IManifestExpressionProvider) is replaced with a staticBuildConfigExpression()method that returns aReferenceExpression. This makes the ConfigResponse environment variable natively understood by all publishers.How it works:
__ORIGIN__token in place of the gateway URLUnsafeRelaxedJsonEscaping(we control all values, no braces present){->{{) forstring.Formatsafety__ORIGIN__with{0}to create the format stringReferenceExpressionwithGatewayOriginReferenceas the argumentResult:
https://localhost:PORT— ConfigResponse contains absolute URLs$${GATEWAY_BINDINGS_HTTPS_URL}— deployer fills.envNew file:
GatewayOriginReference.cs— lightweight IValueProvider + IManifestExpressionProvider that wraps an EndpointReference, trims trailing slashes, and emits manifest expressions for publishers.