I want to use Asp.Net Core 2.2 to host my Angular app - as well as serve API requests (on /api).
So in Startup.cs, Configure, I set the following:
app.Map("/home", config =>
{
config.UseSpa(spa =>
{
...
});
});
However, the problem is that runtime.js, polyfills.js etc are all not found because they are being referenced as http://localhost:port/filename.ext
I tried to use
config.UseSpaStaticFiles(new StaticFileOptions { RequestPath = "/runtime.js" });
But to no avail.
What is the secret sauce to serve Angular SPA under a different route in ASP.Net Core?
Edit: Answering @Michael - I was looking into this to ultimately host multiple apps, but I figured it may not be worth the trouble. I want to be able to do 'ng serve' when I am developing the apps and run under Asp.Net Core when I deploy. If one thing works, the other thing is getting broken. So decided to table it for now.
ASP.NET Core application cannot serve static files by default. We must include Microsoft. AspNetCore. StaticFiles middleware in the request pipeline.
Static files, such as HTML, CSS, images, and JavaScript, are assets an ASP.NET Core app serves directly to clients by default.
To serve static files from an ASP.NET Core app, you must configure static files middleware. With static files middleware configured, an ASP.NET Core app will serve all files located in a certain folder (typically /wwwroot).
Static files are stored within the project's web root directory. The default directory is {content root}/wwwroot , but it can be changed with the xref:Microsoft. AspNetCore. Hosting.
I'm going to talk to the csproj configurations, package.json npm configurations, and naturally your Startup.cs code.
at the bottom of your csproj file, you will find a set of npm commands that are run when the application is published.
<!--...-->
<PropertyGroup>
<SpaRoot>ClientApp\</SpaRoot>
</PropertyGroup>
<!--...-->
<Exec WorkingDirectory="$(SpaRoot)" Command="npm install" />
<Exec WorkingDirectory="$(SpaRoot)" Command="npm run build -- --prod" />
<Exec WorkingDirectory="$(SpaRoot)" Command="npm run build:ssr -- --prod" Condition=" '$(BuildServerSideRenderer)' == 'true' " />
<!--...-->
If you wanted to have two applications deployed, you will need to double up on all those deploy instructions.
<!--...-->
<PropertyGroup>
<!--...-->
<SpaRoot>ClientApp\</SpaRoot>
<SpaRoot2>ClientApp2\</SpaRoot2>
<!--...-->
</PropertyGroup>
<!--...-->
<Exec WorkingDirectory="$(SpaRoot)" Command="npm install" />
<!--...-->
<Exec WorkingDirectory="$(SpaRoot2)" Command="npm install" />
<!--...-->
While under development, you will likely want nodejs to host the application. In this scenario, our server isn't hosting our client app.
You going to need to set the servepath to match the subdirectory you want the client application to run out of.
// ...
"start": "ng serve --servePath /app/ --baseHref /app/",
// ...
At this point, don't forget to update the baseHref for the build. otherwise when the scripts in csproj call build, it won't be pointing to the correct basehref.
"build": "ng build --baseHref /app/",
Remember how I said while in development the server don't host the client? I would suggest running one at a time while developing. The important thing is that you update the package.json servePath so that your testing the url pathing and how everything will link together.
if (env.IsDevelopment())
{
app.UseSpaStaticFiles();
app.UseSpa(spa =>
{
spa.Options.SourcePath = "ClientApp";
// this is calling the start found in package.json
spa.UseAngularCliServer(npmScript: "start");
});
}
else // Production -- in the next section,
Finally, we have how we want it to behave in production.
// how you had it, we will create a map
// for each angular client we want to host.
app.Map(new PathString("/app"), client =>
{
// Each map gets its own physical path
// for it to map the static files to.
StaticFileOptions clientAppDist = new StaticFileOptions()
{
FileProvider = new PhysicalFileProvider(
Path.Combine(
Directory.GetCurrentDirectory(),
@"ClientApp\dist"
)
)
};
// Each map its own static files otherwise
// it will only ever serve index.html no matter the filename
client.UseSpaStaticFiles(clientAppDist);
// Each map will call its own UseSpa where
// we give its own sourcepath
client.UseSpa(spa =>
{
spa.Options.SourcePath = "ClientApp";
spa.Options.DefaultPageStaticFileOptions = clientAppDist;
});
});
you can test the production setup by commenting out the development code and running npm run build in your respective clientapp folders before running the C# code. Just ensure the dist folder generated is not checked into your git repo.
Hopefully, you now have a better understand of how it works in a developing environment, creating the build instructions, and how it will run on a production environment.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With