问题
First of, in my project root I have a folder called ClientApp
, which contains a folder build
which is where the output of my frontend build is located.
Then, in Startup.cs
, I have the following in ConfigureServices
:
public void ConfigureServices(IServiceCollection services)
{
...
services.AddSpaStaticFiles(configuration => {
configuration.RootPath = "ClientApp/build";
});
}
Following, my Configure
method looks as follows:
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment()) {
app.UseDeveloperExceptionPage();
} else {
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseSpaStaticFiles();
app.UseAuthentication();
app.UseMvcWithDefaultRoute();
app.Map("/dashboard", dashboard => {
dashboard.Use(async (context, next) => {
if (context.User.Identity.IsAuthenticated) {
await next();
return;
}
context.Response.Redirect("/Account/Login");
});
dashboard.UseSpa(spa => {
spa.Options.SourcePath = "ClientApp";
if (env.IsDevelopment()) {
spa.UseProxyToSpaDevelopmentServer("http://localhost:3000");
}
});
});
}
If I remove the .Map(...)
and just serve the spa in on the app
IApplicationBuilder instance, then it works.
Thank you in advance for any help, this has been bugging me for a few days now.
Edit
The setup I would want in the end is as follows. /dashboard
would serve a SPA application, and anyone accessing that route has to be authenticated. However, routes such as /Account/Login
would not be part of the SPA.
By moving UseSpa
outside of the Map
, any routes that are not handled by the Mvc or a static file in wwwroot
will render the SPA, but when visiting e.g. /about
I want to show a 404, not the SPA which renders the 404.
回答1:
Right, after some clarification and help from Edward, I was able to identify the problem. As Edward pointed out, since the call to UseSpa
was done inside a branch of the request pipeline, the static assets which are served at ClientApp/build
are not used since the request for those assets starts with /static/
and not /dashboard
. This means the request pipeline is unaware of them.
The fix I found is actually more on the client build than the server, since I was unable to correctly let the server know about the static assets. The fix requires to set the homepage
property in package.json
as documented here. The only downside to this is that this does not work whilst running npm start
since the build is not actually output to the filesystem but is instead in memory of the web-server.
On the server, I did have to move app.UseSpaStaticFiles()
inside of the Map
call in order for it to work correctly.
Thanks again to Edward for helping me better understand how Map
works.
回答2:
For app.Map
, it will route the request based on path https://localhost:44378/dashboard/
. Which means only requests with https://localhost:44378/dashboard/
will go into the Spa
middleware.
For dashboard.UseSpa
, it will survery spa static files with https://localhost:44378/styles.bundle.css
which will not match https://localhost:44378/dashboard/
.
If you did not want to change the request base path in SPA to https://localhost:44378/dashboard/
, you may try move UseSpa
outside of app.Map("/dashboard"
.
app.UseSpa(spa =>
{
// To learn more about options for serving an Angular SPA from ASP.NET Core,
// see https://go.microsoft.com/fwlink/?linkid=864501
spa.Options.SourcePath = "ClientApp";
if (env.IsDevelopment())
{
spa.UseAngularCliServer(npmScript: "start");
}
});
app.Map("/dashboard", dashboard =>
{
dashboard.Use(async (context, next) =>
{
if (context.User.Identity.IsAuthenticated)
{
await next();
return;
}
context.Response.Redirect("/Account/Login");
});
});
Update
For changing SPA Static files request URL, you could try to change package.json
like below:
"start": "ng serve --base-href=/dashboard/ --serve-path=/ --live-reload-client=https://localhost:port/frontend/sockjs-node/",
For another option while developing, change code below in Startup
app.Map("/dashboard", frontendApp =>
{
frontendApp.UseSpa(spa =>
{
// To learn more about options for serving an Angular SPA from ASP.NET Core,
// see https://go.microsoft.com/fwlink/?linkid=864501
spa.Options.SourcePath = "ClientApp";
if (env.IsDevelopment())
{
spa.UseAngularCliServer(npmScript: "start -- --base-href=/frontend/ --serve-path=/ --live-reload-client=https://localhost:44302/frontend/sockjs-node/");
}
});
});
来源:https://stackoverflow.com/questions/51730535/my-spa-files-are-giving-404-errors-when-serving-the-spa-in-a-branch-of-the-reque