Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Blazor net9 PathBase not working #59521

Closed
1 task done
peterharding93 opened this issue Dec 17, 2024 · 9 comments
Closed
1 task done

Blazor net9 PathBase not working #59521

peterharding93 opened this issue Dec 17, 2024 · 9 comments
Labels
area-blazor Includes: Blazor, Razor Components ✔️ Resolution: Duplicate Resolved as a duplicate of another issue Needs: Repro Indicates that the team needs a repro project to continue the investigation on this issue Status: Resolved

Comments

@peterharding93
Copy link

Is there an existing issue for this?

  • I have searched the existing issues

Describe the bug

There appear to be multiple errors with using net9 Blazor, ServerInteractive rendering and PathBase.

TLDR:

Is there a working example of how I can UsePathBase() in a net 9 blazor application? The documented solutions don't quite work.
My attempts lead me to believe that #48370 is an open issue.

Details:

Using net9, Create a new Blazor WebApp project. Add the line to program.cs:
app.UsePathBase("/app1/");
And in App.razor set the base path:
base href="/app1/"

This fails as described in #57843 - Failed to load resource: the server responded with a status of 405 (Method Not Allowed). That task is marked as closed in RC, but it is still occurring.

I can resolve that by One of two Methods: either explicitly mapping the blazor hub or calling UseRouting. I am not sure which is best:

app.MapBlazorHub("app1/_blazor");
or app.UseRouting();

UseRouting is old know issue from back in net 6 (eg #48370), but I shouldn't have to because that was marked as resolved. This is possibly a regression. The documentation states that I shouldn't need MapBlazorHub either, and this solution doesn't work well if the path base comes from a forwarded header.

These workarounds still leave one open bug - exactly as described in #58046, which is also closed (due to inactivity, not because it was resolved).
BrowerLink is is not retrieved using the path base. I note that blazor.web.js is now using the correct base address (before it was not).

I cannot find a workaround for this, nor find the root cause.

I also note that standalone testing may show this to work - as the BrowserLink file is actually returned correctly without the path base. It is only behind a proxy that requires the path base that the problem appears.

I have a feeling that this is somehow related to the introduction of MapStaticAssets() over UseStaticFiles() - but switching back doesn't seem to resolve the problem.

Expected Behavior

Some documented and robust way to UsePathBase() behind a proxy with Blazor net 9.

Steps To Reproduce

Pretty much as as described in #58046:

  1. Create new Blazor Web App project, globally Server Interactive.
  2. Add app.UsePathBase("/app1/")
  3. Add app.UseRouting();
  4. Set Base path in App.razor
  5. Run the project - it appears to run correctly.
  6. View the page network traffic and notice that something (I think blazor.web.js) is loading to access https://localhost:7116/_vs/browserLink
  7. This Url is incorrect and should be: https://localhost:7116/app1/_vs/browserLink

Exceptions (if any)

No response

.NET Version

9.0.101

Anything else?

VisualStudio.17.Release/17.12.3+35527.113
ASP.NET and Web Tools 17.12.178.10385

In my project file, there are no Nuget packages.
The project has Sdk="Microsoft.NET.Sdk.Web" and TargetFramework of net9.0.

@dotnet-issue-labeler dotnet-issue-labeler bot added the area-blazor Includes: Blazor, Razor Components label Dec 17, 2024
@javiercn
Copy link
Member

@peterharding93 thanks for contacting us.

Can you provide a repro project as a public github repository so that we can check exactly what you are doing?

@javiercn javiercn added Needs: Author Feedback The author of this issue needs to respond in order for us to continue investigating this issue. Needs: Repro Indicates that the team needs a repro project to continue the investigation on this issue labels Dec 17, 2024
@peterharding93
Copy link
Author

peterharding93 commented Dec 17, 2024

I just created this project.
https://github.com/peterharding93/testing-aspnet-blazor-net9
It reproduces exactly as I described above.

How to investigate:

  1. Run the project
  2. Check the URL from which aspnetcore-browser-refresh.js is being called.

Here are the steps I used to create this:

  1. Created new project.
  2. Add single line to map path base in Project.s
  3. Fix up the base tag in App.razor. I pulled this from httpContext instead of hard coding. This works correctly.
  4. Run project and it (pre) renders correctly in static mode.
  5. No interactive functionality. Can't increment counter page.
  6. Interaction shows Blazor 405 (Screenshot attached)
  7. Fix that by adding UseRouting()
  8. Program appears to work, but will fail behind proxy
  9. The Browserlink is retrieved without correctly using pathbase (screenshot attached)\

I also added in some custom middleware to help demonstrate and catch the bug.
It doesn't actually intercept the incorrect GET - I'm guessing the blazor files are earlier in the middleware pipeline than I can intercept.

Image
Image

@dotnet-policy-service dotnet-policy-service bot added Needs: Attention 👋 This issue needs the attention of a contributor, typically because the OP has provided an update. and removed Needs: Author Feedback The author of this issue needs to respond in order for us to continue investigating this issue. labels Dec 17, 2024
@peterharding93
Copy link
Author

I think I have found the root cause. These script URLs that are automatically injected into the page source start with a leading slash. I can see that doesn't work for both browserLink and browser refresh.
Now to find out where that is written, and whether it should (a) be pathbase relative without the slash, or (b) include the full path base.
Image

@peterharding93
Copy link
Author

peterharding93 commented Dec 20, 2024

I think I have found the bug. It's not ASP.NET Core - it is the SDK.

The paths of concern hard-coded in this file:
https://github.com/dotnet/sdk/blob/main/src/BuiltInTools/BrowserRefresh/ApplicationPaths.cs

The leading slash seems fundamentally flawed. Either drop the leading slash or use the httpContext pathBase.
The comment say the listenting URI's must be at this PathString, but that is not possible behind a proxy.

Maybe this only comes up now after the introduction of .NET Aspire where developers can easily test and develop behind a proxy?

I am about to try putting code at the start of my program.cs (actually, I have to hack it using reflection, which I don't know how to do given there is not even a private setter):
Microsoft.AspNetCore.Watch.BrowserRefresh.ApplicatinPaths.FrameworkRoot = "_framework";

Additional Note about when the break occurred:
This behavior seemed to be fine before updating to the net8 style projects. My projects using the old _hosts.cshtml and a slightly older but still net9 SDK worked fine. I just spun up a container about 2 weeks ago, and confirmed that it works - it looks like this BrowserRefresh script injection wasn't being run.

@peterharding93
Copy link
Author

Okay. I give up. I can't see any assemblies in the namespace Microsoft.AspNetCore.Watch.BrowserRefresh. I think it is in the request pipeline but there are quite a few things I don't understand going on. I'm wasting my time trying to reverse engineer the ASP.NET stack. I think I need to wait for help.

@javiercn
Copy link
Member

@peterharding93 thanks for the additional details.

This seems to be indeed a bug. The issue seems to be here https://github.com/dotnet/aspnetcore/blob/main/src/Components/WebAssembly/WebAssembly/src/HotReload/WebAssemblyHotReload.cs#L37. The intended behavior was by design I believe, since we wire this up with a middleware that gets injected and that can't account for the base path (I believe it's too early in the pipeline).

So, either we change the middleware to look at the forwarded headers (I believe there's one that sends that path base from the proxy) or we change the approach of how this file is handled (which we kind-of want to do in any case).

As for how to workaround the issue, you can try setting up an IStartupFilter like we do to try and set the path base ahead of time.

@javiercn
Copy link
Member

We are going to track further work at Revisit hot reload browser refresh script injection. For all our intents and purposes, we should use a build-only JS initializer to setup this for Blazor applications.

@javiercn javiercn added ✔️ Resolution: Duplicate Resolved as a duplicate of another issue and removed Needs: Attention 👋 This issue needs the attention of a contributor, typically because the OP has provided an update. labels Dec 21, 2024
@javiercn
Copy link
Member

javiercn commented Dec 21, 2024

@peterharding93 note also that this issue is only relevant during development with hot reload enabled. If you CTRL+F5 the app without hot reload enabled everything should work. If that's not the case, let us know.

@peterharding93
Copy link
Author

Thanks for looking into it.
It looks to me like the bug you found is a third incorrect path. That doesn't look like the calls I am seeing in the sample app.

The first two calls are what I am experiencing from the SDK / BuiltInTools / SDK which is probably only for Blazor Server side. The third one you found is probably part of Web Assembly.

I can work around this - although it really compromises how .NET Aspire can be used to debug applications emulating the 'real' setup.

PS. A quick search of the source coded for hard-coded "/_framework/" makes me think think this problem isn't going away quickly. It probably needs a coherent design solution for Server and one for WebAssembly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-blazor Includes: Blazor, Razor Components ✔️ Resolution: Duplicate Resolved as a duplicate of another issue Needs: Repro Indicates that the team needs a repro project to continue the investigation on this issue Status: Resolved
Projects
None yet
Development

No branches or pull requests

2 participants