Bagaimana cara mengkonfigurasi IIS untuk URL Menulis ulang aplikasi AngularJS dalam mode HTML5?


140

Saya memiliki proyek seed AngularJS dan saya telah menambahkan

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

ke file app.js. Saya ingin mengkonfigurasi IIS 7 untuk merutekan semua permintaan

http://localhost/app/index.html

sehingga ini bekerja untuk saya. Bagaimana saya melakukan ini?

Memperbarui:

Saya baru saja menemukan, mengunduh dan menginstal modul Penulisan Ulang URL IIS , berharap ini akan membuatnya mudah dan jelas untuk mencapai tujuan saya.

Pembaruan 2 :

Saya kira ini merangkum apa yang saya coba capai (diambil dari dokumentasi Pengembang AngularJS ):

Menggunakan mode ini memerlukan penulisan ulang URL di sisi server, pada dasarnya Anda harus menulis ulang semua tautan Anda ke titik masuk aplikasi Anda (mis. Index.html)

Pembaruan 3:

Saya masih mengerjakan ini dan saya menyadari bahwa saya TIDAK perlu mengarahkan ulang (memiliki aturan yang menulis ulang) URL tertentu seperti

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

jadi apa pun yang ada di direktori css, js, lib, atau parsial tidak dialihkan. Semua yang lain perlu diarahkan ke app / index.html

Adakah yang tahu cara mencapai ini dengan mudah tanpa harus menambahkan aturan untuk setiap file?

Pembaruan 4:

Saya memiliki 2 aturan masuk yang ditentukan dalam modul Penulisan Ulang URL IIS. Aturan pertama adalah:

URL IIS Menulis Ulang Aturan Masuk 1

Aturan kedua adalah:

URL IIS Menulis Ulang Aturan Masuk 2

Sekarang ketika saya menavigasi ke localhost / app / view1 memuat halaman, namun file pendukung (yang ada di direktori css, js, lib dan partials) juga sedang ditulis ulang ke halaman app / index.html - jadi semuanya akan datang kembali sebagai halaman index.html apa pun URL yang digunakan. Saya kira ini berarti aturan pertama saya, yang seharusnya mencegah URL ini diproses oleh aturan kedua, tidak berfungsi .. ada ide? ...siapa saja? ...Saya merasa begitu sendirian... :-(


Terima kasih untuk ini! Sangat membantu!
Ash Clarke

aturan kedua sangat penting: Anda perlu memastikan bahwa itu merutekan ke app/index.htmldan tidak app/ secara eksplisit memicu halaman yang menyajikan AngularJS. saya kehilangan 2 jam hidup saya sebelum saya menemukan jawabannya. :-)
Dexter Legaspi

Cara lain untuk menggunakan ASP.NET MVC dan tambahkan ke RouteConfig.cs: routes.MapRoute (nama: "Default", url: "{* anything}", default: new {controller = "Home", action = "Index", }); dan Indeks HomeController Anda hanya mengembalikan File ("~ / index-anyhinghere.html", "text / html"); Kemudian aplikasi Anda menjadi IIS independen
Toolkit

Saya harus menginstal "modul penulisan ulang URL dari 'Web Installer'". Jika modul penulisan ulang url tidak ada, maka saat memuat ulang, menulis ulang tidak akan berfungsi. INSTALL modul penulisan ulang URL. :)
Bimal Das

Jawaban:


289

Saya menulis aturan di web.config setelah $locationProvider.html5Mode(true)diatur app.js.

Semoga, bantu seseorang keluar.

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

Di index.html saya menambahkan ini ke <head>

<base href="/">

Jangan lupa untuk menginstal IIS URL Rewrite di server.

Juga jika Anda menggunakan Web API dan IIS, ini akan berfungsi jika API Anda berada di www.yourdomain.com/apikarena input ketiga (kondisi baris ketiga).


2
Ini sangat berguna dan saya menemukan itu menjadi yang paling lengkap. Terima kasih!
Mario

2
senang ini membantu @Mario
Ozturk

5
SEMPURNA! Yang ini adalah masalah yang sulit bagi saya, menghabiskan berjam-jam mengerjakan ini. Terima kasih! NASIHAT KEPADA SIAPA SAJA: Saya menambahkan index.html ke <action type = "Tulis ulang" url "/index.html" /> Kemudian pada index.html saya (file direktori root untuk Angular SPA, <base href = "/ index .html "/> Ketika saya menyalin kode di atas, itu tidak cocok dengan <base href /> saya sehingga tidak berfungsi dengan benar. Alat peraga besar untuk pola" / (api) "juga, saya terus tersandung pada bagian itu.
Brad Martin

bagaimana jika saya meng-host di situs web Azure?
Toolkit

7
Ini adalah lelucon bahwa kita harus melompat melalui lingkaran ini untuk routing Angular. Ini membunuh rute sudut bagi saya. Berantakan sekali.
user441521

38

Aturan masuk IIS seperti yang ditunjukkan dalam pertanyaan DO berfungsi. Saya harus menghapus cache browser dan menambahkan baris berikut di bagian atas <head>halaman index.html saya:

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

Ini karena saya memiliki lebih dari satu aplikasi di localhost dan permintaan untuk parsial lainnya sedang dibawa ke localhost/app/view1bukannyalocalhost/myApplication/app/view1

Semoga ini bisa membantu seseorang!


1
Saya tidak membutuhkan ini, tetapi suntingan pertanyaannya bagus. Terima kasih!
Ash Clarke

2
Ini juga bisa bermanfaat. Bekerja untuk saya saat memuat ulang laman. Tanpa aturan khusus untuk setiap file: coderwall.com/p/mycbiq
Per G

seperti yang dikatakan @ ash-clarke, itu tidak perlu tetapi tetap merupakan praktik yang baik karena memungkinkan tautan pada halaman menjadi agnostik tentang "subdirektori" yang dimilikinya.
Dexter Legaspi

@ PerG Saya berlari ke solusi di atas bekerja tetapi tidak pada reload, di sini adalah kode saya: stackoverflow.com/questions/25644287/iis-url-rewrite-rules Ada ide?
amcdnl

Saya tidak tahu atau sudah mencoba menyaring panggilan tertentu. Cara lain adalah dengan memiliki API di domain lain dll. Tapi mungkin ini bukan solusi untuk Anda. Tetapi Anda dapat terus bertanya di tautan saya di atas. Dan mungkin penulis dapat menjawab Anda?
Per G

11

Dalam kasus saya, saya terus mendapatkan 403.14 setelah saya mengatur aturan penulisan ulang yang benar. Ternyata saya memiliki direktori dengan nama yang sama dengan salah satu rute URL saya. Setelah saya menghapus aturan penulisan ulang IsDirectory, rute saya berfungsi dengan benar. Apakah ada kasus di mana menghapus negasi direktori dapat menyebabkan masalah? Saya tidak bisa memikirkan apa pun dalam kasus saya. Satu-satunya kasus yang dapat saya pikirkan adalah jika Anda dapat menelusuri direktori dengan aplikasi Anda.

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

10

Masalah dengan hanya memiliki dua kondisi ini:

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

adalah bahwa mereka hanya berfungsi selama {REQUEST_FILENAME} ada secara fisik pada disk . Ini berarti bahwa mungkin ada skenario di mana permintaan untuk tampilan parsial dengan nama yang salah akan mengembalikan halaman root alih-alih 404 yang akan menyebabkan sudut dimuat dua kali (dan dalam skenario tertentu dapat menyebabkan loop tak terhingga yang tak terhingga).

Karenanya, beberapa aturan "fallback" yang aman akan direkomendasikan untuk menghindari masalah yang sulit dipecahkan ini:

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

atau suatu kondisi yang cocok dengan akhiran file apa pun :

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

1
Dengan semua ini di tempat situs saya memuat dengan baik, tetapi jika saya berada di jalur di sepanjang rute saya memiliki masalah. Jadi, jika path di browser saya adalah: 10.34.34.46/jbvdev/documents/BC498484 Awalnya itu muncul baik-baik saja, tetapi jika saya menekan refresh, semuanya rusak karena mulai mencari css dan js di 10.34.34.46/jbvdev/documents / css atau 10.34.34.46/jbvdev/documents/js Apakah ada yang tahu cara mengatasi yang ini?
Michael Mahony

1

Cara termudah yang saya temukan adalah hanya mengarahkan permintaan yang memicu 404 ke klien. Ini dilakukan dengan menambahkan tagar bahkan ketika $locationProvider.html5Mode(true)diatur.

Trik ini berfungsi untuk lingkungan dengan Aplikasi Web yang lebih banyak di Situs Web yang sama dan memerlukan batasan integritas URL (EG external authentication). Berikut langkah demi langkah gimana caranya

index.html

Atur <base>elemen dengan benar

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

web.config

Redirect pertama 404 ke halaman kustom, misalnya "Rumah / Kesalahan"

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

Pengontrol rumah

Terapkan ActionResultinput "terjemahan" yang sederhana ke rute yang berada di sisi klien.

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

Ini adalah cara paling sederhana.


Dimungkinkan (disarankan?) Untuk meningkatkan fungsi Kesalahan dengan beberapa logika yang ditingkatkan untuk mengarahkan 404 ke klien hanya ketika url valid dan membiarkan pemicu 404 secara normal ketika tidak ada yang ditemukan pada klien. Katakanlah Anda memiliki rute sudut ini

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

Masuk akal untuk mengarahkan ulang URL ke klien hanya ketika dimulai dengan "/ Baru" atau "/ Tampilkan /"

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

Ini hanyalah contoh dari logika yang ditingkatkan, tentu saja setiap aplikasi web memiliki kebutuhan yang berbeda


1

Saya sudah mencoba untuk menyebarkan aplikasi Angular 7 sederhana, ke Aplikasi Web Azure. Semuanya berfungsi dengan baik, sampai pada titik di mana Anda me-refresh halaman. Melakukan hal itu, mempresentasikan saya dengan 500 kesalahan - pindah konten. Saya telah membaca dokumen Angular dan di sekitar beberapa forum yang bagus, bahwa saya perlu menambahkan file web.config ke solusi yang saya gunakan dan memastikan aturan penulisan ulang mundur ke file index.html. Setelah berjam-jam frustrasi dan uji coba dan kesalahan, saya menemukan kesalahan itu cukup sederhana: menambahkan tag di sekitar markup file saya.


1

Saya memiliki masalah serupa dengan Angular dan IIS melemparkan kode status 404 pada penyegaran manual dan mencoba solusi yang paling banyak dipilih tetapi itu tidak berhasil untuk saya. Juga mencoba banyak solusi lain yang harus berurusan dengan WebDAV dan mengubah penangan dan tidak ada yang berhasil.

Untungnya saya menemukan solusi ini dan berhasil (mengeluarkan bagian yang tidak saya butuhkan). Jadi, jika tidak ada di atas yang berfungsi untuk Anda atau bahkan sebelum mencobanya, coba ini dan lihat apakah itu memperbaiki penyebaran sudut Anda pada masalah iis.

Tambahkan snippet ke konfigurasi web Anda di direktori root situs Anda. Dari pemahaman saya, ini menghapus kode status 404 dari warisan apa pun (applicationhost.config, machine.config), kemudian membuat kode status 404 di tingkat situs dan mengarahkan kembali ke halaman beranda sebagai halaman 404 khusus.

<?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>
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.