C
C#14mo ago
kunio_kun

❔ Serving SPA on ASP.NET Core MVC Web API

Hi, I'm trying to serve SPA in a folder client in BaseDirectory. I want it to be served in "/". Here's what I tried
WebApplication app = builder.Build();
app.UseCors(options => {
options.AllowAnyOrigin();
options.AllowAnyHeader();
options.AllowAnyMethod();
});
app.UseStaticFiles();

app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();

// Configure the HTTP request pipeline.
app.UseSwagger();
app.UseSwaggerUI();

app.MapHub<DevicesHub>("api/hubs/devices");
app.MapControllers();
app.UseSpa(spa => {
spa.Options.SourcePath = Path.Join(app.Environment.ContentRootPath, "client");
});
app.MapFallbackToController("Index", "Fallback");
WebApplication app = builder.Build();
app.UseCors(options => {
options.AllowAnyOrigin();
options.AllowAnyHeader();
options.AllowAnyMethod();
});
app.UseStaticFiles();

app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();

// Configure the HTTP request pipeline.
app.UseSwagger();
app.UseSwaggerUI();

app.MapHub<DevicesHub>("api/hubs/devices");
app.MapControllers();
app.UseSpa(spa => {
spa.Options.SourcePath = Path.Join(app.Environment.ContentRootPath, "client");
});
app.MapFallbackToController("Index", "Fallback");
And the fallback controller implementation is
public class Fallback: ControllerBase
{
public IActionResult Index()
{
return File("~/client/index.html", "text/html");
}
}
public class Fallback: ControllerBase
{
public IActionResult Index()
{
return File("~/client/index.html", "text/html");
}
}
But when i navigate to /, I am getting
FileNotFoundException: Could not find file 'ProjectDirectory\bin\Debug\net7.0\client'.
FileNotFoundException: Could not find file 'ProjectDirectory\bin\Debug\net7.0\client'.
How do I do this correctly? Thanks in advance.
8 Replies
JakenVeina
JakenVeina14mo ago
error is pretty clear there's no such folder or file as ProjectDirectory\bin\Debug\net7.0\client the folder you're telling it to serve your SPA files from
kunio_kun
kunio_kun14mo ago
I can verify the folder exists
JakenVeina
JakenVeina14mo ago
okay well, the program disagrees so I'm gonna have to say, "no, you didn't"
kunio_kun
kunio_kun14mo ago
Do you have any tips to diagnose this situation? By the way, I am trying another approach with the SpaExtensions, now the startup order looks like
// other configurations
WebApplication app = builder.Build();
app.UseCors(options => {
options.AllowAnyOrigin();
options.AllowAnyHeader();
options.AllowAnyMethod();
});
app.UseStaticFiles();
Console.WriteLine(Path.Join(app.Environment.ContentRootPath, "client"));
app.UseSpaStaticFiles(new StaticFileOptions()
{
FileProvider = new PhysicalFileProvider(Path.Join(app.Environment.ContentRootPath, "client")),
RequestPath = ""
});
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();

// Configure the HTTP request pipeline.
app.UseSwagger();
app.UseSwaggerUI();
// more configurations
// other configurations
WebApplication app = builder.Build();
app.UseCors(options => {
options.AllowAnyOrigin();
options.AllowAnyHeader();
options.AllowAnyMethod();
});
app.UseStaticFiles();
Console.WriteLine(Path.Join(app.Environment.ContentRootPath, "client"));
app.UseSpaStaticFiles(new StaticFileOptions()
{
FileProvider = new PhysicalFileProvider(Path.Join(app.Environment.ContentRootPath, "client")),
RequestPath = ""
});
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();

// Configure the HTTP request pipeline.
app.UseSwagger();
app.UseSwaggerUI();
// more configurations
It still complains the same thing, however the client folder exists on the project directory, and in bin\Debug\net7.0 directory, I can explorer the\path\it\complains\not\found and it is there and I could go to localhost:port/index.html and have index.html loaded in the browser I appreciate your response
JakenVeina
JakenVeina14mo ago
if you're going to instruct the app to serve up the SPA files from "ContentRoot/client" you need to put the files there you seem to ve missing .UseDefaultFiles()
kunio_kun
kunio_kun14mo ago
A moment ago i got it working, not its not. It now serves index.html, but when other files are requested, it says file not found while it is there yeah, it's already there okay i fixed it, apparently To sum it up, i need to
builder.Services.AddSpaStaticFiles(config => {
config.RootPath = "client";
});
builder.Services.AddSpaStaticFiles(config => {
config.RootPath = "client";
});
then after the UseStaticFiles
app.UseStaticFiles();
app.MapWhen(context =>
context.Request.Path.Value is not null && !(context.Request.Path.Value.StartsWith("/api") ||
context.Request.Path.Value.StartsWith("/swagger") ||
context.Request.Path.Value.StartsWith("/_client") ||
context.Request.Path.Value.StartsWith("/user")),
appBuilder => {
appBuilder.UseSpaStaticFiles();
appBuilder.UseSpa(_ => {
});
});
app.UseStaticFiles();
app.MapWhen(context =>
context.Request.Path.Value is not null && !(context.Request.Path.Value.StartsWith("/api") ||
context.Request.Path.Value.StartsWith("/swagger") ||
context.Request.Path.Value.StartsWith("/_client") ||
context.Request.Path.Value.StartsWith("/user")),
appBuilder => {
appBuilder.UseSpaStaticFiles();
appBuilder.UseSpa(_ => {
});
});
Thanks you for your responses
JakenVeina
JakenVeina14mo ago
hmmm, okay I don't think I've ever used that extension, just the base StaticFiles middleware can you not just swap that whole if chunk with .StartsWith("/client")?
Accord
Accord14mo ago
Was this issue resolved? If so, run /close - otherwise I will mark this as stale and this post will be archived until there is new activity.