Маршрутизация в Angular 7 работает в подпапке некорректно

Мы работаем над переносом нашего приложения на новую версию Angular. Старый (Angular.JS) был собственным приложением / репо, обслуживаемым приложением .NET Framework 4.5.2 ASP.NET MVC, которое перенаправляло каждый вызов на Home, которое возвращало Razor View, содержащее приложение angular, а затем запускало это вверх, возможно, перенаправив суффикс URL-адреса на фактическую страницу Angular. Например, он направит www.website.com/profile на маршрут profile в Angular, НЕ пытаясь получить доступ к папке с именем profile на сервере. Интеграция нашего API и приложения Angular.JS не слишком приятна, но сработала. На сервере также есть виртуальные папки в IIS для других подпапок, к которым следует обращаться, например, шрифтов, изображений, конфигураций и т. д.

В настоящее время я работаю над тем, чтобы приложение Angular 7 работало вместе с приложением Angular.JS. Мы хотим запустить приложение Angular 7 для запуска внутри каталога текущего приложения, а затем переместить его в собственное веб-приложение, потому что наше новое приложение Angular представляет собой просто набор статических файлов и его не нужно связывать с сервером. больше. По сути, нет необходимости в какой-либо конфигурации ASP.NET MVC.

Текущий URL-адрес будет www.website.com и вернет приложение Angular.JS. Новый будет www.website.com/v2/ и вернет приложение Angular 7. Если мы закончили версию v2 страницы profile, переход к wwww.website.com/v2/profile должен теперь перейти на страницу profile приложения Angular 7.

В IIS одна из виртуальных папок - это папка с именем dist, которая указывает расположение файлов приложения Angular.JS. Теперь настроен новый под названием v2, который указывает на расположение файлов приложения Angular 7. Другой, названный assets, ведет к папке assets приложения Angular 7.

Теперь, когда я перехожу к www.website.com/v2/, Angular запускает и направляет меня к www.website.com/v2/home, который является домашним маршрутом.

Проблема заключается в том, что когда я сам набираю www.website.com/v2/home, это приводит к обратному перенаправлению приложений на www.website.com. и таким образом он снова загружает приложение Angular.JS. Ошибок и перенаправлений нет. Похоже, что он просто игнорирует часть, которая идет после части v2/, хотя Angular.JS отлично справляется с этим.

TL; DR Переход к www.website.com/v2 загружает Angular 7, но переход к v2/{{Anything}} приводит к тому, что приложение возвращается к приложению Angular.JS, работающему на www.website.com, даже если {{anything}} был внутренней ссылкой в ​​Angular 7, он было бы переходит к маршруту {{anything}}.

Я создаю проект Angular с помощью следующей команды:

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

Маршруты в приложении 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',
  },
];

Может ли кто-нибудь сказать мне, как я могу, например, ввести www.website.com/v2/contact в браузере, чтобы перейти на страницу контактов v2, а также сделать возможной внутреннюю навигацию (так, если пользователь нажимает «перейти на страницу контактов v2» внутри Angular 7, оно также переходит на страницу контактов v2)

Обновлено: была запрошена информация об Angular.JS Routerconfig и внутреннем web.config; Я привел их ниже.

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>

включите сюда свой RouterConfig

John Velasquez 11.01.2019 17:28

@JohnVelasquez Спасибо за ваш комментарий. Я сам бэкендер, вы имеете в виду Angular.JS RouterConfig? Если нет, то какая еще информация о маршрутизации приложения Angular 7 вам нужна? На данный момент я отредактировал основной пост, включив в него RouterConfig приложения Angular JS; пожалуйста, взгляните еще раз, если у вас есть время.

S. ten Brinke 12.01.2019 16:11

Вы используете ASP.NET MVC? Если да, включите RouteConfig

John Velasquez 12.01.2019 17:33

Извините, я забыл сказать вам, что я говорил об ASP.NET

John Velasquez 12.01.2019 17:34

Что ж, у него есть маршрут по умолчанию, который вы всегда получаете, и по умолчанию для этого маршрута следует перейти к Homecontroller, который возвращает представление, которое в сочетании с базовым макетом в razor запускает приложение Angular JS.

S. ten Brinke 12.01.2019 19:31
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
3
5
7 979
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Вы вносили какие-либо изменения в свой файл Web.config? Вам нужно настроить его для базового приложения angular (используя модуль 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>

Я предполагаю, что вам нужно будет добавить сюда еще одно «правило». Надеюсь это поможет!!! (примечание: предполагается, что перезапись должна соответствовать вашему базовому значению href для сборки ng)

Привет! Я отредактировал свой пост, чтобы показать вам значения правил перезаписи IIS. Изначально моя виртуальная папка для Angular 7 называлась distv2, чтобы отразить, что dist был для Angular JS, а distv2 для Angular 7. Запросы, поступавшие для /v2/, затем переписывались в /distv2/. У меня были проблемы с этим, и поэтому я переименовал виртуальную папку v2, поэтому я считаю, что никакие другие перезаписи не нужны. Спасибо за уделенное время!

S. ten Brinke 12.01.2019 16:17
  1. Удалите ваш Web.Config IIS rewrite rules
  2. В вашем 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 }
            );
        }
 }

По сути, это означает, что он будет перехватывать все ваши пути маршрута, заданные с конкретным именем маршрута, {*url} перехватывает весь сегмент маршрута независимо от значения.

Итак, когда мы говорим, что URL-адрес;

  • localhost: 4200 / test <- это указывает на Default
  • localhost: 4200 / v2 / test <- это указывает на V2
  • localhost: 4200 / test / something / 2323 <- это указывает на Default
  • localhost: 4200 / v2 / test2 / test_again / 2323 <- это указывает на V2

и в вашем HomeController обязательно добавьте IndexV2

HomeController

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

Я понимаю, к чему вы идете, но это будет означать, что мое новое приложение Angular все еще необходимо интегрировать с ASP.NET MVC. Было бы круче, если бы их можно было разделить, чтобы мы могли при необходимости выпускать их по отдельности. Могу ли я не использовать localhost:4200/v2/test2/test_again/2323, используя правило перезаписи, которое перенаправляло бы этот URL-адрес на localhost:4200/v2, а затем позволяло angular делать все остальное (чего я и хочу)? Тогда я бы сделал почти то же самое, что и решение ASP.NET MVC.

S. ten Brinke 13.01.2019 15:36

Я думаю, что так лучше, чтобы вы могли разделить _Layout на каждую версию,

John Velasquez 13.01.2019 15:54

Это! Это ASP.NET MVC, а Angular JS обслуживается с использованием описываемой вами техники. Но приложение angular 7 - это просто статические файлы, поэтому, если они НЕ связаны с ASP.NET MVC, мы можем развернуть интерфейс и сервер отдельно. Вот почему я бы предпочел решение, в котором нам не нужно делать ничего специфичного для ASP.NET MVc :)

S. ten Brinke 13.01.2019 17:43

хммм, я не знаком с правилами перезаписи, это единственный ответ, который я могу для вас сделать

John Velasquez 14.01.2019 07:56
Ответ принят как подходящий

Причина, по которой он всегда будет возвращаться к URL-адресу 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>

Я считаю, что это значение по умолчанию для развертывания IIS, и член группы мог добавить это. Я никогда не думал о наличии web.config во фронтенд-проекте.

По сути, это правило заботится о перенаправлении пользователя на index.html. Например, www.website.com/folder обычно переносит пользователя в папку с именем folder на веб-сервере, но Angular запускается не здесь и может вызвать ошибку 404. Это правило возвращает пользователя к www.website.com, а затем позволяет angular маршрутизировать часть folder.

Поскольку я запускаю свое приложение в подпапке, я изменил url = "/" на url = "/v2/", и оно сразу заработало!

Не забудьте собрать проект с ng build --configuration=dev --deploy-url=/v2/ --base-href=/v2/! URL-адрес развертывания необходим, потому что файлы scripts / css / other не найдены в корневой папке сервера; он находится в / v2 /. Для маршрутизатора необходим base-href; он должен начать маршрутизировать приложение с www.website.com/v2/, а не с www.website.com/!

Никаких других правил перезаписи iis не требуется, никакой конфигурации asp.net, никакой специальной угловой маршрутизации. Всего лишь эти простые шаги!

Для .Net Core 3 или выше


если 404 произошло в подкаталоге angular, это из-за конфигурации маршрута по умолчанию. так что это будет исправлено написанием этого кода при запуске.

 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();

Другие вопросы по теме