10

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 !

1
  • 1
    Hi Ami - I have a very similar requirement. Did you ever get this working? Commented Jun 26, 2018 at 23:31

3 Answers 3

6

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 =>
Sign up to request clarification or add additional context in comments.

Comments

1

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;
                    }
                });
            });
  1. 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/

1 Comment

the first app handle all routing such that navigating to the other path falls back to the previous. Can't seem to get this right.
0

@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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.