客戶有台電腦用IE 7.0,使用我們ASP.NET 1.1的程式時,發現驗証都無法使用。查不出原因,給他上到IE 8.0還是一樣, 昏倒! 真想叫User重裝OS,後來使用IE 8的Debug一步一步找出問題所在....
前言
客戶有台電腦用IE 7.0,使用我們ASP.NET 1.1的程式時,發現驗証都無法使用。查不出原因,給他上到IE 8.0還是一樣, 昏倒! 真想叫User重裝OS..
研究
後來在客戶那直接用IE 8給他Debug下去,發現沒有Page_ClientValidate這個function,檢視原始檔,居然沒有沒有WebUIValidation.js。
- 解法1:
如果它沒有下WebUIValidation.js那就手動加到網頁裡吧!
<script language="javascript" type="text/javascript" src="/aspnet_client/system_web/1_1_4322/WebUIValidation.js"></script>
這時雖然有Page_ClientValidate這個function了,但是會死在這個functoin裡,所以就再改WebUIValidation.js裡的Page_ClientValidate function,以避免JS錯誤!
try{ var i; for (i = 0; i < Page_Validators.length; i++) { ValidatorValidate(Page_Validators[i]); } ValidatorUpdateIsValid(); ValidationSummaryOnSubmit(); }catch(ex){ Page_IsValid = true; } Page_BlockSubmit = !Page_IsValid; return Page_IsValid; }
- 解法2:
解法1的方式雖然讓Client端有了Page_ClientValidate function,但是Client端的驗証還是無效的,因為我們不知要Render出那驗証做為Page_Validators的Array。最好還是要讓ASP.NET可以自動Render而不是手動。
想了一下,可以反組譯System.dll呀! 先找到System.Web.UI.WebControls裡的RequiredFieldValidator,再找到BaseValidator。然後再看BaseValidator的OnPreRender事件中,它是依DetermineRenderUplevel()決定要不要把驗証給Render到Client端。RegisterValidatorCommonScript就是Render那些驗証的函式。
即然發現是DetermineRenderUplevel再看一下裡面在做那些事呢? 原來是去判斷是否允許Script及IE的版本為何。
於是我就寫個程式用那個Client測試一下。
Response.Write("IsNothing(page.Request):" & IsNothing(Page.Request) & "<BR>") Response.Write("EnableClientScript:" & Me.RequiredFieldValidator1.EnableClientScript & "<br>") Response.Write("page.Request.Browser.MSDomVersion.Major:" & Page.Request.Browser.MSDomVersion.Major & "<br>") Response.Write("page.Request.Browser.EcmaScriptVersion.CompareTo(new Version(1, 2)):" & Page.Request.Browser.EcmaScriptVersion.CompareTo(New Version(1, 2)) & "<br>")
結果如下,
IsNothing(page.Request):False
EnableClientScript:True
page.Request.Browser.MSDomVersion.Major:0
page.Request.Browser.EcmaScriptVersion.CompareTo(new Version(1, 2)):-1果然是有問題呀! 連到http://www.cyscape.com/showbrow.aspx?bhcp=1 是可以查的出來的說!
拿IIS Log的中Client的User Agent到http://user-agent-string.info/ Parse也是可以Check的出來說!
後來再依MSDomVersion Keyword到網路上去找,找到了關於browserCaps(在C:\WINDOWS\Microsoft.NET\Framework\v1.1.4322\CONFIG\machine.config),看了該區段的內容,想說用暴力法,如果Asp.NET parse不到的,就一律把它設定成可以符合的版本,這樣起碼Client Validator是可以Work的。
<browserCaps>
<result type="System.Web.Mobile.MobileCapabilities, System.Web.Mobile, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/>
<use var="HTTP_USER_AGENT"/>browser=Unknown
version=0.0
majorversion=0
minorversion=0
frames=false
tables=false
cookies=false
backgroundsounds=false
vbscript=false
javascript=false
javaapplets=false
activexcontrols=false
win16=false
win32=false
beta=false
ak=false
sk=false
aol=false
crawler=false
cdf=false
gold=false
authenticodeupdate=false
tagwriter=System.Web.UI.Html32TextWriter
ecmascriptversion=0.0
msdomversion=0.0
w3cdomversion=0.0
platform=Unknown
css1=false
css2=false
xml=falsemobileDeviceManufacturer = "Unknown"
mobileDeviceModel = "Unknown"gatewayVersion = "None"
gatewayMajorVersion = "0"
gatewayMinorVersion = "0"preferredRenderingType = "html32"
preferredRenderingMime = "text/html"
preferredImageMime = "image/gif"defaultScreenCharactersWidth = "12"
defaultScreenCharactersHeight = "6"
defaultScreenPixelsWidth = "96"
defaultScreenPixelsHeight = "72"
defaultCharacterWidth = "8"
defaultCharacterHeight = "12"
screenBitDepth = "1"
isColor = "false"
inputType = "telephoneKeypad"numberOfSoftkeys = "0"
maximumSoftkeyLabelLength = "5"canInitiateVoiceCall = "false"
把以上browser=Unknown中的上面紅色3行改成以下,這樣就可以了!
ecmascriptversion=1.2
msdomversion=4.0
w3cdomversion=1.0
結論
原本有開問題問MS,後來有解就沒有再問MS為何會如此了。如果其他人有任何想法或解法,煩請回應哦! 謝謝!
呵! 還好是.NET,起碼可以知道要去改那裡! 也還好有IE8.0,可以直接在Client端對Javascript做Debug,才會發現是少了WebUIValidation.js。後來反組譯後才發現是什麼原因導致,但又不知如何去修正Client的電腦,後來找到「Client-Side Validation in Downlevel Browsers」及「A Look at ASP.NET's Adaptive Rendering」才去看machine.config裡的browserCaps內容,也才想到用暴力法去解這個問題。
Hi,
亂馬客Blog已移到了 「亂馬客 : Re:從零開始的軟體開發生活」
請大家繼續支持 ^_^