2011/2/24

[Fix] 在 Chrome/Firefox 開啟 ASP.NET Development server 下網站速度緩慢問題

已經忘了大約有多久的時間,可能是在升級到win7當作開發環境以後,就遇到了使用Chrome/Firefox 來開啟開發中的網站載入網頁速度非常緩慢的問題;開啟或重新整理一個網頁的時間絕對超過10秒鐘以上,加上網頁上載入的javascript檔案非常多,所以之前常常在Debug時直接改用IE來作業,但是如果一遇到Bug是發生在非IE瀏覽器上時,就非常頭痛了。

之前遇到這樣的情況是,使用fiddler來觀察時,發現只要網頁一開,同時載入5個資源(js,css or image)時,browser就會卡住,所以當時朝著加大max connection數量的方向在想,但是由於在趕案子(好吧,我承認這只是一個藉口..現在看來只是一個不要先入為主的認定,再加上花5分鐘google一下就可以解決的事),所以一直沒能解決這件事。

今天因為在開發新的網站,又遇到了一樣的情況;這回真的忍不住了,直覺的打了幾個keyword搜尋一下,沒想到困擾已久的問題就迎刃而解,前後絕對花不到5分鐘..Orz

原來問題出在IPv6的問題造成DNS解析速度緩慢,有以下3種解決方式

  • 修改hots,將localhost指定為127.0.0.1
  • 如果使用Firefox,關掉它的IPv6設定,Chrome的話似乎還沒有解法
  • 關掉系統的IPv6功能


在以不改變系統設定的情況下,我選擇修改hosts來處理掉這件事,相關文章可以參考下列網址:
ASP.NET Development server slow on Windows Vista/7 with Firefox or Chrome
Fixing Firefox Slowness with localhost on Vista (or XP with IPv6)

2011/2/16

[CODE] 解決反序列化時 『__type』 造成的錯誤訊息

這兩天在工作上遇到一個需求,要將原來A網站上用Ajax-Enabled WCF做出來的Ajax查詢ID的功能提供給Server上的B網站使用。本來這樣的需求可以透過直接在B網站上呼叫A網站的WCF服務來達成,但是考慮一旦這樣做下來,後續2個網站將必需放在同一台Server上,且在開發時期得另外架一個網站提供這樣的服務,並不便宜開發及除錯。於是改為在B網站上,直接透過在B網站的查詢字串在Server端以Post方式直接連到A網站的WCF服務來取得資料,而不在Client端完成(不過這樣相對的也有它的成本需要考量,必需自行取捨)。

這樣的方式之前在其他Case也有做過,不過當時A網站並不是直接透過WCF的做法來提供Ajax的查詢,而是自行寫一隻.AXD(Http Handler)的方式來完成。本以為類似的模式只要依樣畫葫蘆就可以完成,但卻在將WCF轉出的JSON Data再轉回B網站程式中的物件時出現了錯誤『System.ArgumentNullException: 值不能為 null。參數名稱: type』,遇到這樣的問題,先查了一下A網站出來的JSON,格式如下:『 {"__type":"SimpleType:#TestTypeResolver", "ID":"00001","Name":"Jacky"}"』,其中SimpleType 為A網站Server轉出來的物件type; 看到這裡,直覺認為是『__type』這個欄位在作崇,於是先從程式Replace掉再試一次看看...!!果不其然,只要拿掉了__type 欄位,錯誤訊息則不再出現。

得到了這樣的線索之後,問題就變得明確多了;拜了一下G大神之後,雖然沒有得到直接的解決方式,但卻找到一個解決問題的關鍵訊息...『JavaScriptTypeResolver 物件 』! 這個物件依名稱大概可以猜出七八成它的意義,主要是 JavaScriptSerializer 在遇到__type 這樣的meta資訊時,如何將物件Type轉成string 存到__type中,以及反解時將__type中的字串轉回type的功能。 有了這樣的訊息以後問題就容易解了,只要在建立 JavaScriptSerializer ,傳入自行實作的 JavaScriptTypeResolver ,就可以避開這樣的問題。

 //訂為private,以免外部程式誤用
 private class SimpleTypeResolver : JavaScriptTypeResolver
        {
            public override Type ResolveType(string id)
            {
                return typeof(SimpleType); //在這個例子中只做SimpleType的轉換,暫不考慮其他物
            }

            public override string ResolveTypeId(Type type)
            {
                throw new NotImplementedException(); //在這個例子中不做Serialize,所以不會被呼叫
            }
        }


public SimpleType Deserialize(string json){
     JavaScriptSerializer serial = new JavaScriptSerializer(new SimpleTypeResolver());
     var myType = serial.DeserializeObject(@"{""__type"":""SimpleType:#TestTypeResolver"",""ID"":""00001"",""Name"":""Jacky""}");
}
結論:
原本在使用 JavaScriptSerializer 並沒有留意到內部是透過 JavaScriptTypeResolver 來做 Reflection 的工作,所以遇到這樣情況時,可能一時無法理解原因為何,只能多花時間再去追可能造成問題的原因,若是在開發上能針對使用的物件多花一點心思,不只懂如何使用它,還要瞭解背後的原理或細節,這樣對於各種問題的狀況應該能夠更快的掌握才是!