How to work around the access denied cross-domain frame issue in ASP.NET Ajax 1.0
正好解決了我的問(wèn)題,覺(jué)得作者分析的不錯(cuò),于是以我憋足的英語(yǔ)水平把它翻譯了,希望對(duì)學(xué)習(xí)Asp.Net Ajax的朋友用的上。
譯文如下:
如何解決Asp.Net Ajax 1.0跨域名框架情況下javascript“訪問(wèn)拒絕”的問(wèn)題
???? 一些用戶可能已經(jīng)遇到將Asp.net Ajax程序放在和頂級(jí)窗口域名不一致的Frame或者Iframe中使用的情況。在IE瀏覽器中瀏覽這些網(wǎng)頁(yè)時(shí),任何在框架中觸發(fā)的客戶端DOM事件(比如鼠標(biāo)單擊),IE將拋出“Access denied”(訪問(wèn)拒絕)的異常。造成這種情況的原因是MicrosoftAjax.js中的Sys.UI.getLocation方法。其中有一段棘手的代碼,來(lái)獲取一個(gè)DOM元素相對(duì)于頁(yè)面左上角坐標(biāo)的像素值。所以Body下面的絕對(duì)位置的子元素使用這些坐標(biāo),從而可以準(zhǔn)確的代替你測(cè)量的元素。這個(gè)方法在鼠標(biāo)拖拽,彈出菜單的場(chǎng)景,比如自動(dòng)完成。可以通過(guò)它獲取鼠標(biāo)相對(duì)于觸發(fā)鼠標(biāo)事件元素的坐標(biāo)。由于我們不能動(dòng)態(tài)的根據(jù)瀏覽器的兼容性來(lái)決定不同瀏覽器的各自的行為,一次在Sys.UI.getLocation中的代碼正對(duì)不同瀏覽器做了特定的改寫。你僅僅需要知道,例如某瀏覽器不計(jì)算一個(gè)元素的scroll位置,當(dāng)這個(gè)元素是Body的直接的子元素并且是絕對(duì)位置時(shí)。這就是我們需要解決的一種問(wèn)題。幸運(yùn)的是,IE有兩個(gè)方便的方法讓我們來(lái)完全繞過(guò)一些我們不能有效解決的Bug。
getClientRects
:獲取元素占據(jù)頁(yè)面的所有矩形區(qū)域。
getBoundingClientRect
:返回一個(gè)包含整個(gè)元素的矩形區(qū)域。在我們使用的方法里,我們已經(jīng)使用了
getClientRects
方法,并且獲取到第一個(gè)矩形區(qū)域。因?yàn)槲覀冃枰恢禄煌瑸g覽器間的行為,即使對(duì)于一個(gè)包裝元素Span。這種情況下,元素的左上角就是包含該元素的第一個(gè)矩形區(qū)域的左上角,而不同于包含該元素的全局的矩形區(qū)域。如下圖:
??
???? 這就是我們所犯的錯(cuò)誤,不幸的是已經(jīng)太晚了。
getClientRects
和
getBoundingClientRect
之間僅有一點(diǎn)點(diǎn)區(qū)別。區(qū)別在于,
getClientRects
在框架下使用時(shí),給出的坐標(biāo)包含框架在頂級(jí)窗口中的偏移值(offset 常常元素的offsetLeft offsetTop等屬性來(lái)描述)。然而
getBoundingClientRect
直接給出不包括偏移量的坐標(biāo)。兩個(gè)方法都需要包括計(jì)算Frameborder的高寬才能稱得上完美和準(zhǔn)確。糾正
getClientRects
我們不得不去關(guān)注框架相對(duì)于頂級(jí)窗口的坐標(biāo),并且減去它們,然而這種操作在跨域名的框架下是被禁止的。
??? 解決辦法就是使用 getBoundingClientRect 來(lái)代替 getClientRects ,雖然在使用包裝元素(如span)情況下,這個(gè)辦法將在不同瀏覽器之間帶來(lái)一些不一致,但是總比徹底的失敗要好得多。新版本的函數(shù)依然需要使用try/catch來(lái)修正frameboder的問(wèn)題,所以跨域名框架的情況下,坐標(biāo)可能會(huì)有2個(gè)像素的偏差,但是這已經(jīng)是最好的結(jié)果了。
解決問(wèn)題的步驟
????? 首先,需要用外部的腳本文件來(lái)代替編譯在Dll中基于資源的腳本。 通過(guò)設(shè)置ScriptManager的ScriptPath可以實(shí)現(xiàn)。外部的腳本文件包可以在Microsoft Ajax Library ( http://ajax.asp.net/downloads/library/default.aspx?tabid=47&subtabid=471 )找到,它是基于MSPL,你可以修改其中腳本文件的內(nèi)容。將Microsoft Ajax Library解壓縮后,拷貝文件夾System.Web.Extensions到ScriptPath指定的位置。如果你不希望所有腳本基于路徑被引用,你可以只指定核心腳本文件MicrosoftAjax.js通過(guò)路徑引用,其他的腳本文件繼續(xù)使用Web Resources的方式使用。這樣在使用其他基于資源的庫(kù)時(shí)要容易些,比如使用toolkit的時(shí)候。將下列腳本加入到你的的Script Manager就可以輕松實(shí)現(xiàn):
???? 當(dāng)然,不要忘記將 [Your Script Directory] 替換成為你Web程序中對(duì)應(yīng)的路徑。如果采用這種腳本引用方式,不能在Script Manager中在設(shè)置ScriptPath了。完成上述步驟后,你可以檢查程序是否能繼續(xù)正常工作,并且使用網(wǎng)絡(luò)監(jiān)視工具比如Fidder來(lái)從新的路徑裝載腳本。
???? 第二步就是要修復(fù)原來(lái)腳本中的Bug了 。我們需要修復(fù)腳本的debug版本(MicrosoftAjax.debug.js)和發(fā)布版本。
???? 在MicrosoftAjax.debug.js找到以下代碼片斷
?



??? 并且用下面的代碼替換介于“
case Sys.Browser.Safari:
”之間的所有代碼

























?
對(duì)于發(fā)布版本(
MicrosoftAjax.js
),步驟基本相同,除了文件有點(diǎn)難于操作以外(程序被搞成好長(zhǎng)的幾行,要選中不太容易)。找到代碼片斷
"switch(Sys.Browser.agent){case Sys.Browser.InternetExplorer: ”。并且用下面的代碼替換介于“ case Sys.Browser.Safari: ”之間的所有代碼
switch
(Sys.Browser.agent){
case
?Sys.Browser.InternetExplorer:Sys.UI.DomElement.getLocation
=
function
(a){
if
(a.self
||
a.nodeType
===
9
)
return
?
new
?Sys.UI.Point(
0
,
0
);
var
?b
=
a.getBoundingClientRect();
if
(
!
b)
return
?
new
?Sys.UI.Point(
0
,
0
);
var
?c
=
a.document.documentElement,d
=
b.left
-
2
+
c.scrollLeft,e
=
b.top
-
2
+
c.scrollTop;
try
{
var
?g
=
a.ownerDocument.parentWindow.frameElement
||
null
;
if
(g){
var
?f
=
2
-
(g.frameBorder
||
1
)
*
2
;d
+=
f;e
+=
f}}
catch
(h){}
return
?
new
?Sys.UI.Point(d,e)};
break
;
??? 這個(gè)時(shí)候網(wǎng)站應(yīng)該不會(huì)再拋出異常了
???? 這個(gè)修正帶來(lái)的已知后果
- Sys.UI.DomElement.getLocation方法返回的坐標(biāo),在不同域名框架場(chǎng)景下將偏移2像素
- 這個(gè)修正執(zhí)行結(jié)果返回元素邊界的左上角坐標(biāo),代替了第一個(gè)包含當(dāng)前元素的矩形區(qū)域的左上角,這樣對(duì)于包裝元素(span)是不同的。在不同瀏覽器下返回值也不一致。
??? 重要免責(zé)聲明
???? 這項(xiàng)修正意味著你要停止使用基于資源的腳本,而是用靜態(tài)文件版本代替。我希望這個(gè)問(wèn)題下次服務(wù)包發(fā)布時(shí)得到解決。所以當(dāng)System.Web.Extensions發(fā)布新版本時(shí),你將需要恢復(fù)到使用基于資源的腳本使用方式,從而獲得其他問(wèn)題的修正或者更新。
如何解決Asp.Net Ajax 1.0跨域名框架情況下javascript“訪問(wèn)拒絕”的問(wèn)題[翻譯]
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號(hào)聯(lián)系: 360901061
您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對(duì)您有幫助就好】元
