0
votes

I'm trying to use Angular 6, angular CLI and MV Areas.For POC reasons I've named it Angular The idea was to have an angular app per Area. If this is a bad idea please let me know because maybe the whole concept is And for me it's a pain. This is the first time that I'm configuring it. Below is my example Area has a main controller which looks like this:

public class MainController : BaseController
{
    [HttpGet]
    public ActionResult Index()
    {
        return View();
    }
}

And my Route config looks like this:

    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

        routes.MapRoute(
            name: "mvc",
            url: "{controller}/{action}/",
            defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
        );

        // This is a catch-all for when no other routes match the request; let the Angular 2 router take care of it...
        routes.MapRoute(
            name: "default",
            url: "{*url}",
            defaults: new { controller = "Home", action = "Index" } // The view that bootstraps Angular 2 app
        );

        //routes.MapRoute(
        //    name: "Default",
        //    url: "{controller}/{action}/",
        //    defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional });
    }

I have my app folder in the main project directory, aslo files like angular.json and packages.json. I've created this using angular CLI

Below is an angular.josn file:

   {
      "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
      "version": 1,
      "newProjectRoot": "eagle-app",
      "projects": {
          "test-app": {
          "root": "test-app/",
          "sourceRoot": "test-app",
          "projectType": "application",
          "prefix": "app",
          "schematics": {},
          "architect": {
           "build": {
              "builder": "@angular-devkit/build-angular:browser",
              "options": {
              "outputPath": "eagle-app/dist/test-app",
               "index": "Areas/ANGULAR/Views/Main/Index.cshtml",
                "main": "eagle-app/test-app/main.ts",
                "polyfills": "eagle-app/test-app/polyfills.ts",
                "tsConfig": "eagle-app/test-app/tsconfig.app.json",
                "assets": [
              "test-app/favicon.ico",
              "test-app/assets"
            ],
        "styles": [
          "eagle-app/test-app/styles.css",
          "node_modules/primeicons/primeicons.css",
          "node_modules/primeng/resources/themes/nova-light/theme.css",
          "node_modules/primeng/resources/primeng.min.css"
        ],
        "scripts": []
      },
      "configurations": {
        "production": {
          "fileReplacements": [
            {
              "replace": "eagle-app/test-app/environments/environment.ts",
              "with": "eagle-app/test-app/environments/environment.prod.ts"
            }
          ],
          "optimization": true,
          "outputHashing": "all",
          "sourceMap": false,
          "extractCss": true,
          "namedChunks": false,
          "aot": true,
          "extractLicenses": true,
          "vendorChunk": false,
          "buildOptimizer": true
        }
      }
    },
    "serve": {
      "builder": "@angular-devkit/build-angular:dev-server",
      "options": {
        "browserTarget": "test-app:build"
      },
      "configurations": {
        "production": {
          "browserTarget": "test-app:build:production"
        }
      }
    },
    "extract-i18n": {
      "builder": "@angular-devkit/build-angular:extract-i18n",
      "options": {
        "browserTarget": "test-app:build"
      }
    },
    "test": {
      "builder": "@angular-devkit/build-angular:karma",
      "options": {
        "main": "eagle-app/test-app/test.ts",
        "polyfills": "eagle-app/test-app/polyfills.ts",
        "tsConfig": "eagle-app/test-app/tsconfig.spec.json",
        "karmaConfig": "eagle-app/test-app/karma.conf.js",
        "styles": [
          "eagle-app/test-app/styles.css",
          "node_modules/primeicons/primeicons.css",
          "node_modules/primeng/resources/themes/nova-light/theme.css",
          "node_modules/primeng/resources/primeng.min.css"
        ],
        "scripts": [],
        "assets": [
          "test-app/favicon.ico",
          "test-app/assets"
        ]
      }
    },
    "lint": {
      "builder": "@angular-devkit/build-angular:tslint",
      "options": {
        "tsConfig": [
          "eagle-app/test-app/tsconfig.app.json",
          "eagle-app/test-app/tsconfig.spec.json"
        ],
        "exclude": [
          "**/node_modules/**"
        ]
      }
    }
  }
},
"test-app-e2e": {
  "root": "test-app-e2e/",
  "projectType": "application",
  "architect": {
    "e2e": {
      "builder": "@angular-devkit/build-angular:protractor",
      "options": {
        "protractorConfig": "test-app-e2e/protractor.conf.js",
        "devServerTarget": "test-app:serve"
      },
      "configurations": {
        "production": {
          "devServerTarget": "test-app:serve:production"
        }
      }
    },
    "lint": {
      "builder": "@angular-devkit/build-angular:tslint",
      "options": {
        "tsConfig": "test-app-e2e/tsconfig.e2e.json",
        "exclude": [
          "**/node_modules/**"
        ]
      }
    }
  }
}
}
}

My Index.cshtml from the Area looks like this:

@{ 
    Layout = "~/Views/Shared/_Layout.cshtml";
 }

    <!doctype html>
    <html lang="en">
    <head>
        <meta charset="utf-8">
        <title>TestApp</title>
        <base href="/Areas/ANGULAR/Main/">

        <meta name="viewport" content="width=device-width, initial-scale=1">
            <link rel="icon" type="image/x-icon" href="favicon.ico">
    </head>
    <body>
        <test-app>
        </test-app>
    @section scripts {
    @Scripts.Render("~/Content/angular-ui")
    }
    </body>
</html>

As you can see I have an routingcomponent which looks like this:

import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { Sub1Component } from "./submodule1/sub1.component"
import { Sub2Component } from "./submodule2/sub2.component"
import { AppComponent } from "./app.component";


const routes: Routes = [
    { path: 'Sub1', component: Sub1Component },
    { path: 'Sub2', component: Sub2Component },
    {
      path: '',
      redirectTo: '/Sub1',
      pathMatch: 'full'
    }
 ];

@NgModule({
    imports: [RouterModule.forRoot(routes)],
   exports: [RouterModule]
})
export class AppRoutingModule { }

I'm injecting this to my app.component which a loop that creates buttons for submodules like defined above and the view for it is in shared foler. The problem is I'm getting error like below. And I can't get seem to have the default route for sub1 to be loaded.

ERROR Error: Uncaught (in promise): Error: Cannot match any routes. URL Segment: 'ANGULAR/Main' Error: Cannot match any routes. URL Segment: 'ANGULAR/Main' at ApplyRedirects.push.../node_modules/@angular/router/fesm5/router.js.ApplyRedirects.noMatchError (router.js:1382) at CatchSubscriber.selector (router.js:1363) at CatchSubscriber.push.../node_modules/rxjs/_esm5/internal/operators/catchError.js.CatchSubscriber.error (catchError.js:34) at MapSubscriber.push.../node_modules/rxjs/_esm5/internal/Subscriber.js.Subscriber._error (Subscriber.js:83) at MapSubscriber.push.../node_modules/rxjs/_esm5/internal/Subscriber.js.Subscriber.error (Subscriber.js:61) at MapSubscriber.push.../node_modules/rxjs/_esm5/internal/Subscriber.js.Subscriber._error (Subscriber.js:83) at MapSubscriber.push.../node_modules/rxjs/_esm5/internal/Subscriber.js.Subscriber.error (Subscriber.js:61) at MapSubscriber.push.../node_modules/rxjs/_esm5/internal/Subscriber.js.Subscriber._error (Subscriber.js:83) at MapSubscriber.push.../node_modules/rxjs/_esm5/internal/Subscriber.js.Subscriber.error (Subscriber.js:61) at TapSubscriber.push.../node_modules/rxjs/_esm5/internal/operators/tap.js.TapSubscriber._error (tap.js:61) at ApplyRedirects.push.../node_modules/@angular/router/fesm5/router.js.ApplyRedirects.noMatchError (router.js:1382) at CatchSubscriber.selector (router.js:1363) at CatchSubscriber.push.../node_modules/rxjs/_esm5/internal/operators/catchError.js.CatchSubscriber.error (catchError.js:34) at MapSubscriber.push.../node_modules/rxjs/_esm5/internal/Subscriber.js.Subscriber._error (Subscriber.js:83) at MapSubscriber.push.../node_modules/rxjs/_esm5/internal/Subscriber.js.Subscriber.error (Subscriber.js:61) at MapSubscriber.push.../node_modules/rxjs/_esm5/internal/Subscriber.js.Subscriber._error (Subscriber.js:83) at MapSubscriber.push.../node_modules/rxjs/_esm5/internal/Subscriber.js.Subscriber.error (Subscriber.js:61) at MapSubscriber.push.../node_modules/rxjs/_esm5/internal/Subscriber.js.Subscriber._error (Subscriber.js:83) at MapSubscriber.push.../node_modules/rxjs/_esm5/internal/Subscriber.js.Subscriber.error (Subscriber.js:61) at TapSubscriber.push.../node_modules/rxjs/_esm5/internal/operators/tap.js.TapSubscriber._error (tap.js:61) at resolvePromise (zone.js:814) at resolvePromise (zone.js:771) at zone.js:873 at ZoneDelegate.push.../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:421) at Object.onInvokeTask (core.js:3815) at ZoneDelegate.push.../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:420) at Zone.push.../node_modules/zone.js/dist/zone.js.Zone.runTask (zone.js:188) at drainMicroTaskQueue (zone.js:595)

Anyway I have also a general question is the concept of having seperate apps for an Area is ok? Or maybe some of you have any experience with angular CLI, MVC5 Areas and Angular6? How it should be done. Thanks for you patience and help in advance. Below also are print screens how I have my project structured

My project structure

1

1 Answers

0
votes

Ok with a help of a friend in my team we've managed to solve the issue! The thing is in our MVC app we have also a angularjs (1.x) app and we've noticed that we have hash based urls. That lead us to finding the answer, that in our app module we should import this:

{ provide: LocationStrategy, useClass: HashLocationStrategy }

which get's imported from:

import { LocationStrategy, HashLocationStrategy } from '@angular/common';

in the this looks like this:

@NgModule({
declarations: [
    AppComponent

],
imports: [
    BrowserModule
    , BrowserAnimationsModule
    , HttpClientModule
    , FormsModule
    , SharedModule
    , AppRoutingModule
],

providers: { provide: LocationStrategy, useClass: HashLocationStrategy }],
bootstrap: [AppComponent]
})

Also we had to delele the html part because we had sort of html in html. That his instead of having this:

@{ 
Layout = "~/Views/Shared/_Layout.cshtml";
 }

<!doctype html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title>TestApp</title>
    <base href="/Areas/ANGULAR/Main/">

    <meta name="viewport" content="width=device-width, initial-scale=1">
        <link rel="icon" type="image/x-icon" href="favicon.ico">
</head>
<body>
    <test-app>
    </test-app>
@section scripts {
@Scripts.Render("~/Content/angular-ui")
}
</body>

We should have only this:

@{
Layout = "~/Views/Shared/_Layout.cshtml";
}
  @Styles.Render("~/Content/prime-ng-css")
  <div id="test-app">
     <test-app>
    </test-app>
  </div>

 @section scripts {
   @Scripts.Render("~/Content/mMonitor-ui")
}

This was the solustion for the problem i this specific case and config that we have