今天解決了一位朋友使用 Anthem.NET 遇到的問題。他的代碼在 Windows XP 的開發機器上反應正常,而部署到 2003 Server 的服務器上就提示 "BADRESPONSE".
這個問題產生的緣由是,Anthem 在客戶端 js 中調用服務器時,會返回一個表示 js 對象的文本,在獲得後,經過 eval 方式將這個對象還原。其中包括了服務器須要返回給客戶端的各類信息,好比腳本,更新的 html, ViewState 等。
若是這個 eval 出錯,則會提示 'BADRESPONSE'.
經過查看頁面輸出能夠看到:
JavaScript:
function
Anthem_GetResult(x) {
var
result
=
{
"
value
"
:
null
,
"
error
"
:
null
};
var
responseText
=
x.responseText;
try
{
result
=
eval(
"
(
"
+
responseText
+
"
)
"
);
}
catch
(e) {
if
(responseText.length
==
0
) {
result.error
=
"
NORESPONSE
"
;
}
else
{
result.error
=
"
BADRESPONSE
"
;
result.responseText
=
responseText;
}
}
return
result;
}
如何分析錯誤呢,很明顯,咱們只要看看 responseText 是什麼,就會知道這個文本爲何不能被 eval 估算了。
由於 Anthem_GetResult 是由 Anthem 的 dll 動態輸出的,咱們須要修改這個函數的定義。
方法是在 </body> 前面,加一段代碼來修改這個函數的定義便可:
JavaScript:
function
Anthem_GetResult(x) {
var
result
=
{
"
value
"
:
null
,
"
error
"
:
null
};
var
responseText
=
x.responseText;
alert(responseText);
try
{
result
=
eval(
"
(
"
+
responseText
+
"
)
"
);
}
catch
(e) {
if
(responseText.length
==
0
) {
result.error
=
"
NORESPONSE
"
;
}
else
{
result.error
=
"
BADRESPONSE
"
;
result.responseText
=
responseText;
}
}
return
result;
}
在正常狀況下,alert 提示的信息以下:
---------------------------
Windows Internet Explorer
---------------------------
{
"
value
"
:
null
,
"
error
"
:
null
,
"
viewState
"
:
"
/wEPDwUKMTQ4NzkxOTExMGRkLHCpj5eYh3HaWUC4wwfnI1kE8sI=
"
,
"
eventValidation
"
:
"
/wEWAgKw5r+UAwLM9PumD2DQQ4RF4lRuD5Qz+1A07BOdo0rx
"
,
"
controls
"
:{
"
LinkButton1
"
:
"
<a onclick=\
"
Anthem_FireCallBackEvent(
this
,event,'LinkButton1','',
true
,'','','',
true
,
null
,
null
,
null
,
true
,
true
);
return
false
;\
"
id=\
"
LinkButton1\
"
href=\
"
javascript:__doPostBack('LinkButton1','')\
"
style=\
"
Z
-
INDEX:
101
; LEFT: 416px; POSITION: absolute; TOP: 96px\
"
>Test</a>
"
},
"
script
"
:[
"
window.location = 'http://www.sina.com.cn';
"
]}
---------------------------
肯定
---------------------------
看上去有點亂,咱們把它還原爲正常的 js 代碼,其實是這樣一個對象:
JavaScript:
{
"
value
"
:
null
,
"
error
"
:
null
,
"
viewState
"
:
"
/wEPDwUKMTQ4NzkxOTExMGRkLHCpj5eYh3HaWUC4wwfnI1kE8sI=
"
,
"
eventValidation
"
:
"
/wEWAgKw5r+UAwLM9PumD2DQQ4RF4lRuD5Qz+1A07BOdo0rx
"
,
"
controls
"
: {
"
LinkButton1
"
:
"
<a onclick=\
"
Anthem_FireCallBackEvent(
this
,event,'LinkButton1','',
true
,'','','',
true
,
null
,
null
,
null
,
true
,
true
);
return
false
;\
"
id=\
"
LinkButton1\
"
href=\
"
javascript:__doPostBack('LinkButton1','')\
"
style=\
"
Z
-
INDEX:
101
; LEFT: 416px; POSITION: absolute; TOP: 96px\
"
>Test</a>
"
,
},
"
script
"
: [
"
window.location = 'http://www.sina.com.cn';
"
]
}
其中 controls 是須要更新 innerHTML 的客戶端控件集合,以及要更新的源代碼。
Anthem.NET 修改了常見默認控件的 Render 方法,使控件輸出的 HTML 外圍多了一個容器控件. 而每次回調後,都會經過這我的爲添加的容器來更新其中的控件 HTML 輸出。
看以下 HTML:
HTML:
<span id="Anthem_LinkButton1__"
><
a
id
="LinkButton1"
onclick
="Anthem_FireCallBackEvent(this,event,'LinkButton1','',true,'','','',true,null,null,null,true,true);return false;"
href
="javascript:__doPostBack('LinkButton1','')"
style
="Z-INDEX: 101; LEFT: 416px; POSITION: absolute; TOP: 96px"
>
Test
</
a
></
span>
這段代碼中,span 即是 LinkButton 的容器。
上述返回對象中的 script 屬性,是在服務器端設定的,須要在返回後執行的腳本代碼的集合。
服務器端能夠經過下列語句來添加腳本:
C#:
Anthem.Manager.AddScriptForClientSideEval(
"
window.location = 'http://www.sina.com.cn';
"
);
以上分析的是 Anthem 在正常工做的狀況下輸出的對象,那麼錯誤時會輸出什麼內容呢?下面是一個例子:
---------------------------
Microsoft Internet Explorer
---------------------------
<
html
>
<
head
>
<
title
>
δʵ��÷������/title>
<
style
>
body
{
font-family
:
"Verdana"
;
font-weight
:
normal
;
font-size
:
.7em
;
color
:
black
;
}
p
{
font-family
:
"Verdana"
;
font-weight
:
normal
;
color
:
black
;
margin-top
:
-5px
}
b
{
font-family
:
"Verdana"
;
font-weight
:
bold
;
color
:
black
;
margin-top
:
-5p
咱們看到其中有亂碼信息,能夠判斷 Anthem 是遇到了編碼問題致使輸出錯誤了。
因而從新設定頁面的編碼,解決了這個問題。
分析一下 Anthem 的實現,能夠看到 Anthem 在發送請求時的設定代碼:
JavaScript:
x.open(
"
POST
"
, url
?
url : Anthem_DefaultURL, clientCallBack
?
true
:
false
);
x.setRequestHeader(
"
Content-Type
"
,
"
application/x-www-form-urlencoded; charset=utf-8
"
);
x.setRequestHeader(
"
Accept-Encoding
"
,
"
gzip, deflate
"
);
其默認請求編碼是 utf-8 的。
而其輸出編碼,則能夠經過 web.config 來定製。方法以下:
<
configuration
>
<
system
.web
>
<
appSettings
>
<
add
key
="Anthem.ResponseEncoding"
value
="gb2312"
/>
<
add
key
="Anthem.ResponseType"
value
="gb2312"
/>
</
appSettings
>
</
system.web
>
</
configuration
>
這個辦法是我經過分析 Anthem 的源碼發現的,奇怪的是在其文檔中好像沒有發現相關的說明。
相關代碼以下:
Manager.cs (C#):
private
void
ConfigureResponse(HttpResponse resp) {
string
contentEncoding
=
null
;
string
contentType
=
null
;
#if
V2
contentEncoding
=
WebConfigurationManager.AppSettings[
"
Anthem.ResponseEncoding
"
];
contentType
=
WebConfigurationManager.AppSettings[
"
Anthem.ResponseType
"
];
#else
contentEncoding
=
ConfigurationSettings.AppSettings[
"
Anthem.ResponseEncoding
"
];
contentType
=
ConfigurationSettings.AppSettings[
"
Anthem.ResponseType
"
];
#endif
if
(contentEncoding
!=
null
)
resp.ContentEncoding
=
Encoding.GetEncoding(contentEncoding);
if
(contentType
!=
null
)
resp.ContentType
=
contentType;
resp.Cache.SetCacheability(HttpCacheability.NoCache);
}
小結一下使用 Anthem.NET 碰到腳本問題的查錯方法:
首先定位到 Anthem.NET 產生的某個具體函數,而後,能夠在頁面的 </body> 前插入代碼來改寫該函數,在其中加入調試語句來定位問題。
固然,以上所說的是在部署服務器這種受限的環境下(一般沒有開發環境)排錯的方法,若是可以直接調試頁面的 JavaScript 就更方便了。好比能夠用 Visual Studio, 或者 MSE.exe 等工具來調試。