透過UIWebView修改UserAgent,解決__doPostBack無法產生的問題
今天下午被同事問到一個很好玩的問題,由於部門撰寫的網頁均是用ASP.NET程式來開發,因此在iPhone閱讀的時候,
有時候會遇到JavaScript沒有被載入或是CSS功能失效的問題。但這樣的問題卻在iPhone 3GS裡不會出現,只會出現在
iPhone 4新的iOS之後,甚至連ASP.NET最需要的__doPostback的javascript都沒有產生至網頁的HTML之中。
這下子好了,沒有了__doPostback的Javascript,很多控件(例如:GridView、LinkButton等集合元件)需要透過javascript
來觸發後端事件的功能均沒有辦法實現。但是也許你會發現,透過Safari瀏覽ASP.NET網頁是不會有問題的,只有在透過實
作的App裡內嵌UIWebView控件後,無法出現__doPostback的事件才會明顯被遇到。
至於這樣的問題要怎麼來解決?究竟是ASP.NET的問題還是iOS在UIWebView的支援度的問題呢?
根據<ASP.NET 4.0 issue with BrowserCap incorrectly detecting UIWebView (Safari) in iOS>這一篇的討論串裡,它的主題是:
「ASP.NET 4.0 has an issue where it incorrectly determines browser capabilities for Safari on iPhone 4.2.1.
ASP.NET determines that this browser does not support javascript and does not include __doPostBack function
to handle postbacks which causes javascript errors. This behavior is incorrect since Safari browser does support javascript.」
是不是很接近所要尋找的問題點呢?根據裡面的討論串可以歸納出問題點:
a. ASP.NET支援的Browser Type(App_Browsers) ;
b. IIS支援的Browser Type (ASP.NET 2.0/ASP.NET4.0);
這二個問題就是整個問題的最重要關鍵,由於App_Browsers支援Browser Type的項目,針對iPhone 4.2.1在UIWebView裡內
鍵送出的User Agent識別程度是相對過去而言是比較低的,也造成ASP.NET或IIS無法識別出是否要產生__doPostback的參數,
甚至連一些必要的隱藏欄位也沒有被產生,如下:
1: //ASP.NET運作事件的必要元素,遇到iOS送出的User Agent卻沒有產生
2: <div class="aspNetHidden">
3: <input type="hidden" name="__EVENTTARGET" id="__EVENTTARGET" value="" />
4: <input type="hidden" name="__EVENTARGUMENT" id="__EVENTARGUMENT" value="" />
5: <input type="hidden" name="__LASTFOCUS" id="__LASTFOCUS" value="" />
6: <input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwUKMTc3NTkxNjQxMmQYAgUeX19Db250cm9sc1JlcXVpcmVQb3N0QmFja0tleV9fFgkFCkNXQmFjayRidG4FE0ltYWdlQnV0dG9uSG9tZSRidG4FIUluQm94TGlzdCRBZHZHcmlkVmlldyRjdGwwMiRjdGwwMQUhSW5Cb3hMaXN0JEFkdkdyaWRWaWV3JGN0bDAzJGN0bDAxBSFJbkJveExpc3QkQWR2R3JpZFZpZXckY3RsMDQkY3RsMDEFIUluQm94TGlzdCRBZHZHcmlkVmlldyRjdGwwNSRjdGwwMQUhSW5Cb3hMaXN0JEFkdkdyaWRWaWV3JGN0bDA2JGN0bDAxBStJbkJveExpc3QkSW5Cb3hMaXN0X0J0bkdyaWRWaWV3UHJldlBhZ2UkYnRuBStJbkJveExpc3QkSW5Cb3hMaXN0X0J0bkdyaWRWaWV3TmV4dFBhZ2UkYnRuBRVJbkJveExpc3QkQWR2R3JpZFZpZXcPPCsADAEIAgFk" />
7: </div>
8:
9: //ASP.NET運作事件的必要元素,遇到iOS送出的User Agent卻沒有產生
10: <script type="text/javascript">
11: //<![CDATA[
12: var theForm = document.forms['form1'];
13: if (!theForm) {
14: theForm = document.form1;
15: }
16: function __doPostBack(eventTarget, eventArgument) {
17: if (!theForm.onsubmit || (theForm.onsubmit() != false)) {
18: theForm.__EVENTTARGET.value = eventTarget;
19: theForm.__EVENTARGUMENT.value = eventArgument;
20: theForm.submit();
21: }
22: }
23: //]]>
24: </script>
了解原由後,那就來看看要怎麼解決這樣的問題吧。
由於User Agent無法識別的原因,那麼就設定一個通用可以支援ASP.NET或IIS識別的User Agent參數。
〉修改UIWebView的User Agent:
由於UIWebView不支援直接修改User Agent,所以改為透過直接覆寫NSMutableURLRequest元件的User-Agent,讓每次UIWebView
都可以使用修改過的User Agent來發送給指定的Web Server取得正確的JavaScript與CSS。
但由於每次都要修改NSMutableURLRequest的User Agent很不方便,透過該<Easily set the User-Agent in a UIWebView | MPHWeb >篇
的介紹,它提供直接在init時就讓UIWebView取得設定,這樣就不需每次都修改啦。
如以下的範例:
1: //設定UserAgent參數,綁定在每次UIWebView的Request中使用
2:
3: NSDictionary *dictionnary = [[NSDictionary alloc] initWithObjectsAndKeys:
4: @"Mozilla/5.0 (iPhone; U; CPU OS 4_2_1 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/4.0 Mobile/8C148 Safari/528.16",
5: @"UserAgent", nil];
6: [[NSUserDefaults standardUserDefaults] registerDefaults:dictionnary];
7: [dictionnary release];
User Agent的參數:
Mozilla/5.0 (iPhone; U; CPU OS 4_2_1 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/4.0 Mobile/8C148 Safari/528.16
======
感謝這個問題的提供者 - 白菜,由它提出了這樣問題的需求,所以才有機會讓我找到解決的方式來解開這樣的問題。
該篇文章是針對他的問題加以整理並且加上他對這方面的建議,說明為何透過iOS裡的UIWebView讀取ASP.NET網頁時,
卻沒有產生__doPostback的問題。希望有所幫助。謝謝。
References:
‧ASP.NET 4.0 issue with BrowserCap incorrectly detecting UIWebView (Safari) in iOS (問題的原由)
‧Programmatically fill in data in a UIWebview
‧Easily set the User-Agent in a UIWebView | MPHWeb (必讀)
‧iPhone/iPad – Get User-Agent for UIWebView
‧Change User Agent in UIWebView (iPhone SDK)