Làm cách nào để định cấu hình IIS cho URL Viết lại ứng dụng AngularJS trong chế độ HTML5?


140

Tôi có dự án hạt giống AngularJS và tôi đã thêm

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

vào tệp app.js. Tôi muốn định cấu hình IIS 7 để định tuyến tất cả các yêu cầu tới

http://localhost/app/index.html

để điều này làm việc cho tôi. Làm thế nào để tôi làm điều này?

Cập nhật:

Tôi vừa mới phát hiện, tải xuống và cài đặt mô-đun Viết lại URL IIS , hy vọng điều này sẽ giúp việc đạt được mục tiêu của tôi trở nên dễ dàng và rõ ràng.

Cập nhật 2 :

Tôi đoán điều này tổng hợp những gì tôi đang cố gắng đạt được (lấy từ tài liệu Nhà phát triển AngularJS ):

Sử dụng chế độ này yêu cầu viết lại URL ở phía máy chủ, về cơ bản, bạn phải viết lại tất cả các liên kết của bạn đến điểm vào của ứng dụng của bạn (ví dụ: index.html)

Cập nhật 3:

Tôi vẫn đang làm việc này và tôi nhận ra rằng tôi KHÔNG cần chuyển hướng (có quy tắc viết lại) một số URL nhất định như

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

vì vậy bất cứ điều gì trong các thư mục css, js, lib hoặc partials đều không được chuyển hướng. Mọi thứ khác sẽ cần được chuyển hướng đến app / index.html

Bất cứ ai cũng biết làm thế nào để đạt được điều này một cách dễ dàng mà không cần phải thêm một quy tắc cho mỗi tệp duy nhất?

Cập nhật 4:

Tôi có 2 quy tắc gửi đến được xác định trong mô-đun Viết lại URL IIS. Nguyên tắc đầu tiên là:

Viết lại URL IIS Quy tắc gửi đến 1

Quy tắc thứ hai là:

Viết lại URL IIS Quy tắc gửi đến 2

Bây giờ khi tôi điều hướng đến localhost / app / view1, nó sẽ tải trang, tuy nhiên các tệp hỗ trợ (các tệp trong thư mục css, js, lib và partials) cũng đang được ghi lại vào trang app / index.html - vì vậy mọi thứ đang đến trở lại là trang index.html cho dù URL nào được sử dụng. Tôi đoán điều này có nghĩa là quy tắc đầu tiên của tôi, được cho là để ngăn các URL này được xử lý bởi quy tắc thứ hai, không hoạt động .. có ý tưởng nào không? ...bất kỳ ai? ...Tôi cảm thây cô đơn... :-(


Cảm ơn vì điều đó! Rất hữu ích!
Ash Clarke

quy tắc thứ hai rất quan trọng: bạn cần đảm bảo rằng nó định tuyến app/index.htmlkhông app/ kích hoạt rõ ràng trang phục vụ AngularJS. tôi đã mất 2 giờ trong cuộc đời trước khi tôi nhận ra. :-)
Dexter Legaspi

Một cách khác để sử dụng ASP.NET MVC và thêm vào RouteConfig.cs: Rout.MapRoute (tên: "Mặc định", url: "{* anything}", mặc định: new {controller = "Home", action = "Index", }); và Chỉ mục HomeControll của bạn chỉ trả về Tệp ("~ / index-anyhinghere.html", "text / html"); Sau đó, ứng dụng của bạn trở nên độc lập với IIS
Bộ công cụ

Tôi đã phải cài đặt "mô-đun viết lại URL từ 'Trình cài đặt web'". Nếu mô-đun viết lại url không có ở đó, thì trong khi tải lại, viết lại sẽ không hoạt động. CÀI ĐẶT mô-đun viết lại URL. :)
Bimal Das

Câu trả lời:


289

Tôi viết ra một quy tắc trong web.config sau khi $locationProvider.html5Mode(true)được đặt app.js.

Hy vọng, giúp ai đó ra ngoài.

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

Trong index.html của tôi, tôi đã thêm cái này vào <head>

<base href="/">

Đừng quên cài đặt IIS URL Rewrite trên máy chủ.

Ngoài ra, nếu bạn sử dụng API Web và IIS, điều này sẽ hoạt động nếu API của bạn ở www.yourdomain.com/apivì đầu vào thứ ba (dòng điều kiện thứ ba).


2
Điều này rất hữu ích và tôi thấy nó là hoàn thiện nhất. Cảm ơn!
Mario

2
rất vui vì nó giúp @Mario
Yagiz Ozturk

5
HOÀN HẢO! Đây là một vấn đề khó khăn đối với tôi, đã dành hàng giờ để làm việc này. Cảm ơn! LỜI KHUYÊN CHO BẤT CỨ AI: Tôi đã thêm index.html vào <action type = "Rewrite" url "/index.html" /> Sau đó trên index.html của tôi (tệp thư mục gốc cho Angular SPA, <base href = "/ index .html "/> Khi tôi đối phó mã ở trên, nó không khớp với <base href /> của tôi nên nó không hoạt động chính xác. Cũng có những đạo cụ lớn cho mẫu" / (api) ", tôi tiếp tục vấp phải phần đó.
Brad Martin

Nếu tôi lưu trữ trên các trang web Azure thì sao?
Bộ công cụ

7
Đó là một trò đùa mà chúng ta phải nhảy qua các vòng để định tuyến Angular. Điều này giết chết định tuyến góc cho tôi. Thật là một mớ hỗn độn.
dùng441521

38

Các quy tắc gửi đến IIS như trong câu hỏi DO hoạt động. Tôi đã phải xóa bộ đệm của trình duyệt và thêm dòng sau vào đầu <head>phần của trang index.html:

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

Điều này là do tôi có nhiều hơn một ứng dụng trong localhost và vì vậy các yêu cầu cho các phần khác đã được đưa đến localhost/app/view1thay vìlocalhost/myApplication/app/view1

Hy vọng điều này sẽ giúp được ai đó!


1
Tôi không cần điều này, nhưng các chỉnh sửa câu hỏi rất hay. Cảm ơn!
Ash Clarke

2
Ngoài ra điều này có thể hữu ích. Làm việc cho tôi khi tải lại trang. Không có bất kỳ quy tắc đặc biệt nào cho mọi tệp: coderwall.com/p/mycbiq
Per G

như @ ash-clarke đã nói, dù sao thì nó cũng không cần thiết nhưng dù sao thì nó cũng cho phép các liên kết trên trang không biết về "thư mục con" nào.
Dexter Legaspi

@PerG Tôi đã chạy vào giải pháp trên hoạt động nhưng không tải lại, đây là mã của tôi: stackoverflow.com/questions/25644287/iis-url-rewrite-rules Có ý tưởng nào không?
amcdnl

Tôi không biết hoặc đã thử lọc các cuộc gọi nhất định. Một cách khác là có API trên miền khác, v.v. Nhưng có lẽ đây không phải là giải pháp cho bạn. Nhưng bạn có thể tiếp tục hỏi trong liên kết của tôi ở trên. Và có lẽ tác giả có thể trả lời bạn?
Mỗi

11

Trong trường hợp của tôi, tôi tiếp tục nhận được 403,14 sau khi tôi đã thiết lập các quy tắc viết lại chính xác. Hóa ra tôi có một thư mục cùng tên với một trong các tuyến URL của tôi. Khi tôi xóa quy tắc viết lại IsDirectory, các tuyến của tôi hoạt động chính xác. Có một trường hợp trong đó loại bỏ các tiêu cực thư mục có thể gây ra vấn đề? Tôi không thể nghĩ về bất kỳ trường hợp nào của tôi. Trường hợp duy nhất tôi có thể nghĩ là nếu bạn có thể duyệt một thư mục với ứng dụng của bạn.

<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

Vấn đề chỉ có hai điều kiện sau:

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

là chúng chỉ hoạt động miễn là {REQUEST_FILENAME} tồn tại vật lý trên đĩa . Điều này có nghĩa là có thể có các kịch bản trong đó yêu cầu cho chế độ xem một phần được đặt tên không chính xác sẽ trả về trang gốc thay vì 404 sẽ khiến cho góc được tải hai lần (và trong một số trường hợp nhất định, nó có thể gây ra một vòng lặp vô hạn khó chịu).

Vì vậy, một số quy tắc "dự phòng" an toàn sẽ được đề xuất để tránh những vấn đề khó khắc phục này:

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

hoặc một điều kiện phù hợp với bất kỳ tập tin kết thúc :

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

1
Với tất cả những điều này, trang web của tôi tải rất tốt, nhưng nếu tôi đang ở một con đường dọc theo tuyến đường thì tôi có vấn đề. Do đó, nếu đường dẫn trong trình duyệt của tôi là: 10.34.34.46/jbvdev/document/BC498484 Ban đầu, nó hiển thị tốt, nhưng nếu tôi nhấn refresh, mọi thứ sẽ vỡ vì nó bắt đầu tìm kiếm css và js tại 10.34.34.46/jbvdev/document / css hoặc 10.34.34.46/jbvdev/document/js Có ai biết cách giải quyết vấn đề này không?
Michael Mahony

1

Cách dễ nhất tôi tìm thấy chỉ là chuyển hướng các yêu cầu kích hoạt 404 đến máy khách. Điều này được thực hiện bằng cách thêm một hashtag ngay cả khi $locationProvider.html5Mode(true)được đặt.

Thủ thuật này hoạt động đối với các môi trường có nhiều Ứng dụng web trên cùng một Trang web và yêu cầu các ràng buộc toàn vẹn URL (xác thực bên ngoài EG). Dưới đây là từng bước làm thế nào để làm

index.html

Đặt <base>phần tử đúng

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

web.config

Đầu tiên chuyển hướng 404 đến một trang tùy chỉnh, ví dụ "Trang chủ / Lỗi"

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

Bộ điều khiển gia đình

Thực hiện một ActionResultđầu vào đơn giản để "dịch" trong tuyến khách hàng.

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

Đây là cách đơn giản nhất.


Có thể (nên dùng?) Để tăng cường chức năng Lỗi với một số logic được cải tiến để chuyển hướng 404 sang máy khách khi url hợp lệ và để kích hoạt 404 bình thường khi không tìm thấy gì trên máy khách. Giả sử bạn có những tuyến đường góc cạnh này

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

Thật ý nghĩa khi chuyển hướng URL đến máy khách chỉ khi nó bắt đầu bằng "/ Mới" hoặc "/ Hiển thị /"

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

Đây chỉ là một ví dụ về logic cải tiến, tất nhiên mỗi ứng dụng web có nhu cầu khác nhau


1

Tôi đã cố gắng triển khai một ứng dụng Angular 7 đơn giản, lên Ứng dụng web Azure. Tất cả mọi thứ hoạt động tốt, cho đến khi bạn làm mới trang. Làm như vậy, đã cho tôi một lỗi 500 - di chuyển nội dung. Tôi đã đọc cả trên các tài liệu Angular và trên một vài diễn đàn tốt, rằng tôi cần thêm tệp web.config vào giải pháp đã triển khai của mình và đảm bảo quy tắc viết lại dự phòng cho tệp index.html. Sau nhiều giờ thất vọng và thử nghiệm và kiểm tra lỗi, tôi đã tìm thấy lỗi khá đơn giản: thêm một thẻ xung quanh đánh dấu tệp của tôi.


1

Tôi gặp vấn đề tương tự với Angular và IIS khi ném mã trạng thái 404 khi làm mới thủ công và thử giải pháp được bình chọn nhiều nhất nhưng điều đó không hiệu quả với tôi. Cũng đã thử một loạt các giải pháp khác phải đối phó với WebDAV và thay đổi trình xử lý và không có giải pháp nào hoạt động.

May mắn thay tôi đã tìm thấy giải pháp này và nó đã hoạt động (lấy ra những phần tôi không cần). Vì vậy, nếu không có cách nào ở trên phù hợp với bạn hoặc thậm chí trước khi thử chúng, hãy thử điều này và xem liệu điều đó có khắc phục được việc triển khai góc cạnh của bạn về vấn đề iis không.

Thêm đoạn mã vào cấu hình web của bạn trong thư mục gốc của trang web của bạn. Theo hiểu biết của tôi, nó sẽ xóa mã trạng thái 404 khỏi bất kỳ sự kế thừa nào (applicationationhost.config, machine.config), sau đó tạo mã trạng thái 404 ở cấp trang web và chuyển hướng trở lại trang chủ dưới dạng trang 404 tùy chỉnh.

<?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>
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.