简体   繁体   English

在子文件夹中运行的 Angular 7 中的路由无法正常工作

[英]Routing in Angular 7 running in subfolder not working correctly

We are working on migrating our application to a new Angular version.我们正在努力将我们的应用程序迁移到新的 Angular 版本。 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.旧的 (Angular.JS) 是它自己的应用程序/存储库,由 .NET Framework 4.5.2 ASP.NET MVC 应用程序提供服务,该应用程序会将每次调用路由到Home ,后者将返回一个包含角度应用程序的 Razor 视图,然后启动它,可能将 URL 的后缀路由到实际的 Angular 页面。 For example, it would route www.website.com/profile to the profile route in Angular, NOT trying to access a folder called profile on the server.例如,它会将www.website.com/profile路由到 Angular 中的profile路由,而不是尝试访问服务器上名为profile的文件夹。 Integrating our API and Angular.JS application is not too too pretty but it worked.集成我们的 API 和 Angular.JS 应用程序并不太漂亮,但它奏效了。 The server also has virtual folders in IIS for other subfolders that should be accessed like fonts, images, configs, etc.服务器在 IIS 中还有虚拟文件夹,用于其他应该访问的子文件夹,如字体、图像、配置等。

Currently I am working on getting the Angular 7 application to run alongside the Angular.JS application.目前我正在努力让 Angular 7 应用程序与 Angular.JS 应用程序一起运行。 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.我们希望运行 Angular 7 应用程序以在当前应用程序的目录中运行,然后将其移动到它自己的 Web 应用程序中,因为我们的新 Angular 应用程序只是一堆静态文件,不需要与服务器捆绑了。 Basically, there is no need for any ASP.NET MVC configuration.基本上,不需要任何 ASP.NET MVC 配置。

The current url would be www.website.com and return the Angular.JS application.当前 url 将是www.website.com并返回 Angular.JS 应用程序。 The new one would be www.website.com/v2/ and would return the Angular 7 application.新的将是www.website.com/v2/并将返回 Angular 7 应用程序。 If we had finished a v2 version of the profile page, navigating to wwww.website.com/v2/profile should now navigate to the profile page of the Angular 7 application.如果我们完成了 v2 版本的profile页面,导航到wwww.website.com/v2/profile现在应该导航到 Angular 7 应用程序的profile页面。

In IIS, one of the virtual folders is a folder called dist which leads to the location of the Angular.JS app files.在 IIS 中,其中一个虚拟文件夹是一个名为dist的文件夹,它指向 Angular.JS 应用程序文件的位置。 A new one called v2 is now configured, which leads to the location of the Angular 7 app files.现在配置了一个名为v2的新文件,它指向 Angular 7 应用程序文件的位置。 Another one called assets leads to the assets folder of the Angular 7 application.另一个名为assets的文件夹指向 Angular 7 应用程序的assets文件夹。

Now, when I navigate to www.website.com/v2/ , Angular starts and routes me to www.website.com/v2/home , which is the home route.现在,当我导航到www.website.com/v2/ ,Angular 会启动并将我路由到www.website.com/v2/home ,这是主路由。

The issue is that when I type in www.website.com/v2/home myself, it results in the application routing back to www.website.com .问题是当我自己输入www.website.com/v2/home ,它会导致应用程序路由回www.website.com and thus it boots up the Angular.JS application again.因此它会再次启动 Angular.JS 应用程序。 There are no errors or redirects taking place.没有发生错误或重定向。 It seems like it just ignores the part that comes after the v2/ part even though Angular.JS does this just fine.似乎它只是忽略了v2/部分之后的部分,即使 Angular.JS 做得很好。

TL;DR Navigating to www.website.com/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.com , even though if {{anything}} was an internal link in Angular 7, it would navigate to the {{anything}} route. TL;DR导航到www.website.com/v2会加载 Angular 7,但导航到v2/{{Anything}}导致应用程序回退到在www.website.com运行的 Angular.JS 应用程序,即使{{anything}}在角7的内部链接,导航到{{anything}}路线。

I build the Angular project with the following command:我使用以下命令构建 Angular 项目:

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

The routes in the angular 7 application look like this: angular 7 应用程序中的路由如下所示:

const routes: Routes = [
  {
    path: '',
    redirectTo: 'home',
    pathMatch: 'full',
  },
  {
    path: '',
    canActivate: [AuthGuard],
    component: DefaultLayoutComponent,
    children: [
      {
        path: 'home',
        component: 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',
    component: LoginComponent,
  },
  {
    path: '403',
    component: Page403Component,
  },
  {
    path: '**',
    redirectTo: '/home',
    pathMatch: 'full',
  },
];

Can anyone tell me how I can make, for example, typing www.website.com/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)谁能告诉我如何使,例如,在浏览器中输入www.website.com/v2/contact导致 v2 联系页面,同时还可以进行内部导航(因此,如果用户单击“导航到v2 联系页面”在 Angular 7 应用程序内部,它还导航到 v2 联系页面)

Edit: Information about the Angular.JS Routerconfig and the back-end web.config were requested;编辑:请求有关 Angular.JS Routerconfig和后端web.config的信息; I have provided them below.我在下面提供了它们。

RouterConfig : 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>

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: 之所以总是将其路由回v1网址,是因为angular 7应用程序包含一个如下所示的web.config文件:

<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. 我认为这是IIS部署的默认设置,团队成员可能已添加了此设置。 I never thought about having a web.config in a front-end project. 我从未想过要在前端项目中使用web.config。

Basically, this rule takes care of rerouting the user to the index.html. 基本上,此规则负责将用户重新路由到index.html。 For example www.website.com/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.com and then lets angular route the folder part. 例如, www.website.com/folder folder通常会将用户带到Web服务器上的一个名为folder的文件folder ,但这不是Angular运行的位置,并且可能会导致404。此规则将用户带回www.website.com ,然后让角度路由folder部分。

Because I am running my application in a subfolder, I changed the url="/" to url="/v2/" and it worked immediatly! 因为我在子文件夹中运行应用程序,所以我将url="/"更改为url="/v2/"并立即生效!

Remember to build the project with ng build --configuration=dev --deploy-url=/v2/ --base-href=/v2/ ! 请记住使用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; 需要deploy-url,因为在服务器的根文件夹中找不到脚本/ css /其他文件。 it is found in /v2/. 在/ v2 /中可以找到它。 The base-href is necessary for the router; 路由器需要base-href; it should start routing the application at www.website.com/v2/ and not at www.website.com/ ! 它应该从www.website.com/v2/而不是www.website.com/开始路由应用程序!

No other iis rewrite rules are necessary, no asp.net config, no special angular routing. 无需其他iis重写规则,asp.net配置,特殊的角度路由。 Just these simple steps! 这些简单的步骤!

Have you made any modification to your Web.config file? 您是否对Web.config文件进行了任何修改? 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... 您需要为基本的角度应用程序设置它(使用UrlRewrite模块),我认为它可能需要针对您的用例进行修改...

<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) (注意:重写应该与您的ng build base href值匹配)

  1. Remove your Web.Config IIS rewrite rules 删除您的Web.Config IIS rewrite rules
  2. In your RouteConfig change it this way 在您的RouteConfig以这种方式更改它

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. 基本上,此操作将捕获您使用特定路由名称指定的所有路由路径, {*url}捕获所有路由段,无论其值如何。

So when we say the url is; 所以当我们说URL是

  • localhost:4200/test <- this points to Default localhost:4200 / test <-这指向Default
  • localhost:4200/v2/test <- this points to V2 本地主机:4200 / v2 / test <-指向V2
  • localhost:4200/test/something/2323 <- this points to Default 本地主机:4200 / test / something / 2323 <-这指向Default
  • localhost:4200/v2/test2/test_again/2323 <- this points to V2 本地主机:4200 / v2 / test2 / test_again / 2323 <-指向V2

and in your HomeController make sure to add the IndexV2 并在您的HomeController确保添加IndexV2

HomeController 家庭控制器

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

For .Net Core 3 or higher对于 .Net Core 3 或更高版本


if 404 happened in the angular subdirectory, it's because of the default route config.如果 404 发生在 angular 子目录中,那是因为默认路由配置。 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();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM