Как настроить 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. Первое правило:
Второе правило:
Теперь, когда я перехожу к 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).
Измените выходной путь angular.json в параметрах сборки =>: «../BackEnd/wwwroot»
В Program.cs: app.UseDefaultFiles(); приложение.UseStaticFiles();
Указывает серверу искать index.html по умолчанию в каталоге wwwroot.
ng build — который создал папку wwwroot и все статические угловые файлы в этой папке.
Вместо правил перезаписи в web.config я создал новый контроллер следующим образом:
Фоллбакконтроллер.cs
[Route("api/[controller]")]
[ApiController]
public class FallbackController : ControllerBase
{
return PhysicalFile(Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "index.html"), "text/HTML");
}
- В 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();