Skip to content

Passing options to UseStaticFiles breaks Blazor Server's static file service #19578

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

Closed
willdean opened this issue Mar 4, 2020 · 17 comments · Fixed by #45897
Closed

Passing options to UseStaticFiles breaks Blazor Server's static file service #19578

willdean opened this issue Mar 4, 2020 · 17 comments · Fixed by #45897
Assignees
Labels
affected-few This issue impacts only small number of customers area-blazor Includes: Blazor, Razor Components Blazor ♥ MVC Issues related to integration between Blazor and MVC/Razor pages bug This issue describes a behavior which is not expected - a bug. feature-blazor-server Priority:1 Work that is critical for the release, but we could probably ship without severity-minor This label is used by an internal tool
Milestone

Comments

@willdean
Copy link

willdean commented Mar 4, 2020

Describe the bug

If you pass any kind of StaticFileOptions object to app.UseStaticFiles(), then Blazor Server will no longer be able to serve blazor.server.js, breaking Blazor.

To Reproduce

  • Create the template Blazor Server app
  • Run it and observe that it works correctly
  • Change the app.UseStaticFiles() call in Startup.Configure to read app.UseStaticFiles(new StaticFileOptions())
  • Run the app again and observe that blazor.server.js is 404'd, and hence the app doesn't work.

What appears to be happening is that if you don't pass any configuration to UseStaticFiles, then the framework correctly calls ConfigureStaticFilesOptions.PostConfigure after the pipeline is built. This configures the static file middleware to serve the Blazor JS from manifest resources.

As soon as there's any configuration passed to UseStaticFiles, then ConfigureStaticFilesOptions is no longer called. It doesn't matter what specific properties are in the StaticFileOptions object - it's just the presence of the object which causes the problem.

I will debug this further if it's helpful, but I suspect someone more familiar with the IPostConfigureOptions mechanism will know what's going on instantly.

Maybe there's some work-around, but if so then it would be helpful if it could be somehow more obvious, because "I added a static file extension and Blazor stopped working" is somewhat surprising.

I think this may be same issue as #18222, which was perhaps rather confusingly titled and ended up being closed, but I think there is a real issue here.

Further technical details

  • ASP.NET Core version 3.1.2
  • The IDE (VS / VS Code/ VS4Mac) you're running on, and it's version VS 16.4.5 on Win10
@Tratcher Tratcher added the area-blazor Includes: Blazor, Razor Components label Mar 4, 2020
@Tratcher
Copy link
Member

Tratcher commented Mar 4, 2020

Does it work if you add a second instance of UseStaticFiles with options rather than modifying the existing one?

@willdean
Copy link
Author

willdean commented Mar 4, 2020

@Tratcher It does!

I am not sure where I currently am on the amazed <-> appalled spectrum...

@Tratcher
Copy link
Member

Tratcher commented Mar 4, 2020

😁 UseStaticFiles is designed to support multiple instances if you pass in the options directly. UseStaticFiles() with no parameters pulls the options from DI which is likely where Blazor is tweaking the settings.

@willdean
Copy link
Author

willdean commented Mar 4, 2020

@Tratcher Thanks - that does make sense, though I didn't expect it at all, and it feels like a bit of a gotcha.

Would it perhaps be possible for Blazor to detect that it has never been given the chance to run its static file config code and explode somehow early in the run?
That would also catch the case where you didn't have a UseStaticFiles at all - I have seen other people on-line struggling with that.

Or, rather than co-opting (hijacking) the UseStaticFiles to serve-up the manifest resources, could there just be a separate bit of middleware: UseBlazorStaticResources or something, which just served the specific Blazor bits and didn't touch the normal StaticFile middleware?

@Tratcher
Copy link
Member

Tratcher commented Mar 4, 2020

Yeah, blazor should be adding their own static file handler like UseBlazorStaticResources rather than messing with the default.

@mkArtakMSFT mkArtakMSFT added the enhancement This issue represents an ask for new feature or an enhancement to an existing one label Mar 5, 2020
@mkArtakMSFT mkArtakMSFT added this to the Next sprint planning milestone Mar 5, 2020
@mkArtakMSFT
Copy link
Contributor

We've moved this issue to the Backlog milestone. This means that it is not going to happen for the coming release. We will reassess the backlog following the current release and consider this item at that time. However, keep in mind that there are many other high priority features with which it will be competing for resources.

@benm-eras
Copy link

I just tried adding another call to app.UseStaticFiles() and it now works! That is blazor.server.js is served, as is my site.webmanifest file. To be clear this is what I now have in Startup.Configure(...):

app.UseStaticFiles();

FileExtensionContentTypeProvider provider = new FileExtensionContentTypeProvider();
provider.Mappings[".webmanifest"] = "application/manifest+json";

app.UseStaticFiles(new StaticFileOptions()
{
    ContentTypeProvider = provider
});

Not keen on this, but at least it works!

@rudiv
Copy link

rudiv commented Jun 3, 2020

I've just ran in to this which is very confusing behaviour.

I can confirm that @benm-eras workaround is working as expected.

@bdovaz
Copy link

bdovaz commented Jul 1, 2020

I've encountered the same problem.

The solution also comes in this other message which proposes two alternatives:

#9588 (comment)

The first is the ideal solution. The second is a hack that I would not recommend.

Example:

// ConfigureServices method
services.Configure<StaticFileOptions>(options => {
    FileExtensionContentTypeProvider contentTypeProvider = new FileExtensionContentTypeProvider();
    contentTypeProvider.Mappings[".gpx"] = "application/gpx+xml";

    options.ContentTypeProvider = contentTypeProvider;
});

// Configure method
app.UseStaticFiles();

@javiercn javiercn added affected-few This issue impacts only small number of customers severity-minor This label is used by an internal tool labels Oct 9, 2020 — with ASP.NET Core Issue Ranking
@TFTomSun
Copy link

TFTomSun commented Apr 12, 2021

I just wanted to add static asset caching and stumbled upon this problem.

@javiercn javiercn added Blazor ♥ MVC Issues related to integration between Blazor and MVC/Razor pages feature-blazor-server labels Apr 19, 2021
@provencio
Copy link

What a phenomenal time-sink this bug turned out to be for me. Glad there is a suggested workaround, but definitely wish this had been more obvious from the beginning.

@mkArtakMSFT mkArtakMSFT added Priority:1 Work that is critical for the release, but we could probably ship without triaged labels Nov 5, 2021
@mkArtakMSFT mkArtakMSFT modified the milestones: Backlog, .NET 7 Planning Nov 30, 2021
@ghost
Copy link

ghost commented Nov 30, 2021

Thanks for contacting us.

We're moving this issue to the .NET 7 Planning milestone for future evaluation / consideration. We would like to keep this around to collect more feedback, which can help us with prioritizing this work. We will re-evaluate this issue, during our next planning meeting(s).
If we later determine, that the issue has no community involvement, or it's very rare and low-impact issue, we will close it - so that the team can focus on more important and high impact issues.
To learn more about what to expect next and how this issue will be handled you can read more about our triage process here.

@jnsn
Copy link

jnsn commented Aug 1, 2022

I've ran into this issue today when I was trying to set the response HTTP headers for static files (.css, .js) that I'm serving as part of my Blazor website.

I've followed the documentation https://docs.microsoft.com/en-us/aspnet/core/fundamentals/static-files?view=aspnetcore-6.0#set-http-response-headers but it took me a couple of hours before I realized what the issue was and stumbled upon this bug report.

Adding multiple calls to UseStaticFiles() fixed the issue, but interestingly it seems that the order in which they occur matters. I had to place my overrides before the empty call, or the error would still pop up.

app.UseStaticFiles(new StaticFileOptions
{
    OnPrepareResponse = context =>
    {
        // custom response cache logic
    }
});

 app.UseStaticFiles();

@ghost
Copy link

ghost commented Sep 19, 2022

Thanks for contacting us.

We're moving this issue to the .NET 8 Planning milestone for future evaluation / consideration. We would like to keep this around to collect more feedback, which can help us with prioritizing this work. We will re-evaluate this issue, during our next planning meeting(s).
If we later determine, that the issue has no community involvement, or it's very rare and low-impact issue, we will close it - so that the team can focus on more important and high impact issues.
To learn more about what to expect next and how this issue will be handled you can read more about our triage process here.

@willdean
Copy link
Author

You guys should fix this, because it's a ridiculous bug and Blazor should never have broken the defaults like it did. As @Tratcher observed two and a half years ago.

In terms of trying to encourage people to adopt MS tech, I think fixing these sort of festering sores of massive wasted-time for professional developers would give you far more bang-for-buck than all the "write a web app in one line of code" stuff which seems to get so much effort.

@provencio
Copy link

provencio commented Sep 20, 2022 via email

@sbwalker
Copy link

Note that this issue can be resolved by using the options pattern in ConfigureServices:

services.Configure<StaticFileOptions>(options =>
{
    options.OnPrepareResponse = ctx =>
    {
        const int durationInSeconds = 60 * 60 * 24;
        ctx.Context.Response.Headers[HeaderNames.CacheControl] =
            "public, max-age=" + durationInSeconds;
    }  
});

and then call UseStaticFiles() in the standard way (without any parameters) in Configure.

@mkArtakMSFT mkArtakMSFT added Priority:1 Work that is critical for the release, but we could probably ship without and removed Priority:1 Work that is critical for the release, but we could probably ship without labels Nov 10, 2022
@surayya-MS surayya-MS self-assigned this Dec 14, 2022
@mkArtakMSFT mkArtakMSFT added bug This issue describes a behavior which is not expected - a bug. and removed enhancement This issue represents an ask for new feature or an enhancement to an existing one labels Dec 14, 2022
@ghost ghost locked as resolved and limited conversation to collaborators Feb 8, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
affected-few This issue impacts only small number of customers area-blazor Includes: Blazor, Razor Components Blazor ♥ MVC Issues related to integration between Blazor and MVC/Razor pages bug This issue describes a behavior which is not expected - a bug. feature-blazor-server Priority:1 Work that is critical for the release, but we could probably ship without severity-minor This label is used by an internal tool
Projects
None yet
Development

Successfully merging a pull request may close this issue.