Как настроить IIS для перезаписи URL-адреса приложения AngularJS в режиме HTML5?

У меня есть начальный проект AngularJS, и я добавил

$locationProvider.html5Mode(true).hashPrefix('!');

в файл app.js. Я хочу настроить IIS 7 для маршрутизации всех запросов

http://localhost/app/index.html

так что это работает для меня. Как мне это сделать?

Обновить:

Я только что обнаружил, скачал и установил модуль IIS URL Rewrite, надеясь, что это поможет легко и очевидно достичь моей цели.

Обновление 2:

Я предполагаю, что это подводит итог того, что я пытаюсь достичь (взято из документации разработчика AngularJS):

Использование этого режима требует перезаписи URL на стороне сервера, в основном вы должны переписать все ваши ссылки на точку входа вашего приложения (например, index.html)

Обновление 3:

Я все еще работаю над этим, и я понимаю, что мне НЕ нужно перенаправлять (есть правила, которые переписывают) определенные URL, такие как

http://localhost/app/lib/angular/angular.js
http://localhost/app/partials/partial1.html

поэтому все, что находится в каталогах css, js, lib или partials, не перенаправляется. Все остальное нужно будет перенаправить в app/index.html.

Кто-нибудь знает, как легко добиться этого, не добавляя правила для каждого отдельного файла?

Обновление 4:

У меня есть 2 входящие правила, определенные в модуле перезаписи URL IIS. Первое правило:

IIS URL переписать входящее правило 1

Второе правило:

URL IIS переписать входящее правило 2

Теперь, когда я перехожу к localhost / app / view1, он загружает страницу, однако вспомогательные файлы (файлы в каталогах css, js, lib и partials) также переписываются на страницу app/index.html - так что все идет обратно как страница index.html независимо от того, какой URL используется. Я думаю, это означает, что мое первое правило, которое должно предотвратить обработку этих URL-адресов вторым правилом, не работает... какие-нибудь идеи? ...кто-нибудь? ...Я чувствую себя таким одиноким...:-(

9 ответов

Решение

Правила входящего IIS, как показано в вопросе, работают. Я должен был очистить кеш браузера и добавить следующую строку в верхней части моего <head> раздел страницы index.html:

<base href="/myApplication/app/" />

Это потому, что у меня есть несколько приложений на локальном хосте, и поэтому запросы к другим частям были приняты localhost/app/view1 вместо localhost/myApplication/app/view1

Надеюсь, это кому-нибудь поможет!

Выписываю правило в web.config после $locationProvider.html5Mode(true) установлен в app.js,

Надеюсь, выручит кого-то.

  <system.webServer>
    <rewrite>
      <rules>
        <rule name="AngularJS Routes" stopProcessing="true">
          <match url=".*" />
          <conditions logicalGrouping="MatchAll">
            <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
            <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
            <add input="{REQUEST_URI}" pattern="^/(api)" negate="true" />
          </conditions>
          <action type="Rewrite" url="/" />
        </rule>
      </rules>
    </rewrite>
  </system.webServer>

В моем index.html я добавил это в <head>

<base href="/">

Не забудьте установить IIS URL Rewrite на сервере.

Также, если вы используете Web API и IIS, это будет работать, если ваш API находится на www.yourdomain.com/api из-за третьего ввода (третья строка условия).

Проблема только с этими двумя условиями:

  <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
  <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />

является то, что они работают только до тех пор, пока {REQUEST_FILENAME} существует физически на диске. Это означает, что могут быть сценарии, в которых запрос на некорректное частичное представление вернул бы корневую страницу вместо 404, что привело бы к двойной загрузке angular (а в некоторых сценариях это может вызвать неприятный бесконечный цикл).

Таким образом, было бы рекомендовано несколько безопасных "резервных" правил, чтобы избежать этих трудных для устранения проблем:

  <add input="{REQUEST_FILENAME}" pattern="(.*?)\.html$" negate="true" />
  <add input="{REQUEST_FILENAME}" pattern="(.*?)\.js$" negate="true" />
  <add input="{REQUEST_FILENAME}" pattern="(.*?)\.css$" negate="true" />

или условие, которое соответствует любому окончанию файла:

<conditions>
  <!-- ... -->
  <add input="{REQUEST_FILENAME}" pattern=".*\.[\d\w]+$" negate="true" />
</conditions>

В моем случае я продолжал получать 403,14 после того, как я настроил правильные правила перезаписи. Оказывается, у меня был каталог с тем же именем, что и один из моих URL-маршрутов. Как только я удалил правило перезаписи IsDirectory, мои маршруты работали правильно. Есть ли случай, когда удаление отрицания каталога может вызвать проблемы? Я не могу думать ни о чем в моем случае. Единственный случай, о котором я могу подумать, - это если вы можете просматривать каталог с помощью своего приложения.

<rule name="fixhtml5mode" stopProcessing="true">
  <match url=".*"/>
  <conditions logicalGrouping="MatchAll">
    <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
  </conditions>
  <action type="Rewrite" url="/" />
</rule>

Лучшее решение для этого, к сожалению, не сработало для меня с использованием .NET framework 4.5 и IIS 6.2. Я заставил его работать, сначала выполнив все шаги по установке инструмента URL Rewrite от Microsoft, а затем настроив свой Web.configфайл, чтобы включить следующее:

          <system.webServer>
    <!-- handlers etc -->
    <rewrite>
      <rules>
        <rule name="Angular Routes" stopProcessing="true">
          <match url="(^(?!.*\.[\d\w]+$).*)" />
          <conditions logicalGrouping="MatchAny">
            <add input="{REQUEST_URI}" pattern=".*\/api\/.*" negate="true" />
          </conditions>
          <action type="Rewrite" url="./index.html" />
        </rule>
      </rules>
    </rewrite>
  </system.webServer>

Первое регулярное выражение использует отрицательный просмотр вперед, чтобы НЕ совпадать с каким-либо расширением файла в конце URI. Затем внутри условия любой URI, включая /api/также игнорируется.

Эта конфигурация позволяет мне обновить приложение Angular, не нарушая маршрутизацию, а также получить доступ к моему API без перезаписи.

У меня была аналогичная проблема с Angular и IIS, которые выдавали код состояния 404 при обновлении вручную, и я попробовал решение, получившее наибольшее количество голосов, но это не сработало для меня. Также пробовал кучу других решений, связанных с WebDAV и изменением обработчиков, и ни одно из них не сработало.

К счастью, я нашел это решение, и оно сработало (вынул ненужные мне детали). Поэтому, если ничего из вышеперечисленного не работает для вас или даже до того, как попробовать их, попробуйте это и посмотрите, исправит ли это ваше развертывание angular по проблеме iis.

Добавьте фрагмент в свой webconfig в корневой каталог вашего сайта. Насколько я понимаю, он удаляет код состояния 404 из любого наследования (applicationhost.config, machine.config), затем создает код состояния 404 на уровне сайта и перенаправляет обратно на домашнюю страницу в качестве настраиваемой страницы 404.

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <system.webServer>
    <httpErrors errorMode="Custom">
      <remove statusCode="404"/>
      <error statusCode="404" path="/index.html" responseMode="ExecuteURL"/>
    </httpErrors>
  </system.webServer>
</configuration>

Самый простой способ, который я нашел, - это просто перенаправить запросы, запускающие 404, к клиенту. Это делается путем добавления хэштега, даже когда $locationProvider.html5Mode(true) установлено.

Этот прием работает в средах с большим количеством веб-приложений на одном веб-сайте, для которых требуются ограничения целостности URL (например, внешняя аутентификация). Вот шаг за шагом, как это сделать

index.html

Установить <base> элемент правильно

<base href="@(Request.ApplicationPath + "/")">

web.config

Сначала перенаправьте 404 на пользовательскую страницу, например "Домой / Ошибка"

<system.web>
    <customErrors mode="On">
        <error statusCode="404" redirect="~/Home/Error" />
    </customErrors>
</system.web>

Домашний контроллер

Реализуйте простой ActionResult "перевести" ввод в клиентский маршрут.

public ActionResult Error(string aspxerrorpath) {
    return this.Redirect("~/#/" + aspxerrorpath);
}

Это самый простой способ.


Возможно (желательно?) Усовершенствовать функцию Error с помощью некоторой улучшенной логики для перенаправления 404 на клиент только в том случае, если URL-адрес действителен, и позволить 404 запускаться нормально, когда на клиенте ничего не будет найдено. Допустим, у вас есть эти угловые маршруты

.when("/", {
    templateUrl: "Base/Home",
    controller: "controllerHome"
})
.when("/New", {
    templateUrl: "Base/New",
    controller: "controllerNew"
})
.when("/Show/:title", {
    templateUrl: "Base/Show",
    controller: "controllerShow"
})

Имеет смысл перенаправлять URL-адрес клиенту только тогда, когда он начинается с "/New" или "/Show/"

public ActionResult Error(string aspxerrorpath) {
    // get clientside route path
    string clientPath = aspxerrorpath.Substring(Request.ApplicationPath.Length);

    // create a set of valid clientside path
    string[] validPaths = { "/New", "/Show/" };

    // check if clientPath is valid and redirect properly
    foreach (string validPath in validPaths) {
        if (clientPath.StartsWith(validPath)) {
            return this.Redirect("~/#/" + clientPath);
        }
    }

    return new HttpNotFoundResult();
}

Это всего лишь пример улучшенной логики, конечно, у каждого веб-приложения свои потребности

Я пытался развернуть простое приложение Angular 7 в веб-приложении Azure. Все работало нормально, до того момента, когда вы обновили страницу. При этом мне показывали ошибку 500 - перемещенный контент. Я прочитал как на Angular docs, так и на нескольких хороших форумах, что мне нужно добавить файл web.config в мое развернутое решение и убедиться, что правило перезаписи восстановлено в файле index.html. После нескольких часов разочарований, проб и ошибок я обнаружил, что ошибка была довольно простой: добавление тега к разметке моего файла.

Я понимаю, что это может быть старый вопрос, но вот еще одно решение без использования файла web.config .

У меня есть два отдельных проекта: FrontEnd (Angular) и BackEnd (веб-API .NET Core).

  1. Измените выходной путь angular.json в параметрах сборки =>: «../BackEnd/wwwroot»

  2. В Program.cs: app.UseDefaultFiles(); приложение.UseStaticFiles();

    Указывает серверу искать index.html по умолчанию в каталоге wwwroot.

  3. ng build — который создал папку wwwroot и все статические угловые файлы в этой папке.

  4. Вместо правил перезаписи в web.config я создал новый контроллер следующим образом:

Фоллбакконтроллер.cs

      [Route("api/[controller]")]
[ApiController]
public class FallbackController : ControllerBase
{
   return PhysicalFile(Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "index.html"), "text/HTML");
}
  1. В Program.cs: app.MapFallbackToController("Index", "Fallback");

Это сообщает нашему API, что ответственность за маршрутизацию принадлежит Angular и ее можно найти в резервном контроллере, который, в свою очередь, указывает на index.html для получения инструкций по маршрутизации.

Программа.cs

      // prior code
app.UseAuthentication();
app.UseAuthorization();

app.UseDefaultFiles();
app.UseStaticFiles();

app.MapControllers();

app.MapFallbackToController("Index", "Fallback");

app.Run();
Другие вопросы по тегам