admin管理员组

文章数量:1289828

We are working on migrating our application to a new Angular version. The old one (Angular.JS) was it's own application/repo being served by an .NET Framework 4.5.2 ASP.NET MVC application that would route every call to Home which would return a Razor View that contained the angular application and then start it up, possibly routing the suffix of the URL to the actual Angular page. For example, it would route www.website/profile to the profile route in Angular, NOT trying to access a folder called profile on the server. Integrating our API and Angular.JS application is not too too pretty but it worked. The server also has virtual folders in IIS for other subfolders that should be accessed like fonts, images, configs, etc.

Currently I am working on getting the Angular 7 application to run alongside the Angular.JS application. We want to run the Angular 7 application to run inside of a directory of the current application and later on move it to it's own web app because our new Angular application is just a bunch of static files and does not need to be bundled with the server anymore. Basically, there is no need for any ASP.NET MVC configuration.

The current url would be www.website and return the Angular.JS application. The new one would be www.website/v2/ and would return the Angular 7 application. If we had finished a v2 version of the profile page, navigating to wwww.website/v2/profile should now navigate to the profile page of the Angular 7 application.

In IIS, one of the virtual folders is a folder called dist which leads to the location of the Angular.JS app files. A new one called v2 is now configured, which leads to the location of the Angular 7 app files. Another one called assets leads to the assets folder of the Angular 7 application.

Now, when I navigate to www.website/v2/, Angular starts and routes me to www.website/v2/home, which is the home route.

The issue is that when I type in www.website/v2/home myself, it results in the application routing back to www.website. and thus it boots up the Angular.JS application again. There are no errors or redirects taking place. It seems like it just ignores the part that es after the v2/ part even though Angular.JS does this just fine.

TL;DR Navigating to www.website/v2 loads up Angular 7, but navigating to v2/{{Anything}} results in the application falling back to the Angular.JS application running on www.website, even though if {{anything}} was an internal link in Angular 7, it would navigate to the {{anything}} route.

I build the Angular project with the following mand:

ng build --configuration=dev --deploy-url=/v2/ --base-href=/v2/

The routes in the angular 7 application look like this:

const routes: Routes = [
  {
    path: '',
    redirectTo: 'home',
    pathMatch: 'full',
  },
  {
    path: '',
    canActivate: [AuthGuard],
    ponent: DefaultLayoutComponent,
    children: [
      {
        path: 'home',
        ponent: DashboardComponent,
        canLoad: [NoAuthGuard],
      },
      {
        path: 'contact',
        loadChildren: './modules/contact/contact.module#ContactModule',
        canLoad: [NoAuthGuard],
      },
      {
        path: 'timesheets',
        loadChildren: './modules/timesheet/timesheet.module#TimesheetModule',
        canLoad: [NoAuthGuard],
      },
      {
        path: 'users',
        loadChildren: './modules/users/users.module#UsersModule',
        canLoad: [NoAuthGuard, NgxPermissionsGuard],
        data: {
          permissions: {
            only: 'seeUsersPage',
            redirectTo: '/403',
          },
        },
      },
      {
        path: 'profile',
        loadChildren: './modules/profile/profile.module#ProfileModule',
        canLoad: [NoAuthGuard],
      },
    ],
  },
  {
    path: 'login',
    ponent: LoginComponent,
  },
  {
    path: '403',
    ponent: Page403Component,
  },
  {
    path: '**',
    redirectTo: '/home',
    pathMatch: 'full',
  },
];

Can anyone tell me how I can make, for example, typing www.website/v2/contact in the browser lead to the v2 contact page, while also making the internal navigation possible (so if the user clicks on a "navigate to v2 contact page" inside of the Angular 7 application, it also navigates to the v2 contact page)

Edit: Information about the Angular.JS Routerconfig and the back-end web.config were requested; I have provided them below.

RouterConfig:

$routeProvider
    .when('/', {
      templateUrl: 'scripts/home/home.html',
      controller: 'HomeController',
      controllerAs: 'homeCtrl'
    })
    .when('/gebruikers', {
      templateUrl: 'scripts/users/users.html',
      controller: 'UsersController',
      controllerAs: 'usersCtrl'
    })
    .when('/profiel', {
      templateUrl: 'scripts/profile/profile.html',
      controller: 'ProfileController',
      controllerAs: 'profileCtrl'
    })
    .when('/timesheets', {
      templateUrl: 'scripts/timesheets/timesheets.html',
      controller: 'TimesheetsController',
      controllerAs: 'timesheetsCtrl',
      reloadOnSearch: false
    })
    .when('/facturen', {
      templateUrl: 'scripts/invoices/invoices.html',
      controller: 'InvoicesController',
      controllerAs: 'invoicesCtrl',
      reloadOnSearch: false
    })
    .when('/opdrachten', {
      templateUrl: 'scripts/vacancies/vacancies.html',
      controller: 'VacanciesController',
      controllerAs: 'vacanciesCtrl'
    })
    .when('/contact', {
      templateUrl: 'scripts/contact/contact.html',
      controller: 'ContactController',
      controllerAs: 'contactCtrl'
    })
    .when('/help', {
      templateUrl: 'scripts/help/help.html',
      controller: 'HelpController',
      controllerAs: 'helpCtrl'
    })
    .otherwise({
      redirectTo: '/'
    });

Web.Config IIS rewrite rules:

 <rewrite>
      <rules>
        <clear />
        <rule name="Redirect Angular endpoints to MVC Home" enabled="true">
          <match url="^(profiel|timesheets|facturen|opdrachten|contact|help|gebruikers)" negate="false" />
          <conditions logicalGrouping="MatchAll" trackAllCaptures="false" />
          <action type="Rewrite" url="Home" logRewrittenUrl="false" />
        </rule>
     <!-- Some other rules that are not important are here, they redirect HTTP to HTTPS -->
     </rules>
  </rewrite>

We are working on migrating our application to a new Angular version. The old one (Angular.JS) was it's own application/repo being served by an .NET Framework 4.5.2 ASP.NET MVC application that would route every call to Home which would return a Razor View that contained the angular application and then start it up, possibly routing the suffix of the URL to the actual Angular page. For example, it would route www.website./profile to the profile route in Angular, NOT trying to access a folder called profile on the server. Integrating our API and Angular.JS application is not too too pretty but it worked. The server also has virtual folders in IIS for other subfolders that should be accessed like fonts, images, configs, etc.

Currently I am working on getting the Angular 7 application to run alongside the Angular.JS application. We want to run the Angular 7 application to run inside of a directory of the current application and later on move it to it's own web app because our new Angular application is just a bunch of static files and does not need to be bundled with the server anymore. Basically, there is no need for any ASP.NET MVC configuration.

The current url would be www.website. and return the Angular.JS application. The new one would be www.website./v2/ and would return the Angular 7 application. If we had finished a v2 version of the profile page, navigating to wwww.website./v2/profile should now navigate to the profile page of the Angular 7 application.

In IIS, one of the virtual folders is a folder called dist which leads to the location of the Angular.JS app files. A new one called v2 is now configured, which leads to the location of the Angular 7 app files. Another one called assets leads to the assets folder of the Angular 7 application.

Now, when I navigate to www.website./v2/, Angular starts and routes me to www.website./v2/home, which is the home route.

The issue is that when I type in www.website./v2/home myself, it results in the application routing back to www.website.. and thus it boots up the Angular.JS application again. There are no errors or redirects taking place. It seems like it just ignores the part that es after the v2/ part even though Angular.JS does this just fine.

TL;DR Navigating to www.website./v2 loads up Angular 7, but navigating to v2/{{Anything}} results in the application falling back to the Angular.JS application running on www.website., even though if {{anything}} was an internal link in Angular 7, it would navigate to the {{anything}} route.

I build the Angular project with the following mand:

ng build --configuration=dev --deploy-url=/v2/ --base-href=/v2/

The routes in the angular 7 application look like this:

const routes: Routes = [
  {
    path: '',
    redirectTo: 'home',
    pathMatch: 'full',
  },
  {
    path: '',
    canActivate: [AuthGuard],
    ponent: DefaultLayoutComponent,
    children: [
      {
        path: 'home',
        ponent: DashboardComponent,
        canLoad: [NoAuthGuard],
      },
      {
        path: 'contact',
        loadChildren: './modules/contact/contact.module#ContactModule',
        canLoad: [NoAuthGuard],
      },
      {
        path: 'timesheets',
        loadChildren: './modules/timesheet/timesheet.module#TimesheetModule',
        canLoad: [NoAuthGuard],
      },
      {
        path: 'users',
        loadChildren: './modules/users/users.module#UsersModule',
        canLoad: [NoAuthGuard, NgxPermissionsGuard],
        data: {
          permissions: {
            only: 'seeUsersPage',
            redirectTo: '/403',
          },
        },
      },
      {
        path: 'profile',
        loadChildren: './modules/profile/profile.module#ProfileModule',
        canLoad: [NoAuthGuard],
      },
    ],
  },
  {
    path: 'login',
    ponent: LoginComponent,
  },
  {
    path: '403',
    ponent: Page403Component,
  },
  {
    path: '**',
    redirectTo: '/home',
    pathMatch: 'full',
  },
];

Can anyone tell me how I can make, for example, typing www.website./v2/contact in the browser lead to the v2 contact page, while also making the internal navigation possible (so if the user clicks on a "navigate to v2 contact page" inside of the Angular 7 application, it also navigates to the v2 contact page)

Edit: Information about the Angular.JS Routerconfig and the back-end web.config were requested; I have provided them below.

RouterConfig:

$routeProvider
    .when('/', {
      templateUrl: 'scripts/home/home.html',
      controller: 'HomeController',
      controllerAs: 'homeCtrl'
    })
    .when('/gebruikers', {
      templateUrl: 'scripts/users/users.html',
      controller: 'UsersController',
      controllerAs: 'usersCtrl'
    })
    .when('/profiel', {
      templateUrl: 'scripts/profile/profile.html',
      controller: 'ProfileController',
      controllerAs: 'profileCtrl'
    })
    .when('/timesheets', {
      templateUrl: 'scripts/timesheets/timesheets.html',
      controller: 'TimesheetsController',
      controllerAs: 'timesheetsCtrl',
      reloadOnSearch: false
    })
    .when('/facturen', {
      templateUrl: 'scripts/invoices/invoices.html',
      controller: 'InvoicesController',
      controllerAs: 'invoicesCtrl',
      reloadOnSearch: false
    })
    .when('/opdrachten', {
      templateUrl: 'scripts/vacancies/vacancies.html',
      controller: 'VacanciesController',
      controllerAs: 'vacanciesCtrl'
    })
    .when('/contact', {
      templateUrl: 'scripts/contact/contact.html',
      controller: 'ContactController',
      controllerAs: 'contactCtrl'
    })
    .when('/help', {
      templateUrl: 'scripts/help/help.html',
      controller: 'HelpController',
      controllerAs: 'helpCtrl'
    })
    .otherwise({
      redirectTo: '/'
    });

Web.Config IIS rewrite rules:

 <rewrite>
      <rules>
        <clear />
        <rule name="Redirect Angular endpoints to MVC Home" enabled="true">
          <match url="^(profiel|timesheets|facturen|opdrachten|contact|help|gebruikers)" negate="false" />
          <conditions logicalGrouping="MatchAll" trackAllCaptures="false" />
          <action type="Rewrite" url="Home" logRewrittenUrl="false" />
        </rule>
     <!-- Some other rules that are not important are here, they redirect HTTP to HTTPS -->
     </rules>
  </rewrite>
Share Improve this question edited Jan 12, 2019 at 15:14 S. ten Brinke asked Jan 11, 2019 at 15:57 S. ten BrinkeS. ten Brinke 3,0015 gold badges35 silver badges61 bronze badges 5
  • include your RouterConfig here – John Velasquez Commented Jan 11, 2019 at 16:28
  • @JohnVelasquez Thank you for your ment. I am a back-ender myself, do you mean the Angular.JS RouterConfig? If not, what other Routing information about the Angular 7 App do you require? For now I have edited the main post to include the RouterConfig of the Angular JS Application; please take another look if you have time. – S. ten Brinke Commented Jan 12, 2019 at 15:11
  • Are you using ASP.NET MVC?, if yes include the RouteConfig – John Velasquez Commented Jan 12, 2019 at 16:33
  • Sorry forgot to tell you that I was talking about ASP.NET – John Velasquez Commented Jan 12, 2019 at 16:34
  • Well, it has a default route that you always get, and the default for that route is to go to Homecontroller, which returns a View that in bination with the base layout in razor, starts up the Angular JS app. – S. ten Brinke Commented Jan 12, 2019 at 18:31
Add a ment  | 

4 Answers 4

Reset to default 6

The reason why it would always route back to the v1 url is because the angular 7 app contained a web.config file that looked like this:

<configuration>
    <system.webServer>
      <rewrite>
        <rules>
          <rule name="Angular" stopProcessing="true">
            <match url=".*" />
            <conditions logicalGrouping="MatchAll">
              <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
              <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
            </conditions>
            <action type="Rewrite" url="/" />
          </rule>
        </rules>
      </rewrite>
    </system.webServer>
</configuration>

I believe this is default for an IIS deployment and a team member might have added this. I never thought about having a web.config in a front-end project.

Basically, this rule takes care of rerouting the user to the index.html. For example www.website./folder would normally bring the user to a folder called folder on the webserver, but this is not where Angular runs and could cause a 404. This rule brings the user back to www.website. and then lets angular route the folder part.

Because I am running my application in a subfolder, I changed the url="/" to url="/v2/" and it worked immediatly!

Remember to build the project with ng build --configuration=dev --deploy-url=/v2/ --base-href=/v2/! The deploy-url is needed because the scripts/css/other files are not found in the root folder of the server; it is found in /v2/. The base-href is necessary for the router; it should start routing the application at www.website./v2/ and not at www.website./!

No other iis rewrite rules are necessary, no asp config, no special angular routing. Just these simple steps!

Have you made any modification to your Web.config file? You need to set it up for the base angular app (using the UrlRewrite module) I'd assume it might need a modification for your use case...

<rewrite>
    <rules>
      <rule name="Angular RoutesV1" stopProcessing="true">
        <match url=".*" />
        <conditions logicalGrouping="MatchAll">
          <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
          <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
        </conditions>
        <action type="Rewrite" url="/my/app/" />
      </rule>
    </rules>
  </rewrite>

My assumption is you will need to add another 'rule' here. Hope this helps!!! (note: the rewrite is supposed to match your ng build base href value)

  1. Remove your Web.Config IIS rewrite rules
  2. In your RouteConfig change it this way

RouteConfig

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

        // don't change the arrangement, this must be executed first
        routes.MapRoute(
                name: "V2",
                url: "v2/{*url}",
                defaults: new { controller = "Home", action = "IndexV2", id = UrlParameter.Optional }
            );

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

Basically what this does is it will catch all your route paths given with the specific route name, the {*url} catches all the route segment regardless of the value.

So when we say the url is;

  • localhost:4200/test <- this points to Default
  • localhost:4200/v2/test <- this points to V2
  • localhost:4200/test/something/2323 <- this points to Default
  • localhost:4200/v2/test2/test_again/2323 <- this points to V2

and in your HomeController make sure to add the IndexV2

HomeController

public ActionResult IndexV2()
{
    return View();
} 

For .Net Core 3 or higher


if 404 happened in the angular subdirectory, it's because of the default route config. so it will be fixed by writing this code on startup.

 app.Use(async (context, next) => {
   await next();
    if (context.Response.StatusCode == 404 &&
      !System.IO.Path.HasExtension(context.Request.Path.Value) &&
      !context.Request.Path.Value.ToLower().StartsWith("/api/")&&
      !context.Request.Path.Value.ToLower().StartsWith("/swagger"))
        {
          context.Request.Path = "yousubdirectory/index.html";
          await next();
        }
    });
 
  app.UseMvcWithDefaultRoute();

本文标签: javascriptRouting in Angular 7 running in subfolder not working correctlyStack Overflow