星期三, 3月 16, 2011

如何指定 IE 瀏覽器的文件模式

        最近 IE9 正式版剛推出, 在推出前的 RC 版很幸運的躲過了我所認為會遇到的問題, 但在後面的版本及正式版還是讓我碰到了我最不想碰到的事 病厭厭, 但幸運的是至少在正式版可以透過文件模式來避掉該問題, 先不管結果如何, 我還是先針對此部分先做了一些準備功課, 發覺看起來容易卻花了我好多好多時間 ...

首先針對 IIS7 可以很方便的在 Web.config 設定即可
<httpProtocol> 
     <customHeaders>
          <clear />
          <add name="X-UA-Compatible" value="IE=EmulateIE7" />
     </customHeaders>
</httpProtocol>

很不幸的, IIS6 僅能針對 IIS 去做標題自訂的動作, 但因為主機數量還挺多的, 用此方法的話若將來主機擴充會有遺漏的可能性, 所以暫不考慮, 後來想說那我在 Global.asax 裡試試看, 上網查了一下人家是建議在 Begin_Request 理加上

Response.AddHeader("X-UA-Compatible", "IE=EmulateIE7")

但不管我怎麼家都沒有反應, 不死心直接在 .aspx 程式裡寫上一段

<% Response.AddHeader("X-UA-Compatible", "IE=EmulateIE7") %>

也是都沒產生我要的 Meta 資訊, ... 這下我可困惑了, 後來反覆測試的結果發現, 若我的 aspx 網頁內都是 <%%> 處理沒有任何的 tag 資訊的話它會正常出現無誤, 若我加上任何一個資訊就不會出現, 我就很好奇這東西影響了哪些人, 發覺不僅是 aspx 有影響, 包含 Global.asax 裡面的處理跟直接設定 IIS 也會有相同的狀況, 我試著在 IIS 中加入一段自訂的 HTTP 標頭, 一樣會跟剛剛的結果一樣。

image

這讓我有點 鬼魂, 後來不死心找到一篇 MSDN 建議的一種做法, 但僅有大概說點原理範例沒給的很清楚也不保證是完全 ok, 我就把它實做出來試試看, 反正官方建議總比民間的小方法好多了吧, 程式法如下, 是在 Global.asax 理處理

Sub Application_PreRequestHandlerExecute(ByVal sender As Object, ByVal e As EventArgs)
    Dim page As Page = Context.Handler
    If Not page Is Nothing Then
        AddHandler page.PreRenderComplete, AddressOf Page_PreRenderComplete
    End If
End Sub

Sub Page_PreRenderComplete(sender As Object, e As System.EventArgs)
    Dim page = Context.Handler
    Dim header = page.Header

    If Not header Is Nothing Then
        Dim headerControls As ControlCollection = Header.Controls
        Dim hasMeta As Boolean = False
        For Each headerControl As Control In headerControls
            If headerControl.GetType.Name = "HtmlMeta" Then
                Dim metaTag As HtmlMeta = headerControl
                metaTag.Attributes("http-equiv") = "X-UA-Compatible"
                metaTag.Attributes("content") = "ID=EmulateIE8"
                hasMeta = True
            End If
        Next

        If Not hasMeta Then
            Dim metaTag As HtmlMeta = New HtmlMeta()
            metaTag.Attributes("http-equiv") = "X-UA-Compatible"
            metaTag.Attributes("content") = "ID=EmulateIE8"
            header.Controls.AddAt(0, metatag)
        End If
    End If
End Sub

因為家裡沒環境可測, 所以是直接遠端到沒有開發環境的主機上用筆記本慢慢刻出來的, 邊跑邊測試還挺麻煩的, 好不容易寫好發現好像可以了耶, 正當準備要去放鞭炮的時候出現了一段黃底紅字 病厭厭

Server Error in '/' Application.
--------------------------------------------------------------------------------

The Controls collection cannot be modified because the control contains code blocks (i.e. <% ... %>).
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.Web.HttpException: The Controls collection cannot be modified because the control contains code blocks (i.e. <% ... %>).

大概的意思應該是說我在 Header 裡面包含了 <%%> 的東西, 殘念 Orz, 此路看來是不通了,  心理想說那我如果用 javascript 去弄咧, 那時已經有點慌了, 開始不管亂踹了, 就用以下程式碼去測

document.write('<meta http-equiv="X-UA-Compatible" content="ID=EmulateIE8" />');

結果當然是此路不通啦, 有點概念的應該都知道這是不可行的, 唉 ... , 看來我還是只能走我的後門了, 本來趁此機會走走看正統大門看有啥好的解決方案, 搞不好將來可以有其它的發揮, 心裡雖然還有個方法 (用 HttpModule 針對輸出的 Head 去加上那段) 但已經搞到半夜四點多了, 我也懶了, 等下次還有精力的時後再來踹踹看好了, 微軟阿微軟你怎麼可以這樣讓我高興一下下就馬上讓我下地獄咧 …

另外補充一點: 後來我機器裝上 IE9 正式版, 發現
<meta http-equiv="X-UA-Compatible" content="ID=EmulateIE8" /> 這個無效, 要改成
<meta http-equiv="X-UA-Compatible" content="IE=8" /> 這樣
但我在公司的環境上面的卻是 ok 的, 兩台機器的差異就是公司 x32 家裡 x64, 不確定是不是這個影響, 等下次碰的時後再來好好研究一下好了。

沒有留言: