ฉันจะกำหนดค่า IIS สำหรับ URL การเขียนแอปพลิเคชัน AngularJS ในโหมด HTML5 ได้อย่างไร


140

ฉันมีโครงการเมล็ดพันธุ์ 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 ข้อที่กำหนดไว้ในโมดูล IIS URL Rewrite กฎข้อแรกคือ:

IIS URL กฎการเขียนใหม่ขาเข้า 1

กฎข้อที่สองคือ:

IIS URL กฎการเขียนใหม่ขาเข้า 2

ตอนนี้เมื่อฉันไปที่ localhost / app / view1 มันจะโหลดหน้าเว็บอย่างไรก็ตามไฟล์ที่รองรับ (ไฟล์ที่อยู่ในไดเรกทอรี css, js, lib และ partials) ก็ถูกเขียนใหม่ไปยังหน้า app / index.html กลับมาเป็นหน้า index.html ไม่ว่าจะใช้ URL ใด ฉันเดาว่านี่หมายถึงกฎข้อแรกของฉันที่ควรป้องกันไม่ให้ URL เหล่านี้ถูกประมวลผลโดยกฎข้อที่สองไม่ทำงาน .. แนวคิดใด ๆ ... ใคร? ...ฉันรู้สึกโดดเดี่ยว... :-(


ขอบคุณสำหรับสิ่งนี้! มีประโยชน์มาก!
Ash Clarke

กฎข้อที่สองมีความสำคัญ: คุณต้องตรวจสอบให้แน่ใจว่ามีการกำหนดเส้นทางไปที่app/index.htmlและไม่ app/เรียกหน้าเว็บที่แสดง AngularJS อย่างชัดเจน ฉันเสียชีวิตไป 2 ชั่วโมงก่อนที่ฉันจะค้นพบมัน :-)
Dexter Legaspi

อีกวิธีหนึ่งในการใช้ ASP.NET MVC และเพิ่มไปยัง RouteConfig.cs: route.MapRoute (ชื่อ: "Default", url: "{* any}", ค่าเริ่มต้น: ใหม่ {controller = "Home", action = "Index", }); และดัชนี HomeController ของคุณจะส่งคืนไฟล์ ("~ / index-anyhinghere.html", "text / html"); จากนั้นแอปของคุณจะกลายเป็น IIS อิสระ
Toolkit

ฉันต้องติดตั้ง "โมดูลการเขียน URL ใหม่จาก 'Web Installer'" หาก url rewrite module ไม่ได้อยู่ที่นั่นในขณะที่โหลดใหม่การเขียนใหม่จะไม่ทำงาน ติดตั้งโมดูลเขียน URL ใหม่ :)
Bimal Das

คำตอบ:


289

ผมเขียนออกกฎใน 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อินพุตเนื่องจากบรรทัดที่สาม (เงื่อนไขบรรทัดที่สาม)


2
มันมีประโยชน์มากและฉันคิดว่ามันสมบูรณ์ที่สุด ขอบคุณ!
มาริโอ

2
ดีใจที่มันช่วย @Mario
Yagiz Ozturk

5
ที่สมบูรณ์แบบ! อันนี้เป็นปัญหาที่ยากสำหรับฉันใช้เวลาทำงานหลายชั่วโมง ขอบคุณ! คำแนะนำสำหรับผู้อื่น: ฉันเพิ่ม index.html ไปที่ <action type = "Rewrite" url "/index.html" /> จากนั้นใน index.html ของฉัน (ไฟล์ไดเรกทอรีรากสำหรับ Angular SPA <base href = "/ index .html "/> เมื่อฉันจัดการโค้ดด้านบนมันไม่ตรงกับ <base href /> ของฉันดังนั้นจึงไม่ทำงานอย่างถูกต้องอุปกรณ์ขนาดใหญ่สำหรับรูปแบบ" / (api) "ฉันยังสะดุดในส่วนนั้น
แบรดมาร์ติน

เกิดอะไรขึ้นถ้าฉันโฮสต์บนเว็บไซต์ Azure
ชุดเครื่องมือ

7
มันเป็นเรื่องตลกที่เราจะต้องกระโดดข้ามห่วงเหล่านี้สำหรับการจัดเส้นทางเชิงมุม นี่เป็นการฆ่าเส้นทางเชิงมุมสำหรับฉัน ช่างเป็นระเบียบ
user441521

38

IIS ขาเข้ากฎดังแสดงในคำถามทำงาน ฉันต้องล้างแคชของเบราว์เซอร์และเพิ่มบรรทัดต่อไปนี้ที่ด้านบนของ<head>ส่วนของหน้า index.html:

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

นี่เป็นเพราะฉันมีแอปพลิเคชั่นมากกว่าหนึ่งรายการใน localhost ดังนั้นคำขอไปยัง partials อื่นจึงถูกนำไปlocalhost/app/view1ใช้แทนlocalhost/myApplication/app/view1

หวังว่านี่จะช่วยให้ใครบางคน!


1
ฉันไม่ต้องการสิ่งนี้ แต่การแก้ไขคำถามนั้นยอดเยี่ยม ขอบคุณ!
Ash Clarke

2
นอกจากนี้ยังมีประโยชน์ ทำงานให้ฉันเมื่อโหลดหน้าซ้ำ ไม่มีกฎพิเศษสำหรับทุกไฟล์: coderwall.com/p/mycbiq
ต่อ G

ตามที่ @ ash-clarke กล่าวว่าไม่จำเป็น แต่เป็นวิธีปฏิบัติที่ดีเพราะจะช่วยให้การเชื่อมโยงในหน้านั้นไม่เชื่อเรื่องที่ "ไดเรกทอรีย่อย" เป็นของมัน
Dexter Legaspi

@PerG ฉันพบปัญหาข้างต้น แต่ไม่สามารถโหลดซ้ำได้นี่คือรหัสของฉัน: stackoverflow.com/questions/25644287/iis-url-rewrite-rules ความคิดใด ๆ
amcdnl

ฉันไม่ทราบหรือพยายามกรองบางสาย วิธีรอบ ๆ จะมี API บนโดเมนอื่นเป็นต้น แต่บางทีนี่อาจไม่ใช่ทางออกสำหรับคุณ แต่คุณสามารถถามต่อไปได้ในลิงค์ของฉันด้านบน และบางทีผู้เขียนสามารถตอบคุณได้
ต่อ G

11

ในกรณีของฉันฉันได้รับ 403.14 หลังจากฉันตั้งค่ากฎการเขียนซ้ำที่ถูกต้อง ปรากฎว่าฉันมีไดเรกทอรีที่มีชื่อเดียวกับเส้นทาง URL ของฉัน เมื่อฉันลบกฎการเขียนซ้ำ IsDirectory เส้นทางของฉันทำงานอย่างถูกต้อง มีกรณีที่การลบไดเรกทอรี negation อาจทำให้เกิดปัญหาหรือไม่ ฉันไม่สามารถคิดอะไรในกรณีของฉัน กรณีเดียวที่ฉันนึกถึงคือถ้าคุณสามารถเรียกดูไดเรกทอรีด้วยแอปของคุณ

<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

ปัญหาโดยมีเงื่อนไขสองข้อต่อไปนี้เท่านั้น:

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

คือว่าพวกเขาทำงานเฉพาะตราบใดที่อยู่ทางกายภาพบนดิสก์{REQUEST_FILENAME} ซึ่งหมายความว่าอาจมีสถานการณ์ที่การร้องขอสำหรับมุมมองบางส่วนที่มีชื่อไม่ถูกต้องจะส่งคืนหน้ารูทแทนที่จะเป็น 404 ซึ่งจะทำให้โหลดเชิงมุมสองครั้ง (และในบางสถานการณ์อาจทำให้เกิดการวนซ้ำไม่สิ้นสุด)

ดังนั้นจึงแนะนำให้ใช้กฎ "ทางเลือก" ที่ปลอดภัยเพื่อหลีกเลี่ยงปัญหาเหล่านี้ในการแก้ไขปัญหา:

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

1
ทั้งหมดนี้ทำให้ไซต์ของฉันโหลดได้ดี แต่ถ้าฉันอยู่ที่เส้นทางตามเส้นทางฉันมีปัญหา ดังนั้นหากเส้นทางในเบราว์เซอร์ของฉันคือ: 10.34.34.46/jbvdev/documents/BC498484 ในตอนแรกมันแสดงผลได้ดี แต่ถ้าฉันกดรีเฟรชทุกอย่างจะหยุดพักเพราะมันเริ่มมองหา css และ js ที่10.34.34.46/jbvdev/documents / cssหรือ10.34.34.46/jbvdev/documents/js ไม่มีใครรู้วิธีแก้ปัญหานี้หรือไม่?
Michael Mahony

1

วิธีที่ง่ายที่สุดที่ฉันพบคือเพียงเปลี่ยนเส้นทางคำขอที่ทริกเกอร์ 404 ไปยังไคลเอนต์ สิ่งนี้ทำได้โดยการเพิ่มแฮชแท็กแม้ในขณะที่$locationProvider.html5Mode(true)ตั้งค่าไว้

เคล็ดลับนี้ใช้ได้กับสภาพแวดล้อมที่มี Web Application มากขึ้นในเว็บไซต์เดียวกันและต้องการข้อ จำกัด ของ URL integrity (การรับรองความถูกต้องภายนอก EG) นี่คือวิธีการทำ

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

นี่เป็นวิธีที่ง่ายที่สุด


เป็นไปได้ (แนะนำให้เลือก) เพื่อปรับปรุงฟังก์ชั่นข้อผิดพลาดด้วยตรรกะที่ได้รับการปรับปรุงบางอย่างเพื่อเปลี่ยนเส้นทาง 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 ไปยังไคลเอนต์ก็ต่อเมื่อเริ่มต้นด้วย "/ ใหม่" หรือ "/ แสดง /"

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

นี่เป็นเพียงตัวอย่างของตรรกะที่ปรับปรุงแล้วแน่นอนว่าทุกเว็บแอปพลิเคชันมีความต้องการที่แตกต่างกัน


1

ฉันพยายามปรับใช้แอปพลิเคชัน Angular 7 แบบง่ายไปยัง Azure Web App ทุกอย่างทำงานได้ดีจนกระทั่งถึงจุดที่คุณรีเฟรชหน้า การทำเช่นนั้นทำให้ฉันมีข้อผิดพลาด 500 ครั้ง - เนื้อหาถูกย้าย ฉันได้อ่านทั้งใน Angular docs และในอีกไม่กี่ฟอรัมที่ดีฉันต้องเพิ่มไฟล์ web.config ไปยังโซลูชันที่ปรับใช้ของฉันและตรวจสอบให้แน่ใจว่ากฎการเขียนทับสำรองไปยังไฟล์ index.html หลังจากชั่วโมงแห่งความยุ่งยากและการลองผิดลองถูกและการทดสอบข้อผิดพลาดฉันพบว่าข้อผิดพลาดนั้นค่อนข้างง่าย: เพิ่มแท็กรอบ ๆ มาร์กอัพไฟล์ของฉัน


1

ฉันมีปัญหาที่คล้ายกันกับ Angular และ IIS โดยใช้รหัสสถานะ 404 ในการรีเฟรชด้วยตนเองและลองวิธีแก้ปัญหาที่ได้รับการโหวตมากที่สุด แต่นั่นก็ไม่ได้ผลสำหรับฉัน ลองใช้โซลูชันอื่น ๆ อีกมากมายที่ต้องรับมือกับ WebDAV และเปลี่ยนตัวจัดการและไม่มีใครทำงาน

โชคดีที่ฉันพบโซลูชันนี้และใช้งานได้ (เอาส่วนที่ฉันไม่ต้องการออก) ดังนั้นหากไม่ได้ผลใด ๆ ข้างต้นสำหรับคุณหรือก่อนที่จะลองใช้ให้ลองสิ่งนี้และดูว่าการแก้ไขการปรับใช้เชิงมุมของคุณในปัญหา 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>
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.