จะตั้งค่าโหมดความเข้ากันได้ของ IE อย่างจริงจังจากฝั่งเซิร์ฟเวอร์ได้อย่างไร


84

ในสภาพแวดล้อมที่ควบคุมด้วยโดเมนฉันพบว่าโหมดความเข้ากันได้ถูกทริกเกอร์บนไคลเอนต์บางตัว (winXP / Win7, IE8 / IE9) แม้ว่าเราจะให้แท็ก X-UA คำจำกัดความของ! DOCTYPE และการตอบสนอง "IE = Edge" ส่วนหัว ไคลเอนต์เหล่านี้มีช่องทำเครื่องหมาย "แสดงไซต์อินทราเน็ตในมุมมองที่เข้ากันได้" ซึ่งเป็นสิ่งที่ฉันพยายามจะลบล้าง

ต่อไปนี้เป็นเอกสารที่ฉันใช้เพื่อทำความเข้าใจว่า IE ตัดสินใจที่จะเรียกใช้โหมดความเข้ากันได้อย่างไร

http://msdn.microsoft.com/en-us/library/ff406036%28v=VS.85%29.aspx

http://blogs.msdn.com/b/ie/archive/2009/02/16/just-the-facts-recap-of-compatibility-view.aspx

เจ้าของเว็บไซต์มีเสมอในการควบคุมของเนื้อหาของพวกเขา เจ้าของไซต์สามารถเลือกที่จะใช้แท็ก X-UA-Compatible เพื่อเป็นการประกาศอย่างชัดเจนเกี่ยวกับวิธีที่พวกเขาต้องการให้ไซต์ของพวกเขาแสดงและแมปเพจโหมดมาตรฐานกับมาตรฐาน IE7 การใช้แท็กที่เข้ากันได้กับ X-UA จะแทนที่มุมมองความเข้ากันได้บนไคลเอนต์

Google สำหรับ"การกำหนดความเข้ากันได้ของเอกสาร"น่าเสียดายที่โปรแกรม SPAM ไม่อนุญาตให้ฉันโพสต์มากกว่า 2 URL

นี่คือASP .NETเว็บแอปและมีคำจำกัดความต่อไปนี้ในหน้าต้นแบบ:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<head>
   <meta http-equiv="X-UA-Compatible" content="IE=Edge" />
</head>

และ web.config

<system.webServer>
  <httpProtocol>
    <customHeaders>
      <clear />
      <add name="X-UA-Compatible" value="IE=Edge" />
    </customHeaders>
  </httpProtocol>
</system.webServer>

ฉันใช้ Fiddler เพื่อตรวจสอบว่าส่วนหัวถูกฉีดอย่างถูกต้องหรือไม่

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

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

มีความคิดและสิ่งที่ฉันอาจจะขาดหายไป? เป็นไปได้หรือไม่ที่จะบังคับให้ IE แสดงผลหน้าเว็บโดยไม่เรียกใช้โหมด Compat?

ขอบคุณล้าน

Jaume

PS:ไซต์กำลังอยู่ในระหว่างการพัฒนาและแน่นอนว่าไม่อยู่ในรายการความเข้ากันได้ของ Microsoft แต่ฉันได้ตรวจสอบในกรณีนี้ด้วย

Google สำหรับ"การทำความเข้าใจรายการมุมมองที่เข้ากันได้"น่าเสียดายที่โปรแกรม SPAM ไม่อนุญาตให้ฉันโพสต์มากกว่า 2 URL

คำตอบ:


45

ฉันพบปัญหากับสองวิธีทั่วไปในการทำสิ่งนี้:

  1. การทำเช่นนี้กับส่วนหัวที่กำหนดเอง ( <customHeaders>) ใน web.config ทำให้การปรับใช้แอปพลิเคชันเดียวกันต่างกันเพื่อให้ชุดนี้แตกต่างกัน ฉันเห็นว่านี่เป็นอีกสิ่งหนึ่งที่อาจผิดพลาดได้ดังนั้นฉันคิดว่าจะดีกว่าถ้าแอปพลิเคชันระบุสิ่งนี้ในรหัส นอกจากนี้IIS6 ไม่สนับสนุนเรื่องนี้

  2. การรวม<meta>แท็กHTML ในหน้าเว็บฟอร์มหลักหรือหน้าเค้าโครง MVC ดูเหมือนจะดีกว่าข้างต้น อย่างไรก็ตามหากบางหน้าไม่ได้รับการสืบทอดจากสิ่งเหล่านี้แท็กจะต้องซ้ำกันดังนั้นจึงมีปัญหาในการบำรุงรักษาและความน่าเชื่อถือ

  3. ปริมาณการใช้งานเครือข่ายสามารถลดลงได้ด้วยการส่งX-UA-Compatibleส่วนหัวไปยังไคลเอนต์ Internet Explorer เท่านั้น

แอปพลิเคชันที่มีโครงสร้างดี

หากแอปพลิเคชันของคุณมีโครงสร้างในลักษณะที่ทำให้ทุกหน้ารับช่วงจากหน้ารูทเดียวในท้ายที่สุดให้รวม<meta>แท็กตามที่แสดงในคำตอบอื่น ๆคำตอบอื่น

แอปพลิเคชันเดิม

ไม่เช่นนั้นฉันคิดว่าวิธีที่ดีที่สุดในการดำเนินการนี้คือเพิ่มส่วนหัว HTTP ในการตอบกลับ HTML ทั้งหมดโดยอัตโนมัติ วิธีหนึ่งที่ทำได้คือใช้IHttpModule:

public class IeCompatibilityModeDisabler : IHttpModule
{
    public void Init(HttpApplication context)
    {
        context.PreSendRequestHeaders += (sender, e) => DisableCompatibilityModeIfApplicable();
    }

    private void DisableCompatibilityModeIfApplicable()
    {
        if (IsIe && IsPage)
            DisableCompatibilityMode();
    }

    private void DisableCompatibilityMode()
    {
        var response = Context.Response;
        response.AddHeader("X-UA-Compatible", "IE=edge");
    }

    private bool IsIe { get { return Context.Request.Browser.IsBrowser("IE"); } }

    private bool IsPage { get { return Context.Handler is Page; } }

    private HttpContext Context { get { return HttpContext.Current; } }

    public void Dispose() { }
}

IE=edge บ่งชี้ว่า IE ควรใช้เอนจิ้นการเรนเดอร์ล่าสุด (แทนที่จะเป็นโหมดความเข้ากันได้) เพื่อแสดงผลเพจ

ดูเหมือนว่าโมดูล HTTP มักจะถูกลงทะเบียนในไฟล์ web.config แต่สิ่งนี้ทำให้เรากลับไปที่ปัญหาแรก อย่างไรก็ตามคุณสามารถลงทะเบียนแบบเป็นโปรแกรมได้ใน Global.asaxดังนี้:

public class Global : HttpApplication
{
    private static IeCompatibilityModeDisabler module;

    void Application_Start(object sender, EventArgs e)
    {
        module = new IeCompatibilityModeDisabler();
    }

    public override void Init()
    {
        base.Init();
        module.Init(this);
    }
}

โปรดทราบว่าโมดูลนั้นเป็นสิ่งสำคัญstaticและไม่ได้สร้างอินสแตนซ์ในInitเพื่อให้มีเพียงหนึ่งอินสแตนซ์ต่อแอปพลิเคชัน แน่นอนว่าในแอปพลิเคชั่นในโลกแห่งความเป็นจริงคอนเทนเนอร์ IoC น่าจะจัดการสิ่งนี้ได้

ข้อดี

  • เอาชนะปัญหาที่ระบุไว้ในตอนต้นของคำตอบนี้

ข้อเสีย

  • ผู้ดูแลเว็บไซต์ไม่สามารถควบคุมค่าส่วนหัวได้ นี่อาจเป็นปัญหาหาก Internet Explorer เวอร์ชันใหม่ออกมาและส่งผลเสียต่อการแสดงผลของเว็บไซต์ อย่างไรก็ตามสิ่งนี้สามารถเอาชนะได้โดยให้โมดูลอ่านค่าส่วนหัวจากไฟล์คอนฟิกูเรชันของแอปพลิเคชันแทนที่จะใช้ค่าแบบฮาร์ดโค้ด
  • อาจต้องมีการปรับเปลี่ยนเพื่อให้ทำงานกับ ASP.NET MVC
  • ใช้ไม่ได้กับหน้า HTML แบบคงที่
  • PreSendRequestHeadersเหตุการณ์ในโค้ดข้างต้นดูเหมือนจะไม่ไฟไหม้ใน IIS6 ฉันยังไม่ทราบวิธีแก้ไขข้อบกพร่องนี้

2
อาจต้องใช้เวลานานกว่าหนึ่งปีกว่าคำตอบของคุณจะปรากฏขึ้นและตอนนี้แอปจริงที่ฉันใช้งานอยู่นั้นได้เลิกใช้งานแล้ว อย่างไรก็ตามนี่เป็นคำตอบที่ละเอียดรอบคอบและได้รับการวิจัยมาเป็นอย่างดีที่ฉันหวังไว้ สิ่งดีๆมาถึงคนที่รอ :) ขอบคุณ Sam
JSancho

1
"สิ่งนี้ควรทำให้มั่นใจได้ว่าหน้าจะแสดงผลอย่างสม่ำเสมอกับเบราว์เซอร์อื่น ๆ และเป็นไปตามมาตรฐาน" ฉันขอโทษ แต่นี่ไม่ใช่ประสบการณ์ของฉันเลยแม้แต่น้อย ตอนนี้ฉันกำลังทำงานกับรายงาน SSRS ที่แสดงผลผิดทั้งหมดใน IE10 ใช้ได้ดีใน Chrome และใช้ได้ดีในโหมดความเข้ากันได้ของ IE10
BobRodes

@BobRodes ฉันคิดว่าฉันเขียนว่าเพราะ IE เวอร์ชันที่ใหม่กว่าควรจะเป็นไปตามมาตรฐานมากกว่า แต่ฉันไม่ได้พูดจากประสบการณ์จริงๆจุดที่ดี! ฉันเพิ่งอัปเดตคำตอบเพื่อลบการอ้างสิทธิ์นั้น
แซม

Microsoft ใช้แนวคิด "โอบกอดขยายดับ" ในความสัมพันธ์กับคู่แข่ง ขั้นแรกยอมรับมาตรฐานทุกประเภท จากนั้นจึง "ปรับปรุง" ตามมาตรฐานด้วยคุณสมบัติและฟังก์ชันที่เป็นกรรมสิทธิ์ จากนั้นจึงยุติการสนับสนุนมาตรฐานในเวอร์ชันอนาคตอย่างเงียบ ๆ โชคดีที่พวกเขาประสบปัญหากับ IE :)
BobRodes

สิ่งนี้ใช้ได้ผลสำหรับฉันและฉันได้ลองใช้วิธีแก้ปัญหาหลายอย่างรวมถึงเมตาแท็กและพยายามใช้ css hacks เพื่ออธิบายพื้นที่ของไซต์ที่ไม่ได้แสดงผลอย่างไม่ถูกต้องเช่น
user609926

39

การเปลี่ยนส่วนหัวของฉันเป็นวิธีต่อไปนี้ช่วยแก้ปัญหา:

<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=Edge" />

ฉันต้องเพิ่มส่วนหัวของลูกค้าลงในไฟล์ web.config เพื่อให้มันทำงานบนเซิร์ฟเวอร์ Windows 2008
Catch22

17

อัปเดต: ข้อมูลที่เป็นประโยชน์เพิ่มเติม<meta http-equiv = "X-UA-Compatible" content = "IE = edge"> ทำอะไร

บางที URL นี้อาจช่วยคุณได้: การเปิดใช้งานโหมดเบราว์เซอร์ด้วย Doctype

แก้ไข: วันนี้เราสามารถแทนที่มุมมองความเข้ากันได้ด้วย: <meta http-equiv="X-UA-Compatible" content="IE=EmulateIE8" />


@Balanivash นั่นเป็นการอ่านที่ดีจริงๆขอบคุณสำหรับลิงค์ บทความนี้ทำให้ฉันเชื่อว่ากำลังเปิดใช้ "โหมดความเข้ากันได้" เนื่องจากไซต์ตั้งอยู่ในโซนอินทราเน็ต อย่างไรก็ตามสิ่งนี้ไม่ได้เกิดขึ้นอย่างสม่ำเสมอตัวอย่างเช่น: - win7, IE8 บนไคลเอนต์ -> โหมดมาตรฐานเต็ม - win7, IE8 บนกล่องอื่นที่มีข้อมูลรับรองเดียวกัน -> โหมดเข้ากันได้เพื่อให้อยู่ในด้านความปลอดภัย I ' นอกจากนี้ยังเริ่มเซสชันใหม่ของเบราว์เซอร์และรีเซ็ตแถบเครื่องมือนักพัฒนา IE เป็นค่าเริ่มต้นในทุกการทดสอบ
JSancho

บางทีคุณอาจลองสิ่งนี้: <meta http-equiv="X-UA-Compatible" content="IE=8" />
Andrew

1
นอกจากนี้: หากคุณต้องการให้เว็บแอปพลิเคชันของคุณบอกให้ IE8 เชื่อใจคุณจริงๆคุณต้องส่ง X-UA-Compatible เป็นส่วนหัว HTTP จากเว็บเซิร์ฟเวอร์ของคุณแทนเมตาแท็ก: social.msdn.microsoft.com/Forums/en- US / iewebdevelopment / thread / …
Andrew

2
จริงๆแล้ววันนี้เราสามารถลบล้างมุมมองความเข้ากันได้ด้วย:<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE8" />
Andrew

2
ขอบคุณสำหรับการอัปเดตคำตอบของคุณ ฉันคิดว่ามันจะดีกว่าถ้าคำตอบของคุณระบุไว้IE=Edgeเนื่องจากคำถามเกี่ยวกับการปิดโหมดความเข้ากันได้
แซม

0

สำหรับนักพัฒนา Node / Express คุณสามารถใช้มิดเดิลแวร์และตั้งค่าผ่านเซิร์ฟเวอร์

app.use(function(req, res, next) {
  res.setHeader('X-UA-Compatible', 'IE=edge');
  next();
});
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.