Reputation: 352
I have an ASP.NET Core 2.1 and I need to setup workspace for multiple Angular applications with following routing:
http://someurl.com/main -> first app
http://someurl.com/admin -> second app
I use angular-cli.json
with following settings:
"apps": [
{
"root": "src",
"outDir": "dist",
"assets": [
"assets"
],
"index": "index.html",
"main": "main.ts",
"polyfills": "polyfills.ts",
"test": "test.ts",
"tsconfig": "tsconfig.app.json",
"testTsconfig": "tsconfig.spec.json",
"prefix": "app",
"styles": [
"styles.css",
"../node_modules/bootstrap/dist/css/bootstrap.min.css"
],
"scripts": [],
"environmentSource": "environments/environment.ts",
"environments": {
"dev": "environments/environment.ts",
"prod": "environments/environment.prod.ts"
}
},
{
"root": "src2",
"outDir": "dist2",
"assets": [
"assets"
],
"index": "index.html",
"main": "main.ts",
"polyfills": "polyfills.ts",
"test": "test.ts",
"tsconfig": "tsconfig.app.json",
"testTsconfig": "tsconfig.spec.json",
"prefix": "app",
"styles": [
"styles.css",
"../node_modules/bootstrap/dist/css/bootstrap.min.css"
],
"scripts": [],
"environmentSource": "environments/environment.ts",
"environments": {
"dev": "environments/environment.ts",
"prod": "environments/environment.prod.ts"
}
}
]
I've been trying to setup mapping in Startup.cs
like below:
app.Map("/main", l =>
{
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("/admin", l =>
{
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";
spa.UseSpaPrerendering(options =>
{
options.BootModulePath = $"{spa.Options.SourcePath}/dist2/main.bundle.js";
options.BootModuleBuilder = env.IsDevelopment()
? new AngularCliBuilder(npmScript: "build2")
: null;
});
if (env.IsDevelopment())
{
spa.UseAngularCliServer(npmScript: "start2");
}
});
});
With following scripts in project.json
:
"scripts": {
"ng": "ng",
"start": "ng serve --extract-css --base-href=/main/ --serve-path=/main/",
"start2": "ng serve --app=1 --extract-css --base-href=/admin/ --serve-path=/admin/ ",
"build": "ng build --extract-css",
"build2": "ng build --app=1 --extract-css"
}
When I launch solution main app work's well but when I tried go to admin I have failed with error:
Error: Cannot match any routes. URL Segment: 'admin' Error: Cannot match any routes.
Please tell what I've missed and did wrong to achieve my goal Thanks for any advice !
Upvotes: 10
Views: 5584
Reputation: 79457
@sven.to's answer works, I am just pasting here the full snippet for clarity:
app.Map("/foo", l => l.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");
}
}));
This adds the /foo
prefix and now https://localhost:44383/foo/main.js
will show you main.js while https://localhost:44383/main.js
will give you 404 Not Found
.
Upvotes: 0
Reputation: 11
After dealing with such scenario in real time finally got the working solution.
Source code: https://github.com/alpitg/.NetCoreSpa
Important steps : 1. In Startup.cs file under Configure() use following code,
// for each angular client we want to host use Map function
app.Map(new PathString("/clientapp1"), client =>
{
string clientApp1Path = env.IsDevelopment() ? "ClientApp1" : @"ClientApp1/dist";
// Each map gets its own physical path for it to map the static files to.
StaticFileOptions clientApp1Dist = new StaticFileOptions()
{
FileProvider = new PhysicalFileProvider(
Path.Combine(Directory.GetCurrentDirectory(), clientApp1Path)
)
};
// Each map its own static files otherwise it will only ever serve index.html no matter the filename
client.UseSpaStaticFiles(clientApp1Dist);
client.UseSpa(spa =>
{
spa.Options.StartupTimeout = new TimeSpan(0, 5, 0);
spa.Options.SourcePath = "ClientApp1";
if (env.IsDevelopment())
{
// it will use package.json & will search for start command to run
spa.UseAngularCliServer(npmScript: "start");
}
else
{
spa.Options.DefaultPageStaticFileOptions = clientApp1Dist;
}
});
});
package.json file changes,
"start": "ng serve --servePath / --baseHref /newui/",
"build": "ng build --baseHref /newui/",
"build:ssr": "npm run build --baseHref /newui/ -- --app=ssr --output-hashing=media",
These are the primary changes i have shared here. Fore more detail please use the source code and compare your changes.
NOTE: Tested with .net core 2.2 & angular 7
For more detail please refer my blog: https://wayeasier.home.blog/2019/07/21/hosting-two-angular-app-behind-net-core-web-application/
Upvotes: 1
Reputation: 270
You are registering the Single Page Application (SPA) on the app
not the mapped path:
app.Map("/admin", l =>
{
app.UseSpa(spa =>
Change app
to l
to fix the issue:
app.Map("/admin", l =>
{
l.UseSpa(spa =>
Upvotes: 6