12/19/2009 11:47:05 PM

[設計案例] 清除Cache物件 #2. Create Custom CacheDependency

543 | C# | CS | Microsoft.NET | MSDN | 小技巧 | 技術隨筆 | 物件導向

上一篇廢話了這麼多,其實重點只有一個,我這次打算利用 CacheDependency 的機制,只要一聲令下,我想移除的 cache item 就會因為 CacheDependency 的關係自動失效,而不用很辛苦的拿著 cache key 一個一個移除。

我的想法是用 tags 的概念,建立起一套靠某個 tag 就能對應到一組 cache item,然後將它移除。開始之前先來想像一下 code 寫好長什麼樣子:

透過 tags 來控制 cache items 的範例程式[copy code]
   1:      static void Main(string[] args)
   2:      {
   3:          string[] urls = new string[] {
   4:              "http://columns.chicken-house.net/",
   5:              // 共 50 組網址... 略
   6:          };
   7:          foreach (string url in urls)
   8:          {
   9:              DownloadData(new Uri(url));
  10:          }
  11:          Console.ReadLine();
  12:          TaggingCacheDependency.DependencyDispose("funp.com");
  13:          Console.ReadLine();
  14:      }
  15:      private static void Info(string key, object value, CacheItemRemovedReason reason)
  16:      {
  17:              Console.WriteLine("Remove: {0}", key);
  18:      }
  19:      private static byte[] DownloadData(Uri sourceURL)
  20:      {
  21:          byte[] buffer = (byte[])HttpRuntime.Cache[sourceURL.ToString()];
  22:          if (buffer == null)
  23:          {
  24:              // 直接到指定網址下載。略...
  25:              buffer = null;
  26:              HttpRuntime.Cache.Add(
  27:                  sourceURL.ToString(),
  28:                  buffer,
  29:                  new TaggingCacheDependency(sourceURL.Host, sourceURL.Scheme),
  30:                  Cache.NoAbsoluteExpiration,
  31:                  TimeSpan.FromSeconds(600),
  32:                  CacheItemPriority.NotRemovable,
  33:                  Info);
  34:          }
  35:          return buffer;
  36:      }
  37:  }

 

 

這段 sample code 做的事很簡單,程式準備了 50 個網址清單,用 for-loop 一個一個下載。下載的 method: DownloadData(Uri sourceURL) 會先檢查 cache 是否已經有資料,沒有才真正下載 (不過下載的細節不是本篇要講的,所以就直接略過了...)。

而主程式的最後一行,則是想要把指定網站 ( funp.com ) 下載的所有資料,都從 cache 移除。為了方便觀看程式結果,我特地加上了 callback method, 當 cache item 被移除時, 會在畫面顯示資訊:

image

由執行結果來看,果然被移出 cache 的都是來在 funp.com 的網址... 接著來看看程式碼中出現的 TaggingCacheDependecny 是怎麼實作的。相關的 code 如下:

TaggingCacheDependency 的實作[copy code]
   1:  public class TaggingCacheDependency : CacheDependency
   2:  {
   3:      private static Dictionary<string, List<TaggingCacheDependency>> _lists = new Dictionary<string, List<TaggingCacheDependency>>();
   4:      public TaggingCacheDependency(params string[] tags)
   5:      {
   6:          foreach (string tag in tags)
   7:          {
   8:              if (_lists.ContainsKey(tag) == false)
   9:              {
  10:                  _lists.Add(tag, new List<TaggingCacheDependency>());
  11:              }
  12:              _lists[tag].Add(this);
  13:          }
  14:          this.SetUtcLastModified(DateTime.MinValue);
  15:          this.FinishInit();
  16:      }
  17:      public static void DependencyDispose(string tag)
  18:      {
  19:          if (_lists.ContainsKey(tag) == true)
  20:          {
  21:              foreach (TaggingCacheDependency tcd in _lists[tag])
  22:              {
  23:                  tcd.NotifyDependencyChanged(null, EventArgs.Empty);
  24:              }
  25:              _lists[tag].Clear();
  26:              _lists.Remove(tag);
  27:          }
  28:      }
  29:  }

 

30行不到... 其實程式很簡單,TaggingCacheDependency 繼承自 CacheDependency, 額外宣告一個靜態的 Dictionary<string, List<TaggingCacheDependency>> 來處理各個標簽及 TaggingCacheDependency 的關係,剩下的就沒什麼了。呼叫 DependencyDispose( ) 就可以通知 .NET Cache 機制,將相關的 cache item 移除。

用法很簡單,當你要把任何物件放進 cache 時,只要用 TaggingCacheDependency 物件來標示它的 tag:

把物件加進 Cache, 配上 TaggingCacheDependency ...[copy code]
   1:  HttpRuntime.Cache.Add(
   2:      sourceURL.ToString(),
   3:      buffer,
   4:      new TaggingCacheDependency(sourceURL.Host, sourceURL.Scheme),
   5:      Cache.NoAbsoluteExpiration,
   6:      TimeSpan.FromSeconds(600),
   7:      CacheItemPriority.NotRemovable,
   8:      Info);

在這個例子裡 (line 4), 直接在 TaggingCacheDependency 物件的 constructor 上直接標上 tags, 在此例是直接把網址的 hostname, scheme 兩個部份當作 tag, 未來就可以依照這兩種資訊直接讓 cache 裡的相關物件失效。

而要下令讓 Cache 內有標上某個 tag 的 cache item 失效,只要這行:

 

將標為 "funp.com" 的 cache item 設為失效的 cache item[copy code]
   1:  TaggingCacheDependency.DependencyDispose("funp.com");

 

結果就會如同上面的程式範例一樣,還留在 cache 的該網址下載資料,在這一瞬間通通都會被清掉...

 

用這種方式,是不是比拿到 key 再去呼叫 Cache.Remove( key ) 的方式簡單多了呢? 同時也能夠更快速的處理複雜的移除機制。其實運用 tagging 的方式只是一例,需要的話你也可以設計合適的 CacheDependency 類別。

以下是本篇文章的兩個附加參考檔案:

Download File - URL清單



12/19/2009 4:29:29 AM

[設計案例] 清除Cache物件 #1. 問題與作法

ASP.NET | C# | CS | Microsoft.NET | MSDN | 小技巧 | 技術隨筆 | 物件導向

每次心裡有什麼好點子想寫出來時,第一關就卡在想不出個好標題... 想來想去的標題,怎麼看就是既不顯眼又不聳動... 果然是個老實的工程師性格 =_= ...  這次要講的,是 .NET HttpRuntime 裡提供的 Cache 物件的操作心得。這個東西我想不用我多作介紹,大家都用到爛掉了吧? 不過好用歸好用,有個老問題其實一直困擾著我很久了...

" 我該怎麼手動的把某個物件從 cache 裡移除? "

老實說,這問題蠻沒水準的... 老叫別人要翻 MSDN,我自己怎麼沒翻? 不不... 容我花點篇幅先說明一下問題。Cache物件,是個典型的 Dictionary 型態的應用 (雖然它沒有 implement interface: IDictionary… ), 透過 key 就可以拿到 cached item. 要從 cache 裡移除某個 item, 簡單的很,只要用 Remove 這個 method, 一行就搞定了:

從 key 移除指定的 cache item[copy code]
   1:  HttpRuntime.Cache.Remove(“cache-key”);

別小看這一行,實作起來障礙還不少。首先,你得額外去記著 cache key 的值。當你要移除的 cache item 有多個的時後,或是移除的 items 之間的關係有點複雜時,這些 code 就不怎麼漂亮了。下一個問題是:

" 我該如何得知所有存在 Cache 內的 keys 有那些? "

這個問題單純的多,那些把 intelligent sense 當購物網站的人 (平常不看文件,只會按下 . 然後挑個順眼 method 來用的人),可能這次就碰壁了... Cache 物件不像一般的 Dictionary 一樣,有提供 Keys 這樣的 property ... 它藏在 GetEnumerator 這 method 內,它會把所有的 keys 給巡一遍,你需要所有的 keys 的話,可以這樣用:

跑過 cache 裡每一個 key[copy code]
   1:  foreach (string key in HttpRuntime.Cache) { 
   2:      // … 
   3:  }

不過這樣的風險也是蠻高的,誰曉得你拿到 key 後的下一秒,這個 cache item 還在不在 cache 內?

 

 

 

--------------------------------------------------------------

本文正式開始! 哈哈,前面那一段只是廢話 + 碎碎唸,現在才是正題。前面想表達的只是,因為 cache 的不確定性 (資料隨時都會被 remove), 操作起來變的要格外小心, 即使它用起來像一般的 Dictionary 一樣。

我舉個案例,來說明我應用 cache 的情況。假如我想實作一個簡單的 web browser, 透過網路下載資源是很慢的動作,每種 browser 都會有某種程度的 cache 機制。我們就拿 Cache 物件替代 IE 的 "temporary internet files” 目錄吧。這時很簡單,只要用 URL 當作 KEY,下載的 content 就當物件塞進去就好...

不過事情沒那麼簡單。如果程式運作了一陣子,我想提供使用者手動清除 "部份" cache 的功能的話,那該怎麼辦? 我舉幾種情況:

  1. 從 cache 裡刪除所有從某個特定網站 (如: columns.chicken-house.net) 下載的資料
  2. 從 cache 裡刪除所有特定類型的資料 (如: content-type 為 image/jpeg 的圖檔)
  3. 從 cache 裡刪除所有透過特定 protocol (如: https) 下載的資料

這樣的要求應該不算過份吧? 用前面提到的兩種作法,你會想哭吧 XD .. 用這些基礎,你大概只能選這幾種作法 (各位網友有好作法也記得提供一下):

  1. 自己另外管理所有下載過的 URL, 用盡各種適合的資料結構,讓你可以順利的挑出這些 match 的 key, 然後移除它。

    缺點: 都作這麼多,你乾脆自己重寫個 cache 機制好了... 何況時間一久,你管理的 key, 那些對應的資料搞不好老早就通通從 cache 裡清掉了...
  2. 聰明一點,用 regular expression … 從 GetEnumerator( ) 一筆一筆過濾出要移除的 URL, 然後清掉它...

    缺點: 這作法只會檢查還留在 cache 內的 URL,不過這樣的 cache 隨便也有成千上萬個,每次都要 looping 掃一次實在不怎麼好看... 有違處女座有潔癖的個性...

 

這些方法 code 寫起來實在不怎麼漂亮,我就不寫 sample code 了,請各位自行想像一下寫起來的樣子。抱歉,如果你用的正好是上面的作法... 那請多包含... :D   這些都是 workable 的作法,但是看起來就是沒什麼設計感;程式可以動,不過就效能、簡潔、可讀性、美感來看,就是覺的不夠精緻 @@。跟朋友討論到這個問題時,我想到一個爛主意...

" 用蠢方法,這些 cache item 先分好類,每一類去關聯一個檔案,設 CacheDependency … 要清掉時去 touch 一下這個檔案,一整組的物件就會自動被清出 cache 了…。”

老實說,我覺的這是個既聰明又愚蠢的作法。聰明的是它很漂亮的解決我要如何移除某一群 item 的問題...,愚蠢的是這種單純程式內可以解決的事,竟然要繞到外面不必要的 file system I/O 動作... 而這通常是最慢的...

 

--

咳,寫太晚,實際的程式碼明天待續...



9/24/2009 2:42:00 AM

[設計案例] 生命遊戲 #5, 中場休息

543 | CS | Microsoft.NET | 技術隨筆 | 物件導向

在繼續下去之前,先來講一下,我希望讓這個 "生命遊戲" 程式,發展到什麼程度吧。其實前面四篇都還只是基礎入門,跟準備動作而已,接下來才開始會有些有趣的。

我希望這系列文章寫完後,這個程式要能扮演一個真正可運作的 Matrix … 沒錯,就是像電影駭客任務裡的母體一樣,這個程式會變成 Matrix 的主要架構,而各式各樣的 "生物" 可以在這個虛擬世界裡生活。為了讓它真的跑的動,所以前幾篇提到的效能問題,執行緒問題,就不能不考慮。為了讓這個虛擬世界能更擬真一點,它至少要是個依時間驅動的模式,而不是像 "生命遊戲" 最早定義的回合制,因此這個問題也要在基本架構裡解決掉。

這些 "生物" 那裡來? 當然是大家來開發 :D 最終目標是要把這 Matrix 建起來,讓各位的生物可以放進來互相較勁一番... 因此先替這些程式 (生物) 抽像化,定義好它跟世界,及跟其它生物之間互動的規格 (就是下篇 "抽像化 / 多型" 要說的) 就是必要的工作之一了。替生命定義好抽像化介面之後,就可以開始衍生出各種不同的生命型態,一起加入這個虛擬世界,因此繼承、多型的技術就派上用場了。

生命是會演化的,當世界上真的演化出一種新的生命型態時,整個世界可以 "安裝" 好新的生命型態,然後全部存檔,重新啟動嗎? 當然不行... 因此如何 "動態" 的加入新的生命型態,如何不停止 GameHost 的前提下,由新的 Assembly 載入 Class (再下篇要說明的 "動態載入"),也是必需克服的技術之一。

這幾個階段及目標,就是我這一系列文章想要做到的。聽起來好像很有趣,可是卻又沒什麼實際的用途... Orz, 沒辦法,我就是喜歡寫這類要動點腦筋的程式,即使畫面一點都不炫也沒關係... 平常工作就不大有機會寫這種程式了,加上現在又只剩一張嘴...。

如果順利的發展,我倒是有個打算,這個 GameHost 成形之後,我打算定些基本的規則,比如土地上會有一定的機率及規則,長出草 (食物) 來。而這世界有各種不同的生物 (EX: 羊),需要靠這世界上的資源維持生命。到時大家可以把自己創造的 "羊" 一起放到這個世界內,看看執行了一陣子之後,誰設計的 "品種" 比較好,最後可以一代一代的繁衍下來...。

想的很美好,不過我不像 darkthread 可以替最後優勝的造物者提供獎品.. Orz.. 未來的設計藍圖就先規劃到這裡。在繼續下去之前,我把程式重新整理了一下,有興趣的人可以下載回去。這份程式碼跟 #4 的功能結構是一樣的,只不過整個架構都作過重整,變數等命名也調整過了,是為了往後說明相關物件技術時,不會被這些從 #1 ~ #4 改的支離破碎的程式碼干擾...

嗯,講了一堆廢話,結論就是: 敬請期待續集 :D  哈哈...

下載重整過的程式碼:



6/21/2008 4:10:22 AM

[BlogEngine.NET] 改造工程 - CS2007 資料匯入

Microsoft.NET | 543 | ASP.NET | BlogEngine.NET | CS | 技術隨筆

自從搬到 BlogEngine.NET 之後,每天晚上都沒閒著,一點一點的慢慢把整個網站改成我要的樣子... 資料庫 / 檔案是我最在意的,當然要優先顧好,光這部份就花了一個多禮拜...

最早找到了 CS2007 --> BlogML --> BlogEngine,大概把我想要的 90% 資料都轉過來了,不過看到那 10% 的資訊沒過來,心裡就很不是滋味...

 

"這是我要一直保留下來的資料耶,現在沒把資料補回來,以後就永遠補不回來了..."

 

就是心裡一直這樣想,所以... 重匯吧! 不然以後後悔也是補不回來的。首先當然是想先從 BlogEngine 匯入 BlogML 的工具下手,看了一下,沒提供 Source Code ? 再看一下,一篇文章一個 Web Service Call,一則回應也是一個 Web Service Call ... 感覺起來有點沒效率,不過不管了,我內容也不多 (兩百多篇文章) ... 既然有 Web Services,先看看它的 WSDL ...

 

image
http://columns.chicken-house.net/api/blogImporter.asmx

 

沒幾個 WebMethod 嘛,不過看一看它的 Interface 就已經漏掉很多資訊沒轉進來了 (像是我要的原 CS PostID,事後作新舊網址對照表用,還有 PageViewCount... etc),要改原程式也是個大工程,不但 CLIENT 要改,WEB METHOD 也要擴充... 我又不是非得遠端用 WEB SERVICES 執行匯入不可,就當下決定另外寫一個匯入程式還比較快...。重寫的話就得研究它的寫法,正好每個 WebMethod 都只作單一的動作,裡面的實作就是現成的範例... 省了不少熟悉 API 的時間 :P

 

事後證明這作法沒錯,BlogEngine 的 LIB 蠻簡單易懂的,另外寫真的比較快... 就一切以原 .ASMX 的程式碼為藍本,寫了一個 .ASHX ,不作什麼事,就是把事先放在 ~/App_Data 下的 BLOGML 讀進來,一篇一篇 POST 處理,一個一個回應處理... 兩層迴圈就搞定原本那 90% 的匯入作業...

 

接下來就是自訂的部份了。先來列一下那些是我要補的資訊:

  1. 每篇 POST 的 COUNTER
  2. 每則回應的詳細資訊
  3. 每篇 POST 的 ID ( CS2007 內的 ID ),及匯入後的新 ID
  4. 所有必要的網址修正 (圖檔,站內文章連結..)
  5. 原程式的一些缺陷修正 (如前文提到,Modified Date錯誤的問題)

 

源頭就有東西要補了。如果一切基於 BlogML 的話,BlogML 沒定義到的資料就沒機會撈出來了。看了一下我還需要額外抓出來的資訊,像匿名的 COMMENTS 作者資訊,IP 等... 不過這些都用某種序列化的方式存在 CSDB,ㄨ!! 真麻煩... 在 CS2007 DB 內的 [cs_posts] 有這兩個欄位: PropertyNames, PropertyValues... 沒錯,全部壓成一個大字串,得自己寫程式去 PARSE ...

CS2007 的作法是這樣,在 PropertyNames 欄位放的值長的像這樣 (包含 Name, 型別, 字串起始及結束位置):

SubmittedUserName:S:0:3:TitleUrl:S:3:35:

 

而在 PropertyValues 對應的值為:

小熊子http://michadel.dyndns.org/netblog/

 

拆起來有點小麻煩,PropertyNames 是 {Name}:{Type}:{StartPos}:{EndPos}: 的組合,有多組的話就一直重複下去。以 Comments 的 SubmittedUserName 來說,它的型別是 S ( String ),它的值就要從後面的 PropertyValues 整個字串的第 0 個字元 ~ 第 3 個字元之間的值 ( 小熊子 ),而 TitleUrl 則是第 3 個字元 ~ 第 35 個字元的值 ( http://michadel.dyndns.org/netblog/ ) ...

看來用 T-SQL 拆或是用 XPath / XSLT 拆都有點辛苦,想想算了... 這段 CODE 跑不掉一定要寫... 就硬解出來吧。解出來後就可以修正 CS2007 匿名張貼的 Comment 沒正確顯示在 BlogML 內的問題。

接下來要把 SQL 這堆資料倒成 XML 檔,偷吃步一下,找工具直接倒出來就好。反正只作一次,可以不要寫 CODE 就不要寫了... SQL2005 要把 QUERY 結果存成 XML 倒是很簡單,打開 SQL2005 Management Studio, 執行這段 QUERY:

取得所有 comments 的額外 PropertyValues 的查詢指令[copy code]
   1:  select 
   2:    PostID, 
   3:    PostAuthor, 
   4:    PropertyNames, 
   5:    PropertyValues 
   6:  from cs_posts 
   7:  where ApplicationPostType = 4 
   8:  for xml auto


 

會看到這樣的畫面:

image

 

點下去就是 XML 了,手到加上頭尾的 Root Element 存檔就搞定了。接下來補段 CODE 把我要的 Property 拆出來存 XML 檔,第一步驟收工!

接下來這堆問題就以 (4) 最麻煩了。原本想的很天真,用文字編輯器把所有 XML 檔替換掉就沒事... 錯! 先從最單純的圖檔路逕來看吧..

 

[替換圖檔及下載檔案的網址]

最基本的就是圖檔網址... 在 CS2007 裡圖檔是這樣放的 (WLW會幫你補上絕對路逕,不是用相對路逕)

http://columns.chicken-house.net/blogs/chicken/xxxxxxx/xxx.jpg

而看了 BlogEngine 的作法,它用 HttpHandler 的方式來提供前端下載圖檔,格式像這樣:

http://columns.chicken-house.net/xxxxx/image.axd?picture=xxx.jpg

而 BlogEngine 的設定檔是這樣寫的:

 

BlogEngine 在 Web.config 內的 HttpHandler 區段[copy code]
   1:  <httpHandlers>
   2:    <add  verb="*" 
   3:      path="file.axd" 
   4:      type="BlogEngine.Core.Web.HttpHandlers.FileHandler, BlogEngine.Core" 
   5:      validate="false"/>
   6:    <add  verb="*" 
   7:      path="image.axd" 
   8:      type="BlogEngine.Core.Web.HttpHandlers.ImageHandler, 
   9:      BlogEngine.Core" 
  10:      validate="false"/>
  11:    .....
  12:  </httpHandlers>

 

看起來不難,理論上我只要找到原網址,把 ~/blog/chicken/ 後的路逕切出來,前段改成 image.axd?picthre= 就可以了。

大致上是這樣沒錯,不過變數還不少... 因為有好幾種網址 @_@

  1. 分家前  ( http://community.chicken-house.net/blogs/chicken/xxxxx )
  2. 分家後  ( http://columns.chicken-house.net/blogs/chicken/xxxxx )
  3. 古早時代手工打的 ( /blogs/chicken/xxxxx )
  4. 有些內建的要避開,像 ( http://columns.chicken-house.net/blogs/chicken/rss.aspx )

代換要嘛一次做完,要嘛一定要照 1 2 3 順序,否則先做 (3) 就會把 (1) (2) 都破壞掉了... 但是怎麼想程式都很不乾脆,雜七雜八的 CODE 一堆... 最後搬出  http://regexlib.com/ 這個網站,它提供大量的 Regular Expression 的資料庫供你使用,也提供了線上版本讓你測試 MATCH 的結果,很好用! 一定要推一下...

最後定案的 Regular Expression 長這樣:

(http\://(columns|community)\.chicken\-house\.net)?/blogs/chicken/([a-zA-Z0-9\-_\./%]*)

一切都很順利,簡單的就精確的抓到要代換的範圍。補一下小插曲,最後轉完才發現漏掉 (4),不過沒幾篇,就手動改掉了 :P,所以這段 REGEXP 是沒處理到 (4) 這種情況的...

 

 

[站內連結的修正]

再來就開始麻煩了... 動手前我先想了一下,每篇文章要匯進去後才會知道它的新 ID,新網址... 在還不知道新網址之前有些內容的聯結就無法替換了,怎麼樣都不可能在 1 PASS 內解決這問題... 只能用 2 PASS 來處理了。

既然這樣,第一次匯入就不修站內聯結了,只要把新舊 ID 記下來就好...

頭痛的來了,CS2007 的網址格式有好幾種 @_@ (難怪它有專門一個 config 檔來設定幾十個 URL Rewrite 的設定...):

  1. /blogs/chicken/archive/2008/06/20/1234.aspx
  2. /blogs/chicken/archive/2008/06/20/MyPostTitleHash.aspx
  3. /blogs/1234.aspx

其中 1234 是 CS2007 內部使用的 PostID .  再看看 BlogEngine 的網址格式:

  1. /post.aspx?id=xxxx-xxxx-xxxxxx-xxxxxxxxxxx
  2. /post/xxxxxxxxxxxxxxxx.aspx (某種 TITLE 的 HASH,它稱作 SLUG)

還好 BlogEngine 單純多了,只要抓到 (1) 的 ID,SLUG 就有 API 抓的到...

記得 CS 網址還有不需要 URL Rewrite 的版本 ( /blogs/xxxxx.aspx?postID=1234 這樣),不過從來沒出現在我文章內容,就不理它了...

這裡的重點不是單純的代換了,還要精確的抓出 1234 這段 PostID .. 最後定案的 Regular Expression 長這樣:

(http\://(columns|community)\.chicken\-house\.net)?/blogs/chicken/archive/\d+/\d+/\d+/(\d+)\.aspx

果然人家說 Regular Expression 是 "WRITE ONLY LANGUAGE" 真有道理,寫完連我自己都看不懂這堆符號是在幹嘛... 最後新舊 ID 都抓到就可以產生出正確的新站內連結了..

 

 

[站外連結修正]

我自己的 LINK 找到就可以修,不過寫在別人那邊的我那修的到啊... 因此就要靠上一篇講的,想辦法要去接有人點到舊的 CS LINK,然後當場做轉址的動作...

好在舊的文章不會再變多了,靠前面做出來的對照表就有足夠的資訊了... 成果看上一篇就知道了。這裡主要是靠 CSUrlMap.cs 這個我自己寫的 HttpHandler 來解決所有連到 /blogs/*.aspx 的連結...

方法差不多,我得從各種可能的網址格式,抓出舊的 CS PostID,然後查表,找出新的網址,把使用者引導到新的頁面... 貼一下主程式的部份:

CSUrlMap, 將 CS2007 的網址重新導向到 BlogEngine 網址的 HttpHandler[copy code]
   1:  public void ProcessRequest(HttpContext context)
   2:  {
   3:      if (matchRss.IsMatch(context.Request.Path) == true)
   4:      {
   5:          //  redir to RSS
   6:          context.Response.ContentType = "text/xml";
   7:          context.Response.TransmitFile("~/blogs/rss.xml");
   8:      }
   9:      else if (matchPostID.IsMatch(context.Request.Path) == true)
  10:      {
  11:          //  redir to post URL
  12:          Match result = matchPostID.Match(context.Request.Path);
  13:          if (result != null && result.Groups.Count > 0)
  14:          {
  15:              string csPostID = result.Groups[result.Groups.Count - 1].Value;
  16:              if (this.MAP.postIDs.ContainsKey(csPostID) == true)
  17:              {
  18:                  context.Items["postID"] = this.MAP.postIDs[csPostID];
  19:                  context.Items["redirDesc"] = "網站系統更新,原文章已經搬移到新的網址。";
  20:              }
  21:              else
  22:              {
  23:                  context.Items["redirDesc"] = "查無此文章代碼,文章不存在或是已被刪除。將返回網站首頁。";
  24:              }
  25:          }
  26:          else
  27:          {
  28:              context.Items["redirDesc"] = "4444";
  29:          }
  30:      }
  31:      else if (matchPostURL.IsMatch(context.Request.Path) == true)
  32:      {
  33:          context.Items["postID"] = this.MAP.postURLs[context.Request.Path];
  34:          context.Items["redirDesc"] = "網站系統更新,原文章已經搬移到新的網址。";
  35:      }
  36:      else
  37:      {
  38:          context.Items["redirDesc"] = "查無此頁。將返回網站首頁。";
  39:      }
  40:      context.Server.Transfer("~/blogs/AutoRedirFromCsUrl.aspx");
  41:  }

 

看程式說故事,大家都會吧 :D,結果就是上一篇各位看到的樣子... 已經沒力一行一行再說明下去了 :P

 

寫到這邊真是大工程 @_@,動作都不困難,但是都是雜七雜八的工作,害我搞了一個禮拜... 不過到此為止搬家要處理的資料部份全部都完成了。下一篇就輕鬆多了,把網站的版面調整成我想要的樣式... 有興趣的人請多等一等吧 :D 主題會放在跟 FunP 推推王的密切整合上... 敬請期待 :D



6/19/2008 3:26:00 AM

從 CommunityServer 2007 到 BlogEngine.NET

Microsoft.NET | 543 | BlogEngine.NET | CS

哈,不是我要搬家了,是網站搬家... 搬家是想了很久沒錯,只是決定搬到 BlogEngine.Net 倒是沒花幾天的時間,所以準備動作也是有點 LiLiLaLa .. 從 CommunityServer 這種成熟的系統搬到還很年輕的 BlogEngine.Net,其實碰到不少小麻煩,在這裡記錄一下給需要的人參考,也算功德一件!

 

要搬 BLOG,最直覺的就是用 BlogML 了,不錯,我用的 CommunityServer2007 有工具可以匯出 BlogML,而 BlogEngine.Net 也有工具可以匯入 BlogML,想想真是太好了... 就先用 DevWeb 架了 BlogEngine.Net 起來試搬看看..

 

 

image

BlogEngine.Net 匯入的方式,是用 ClickOnce,直接從它的官方網站下載的 WinForm App 配合 BlogEngine.Net 本身提供的 Web Service 來進行匯入 BlogML 的動作,除了 BLOGML 之外也支援 RSS? 不過 RSS 怎麼試都試不出來,放棄... 直接用 BlogML ...

 

image

畫面很乾淨,它也很忠實的完成了它的工作... CommunityServer2007 的 BLOGML 匯入時出了點問題,文章的修改時間不知為何,BlogEngine.Net 都一直抓到 0000/01/01 00:00:00.000 ,而BlogEngine.Net 還會幫你修正時區的問題 (台灣時區,要 -8 小時才是標準時間),結果一扣就變成負的,就送我一個 Exception ... Orz

 

匯入的第一步就得動用到 Visual Studio 2008,真不是好兆頭... 所性拿掉那行程式,就一切沒問題了,順利匯入! 架了台測試網站,研究了一兩天,實在是有點不滿意...

  1. LINK 不對
    Windows Live Writer 很好心的幫你把上傳的圖檔都用絕對網址來表示,因此所有的圖都連回原本的網站,正常顯示沒有問題。不過搬家那有這樣搬的... 改!!!
  2. 只搬了BLOG,文章沒有搬
    只怪當時年輕,無聊去用 article 的功能,造成部份是 BLOG 文章,部份是 ARTICLE。CommunityServer2007是都有忠實的匯到 BLOGML,不過 BlogEngine.Net 的匯入工具略過它了... 改!!!
  3. 站內 LINK 不對
    圖檔 LINK 還好修,字串換一換就搞定,不過站内的文章戶連才是個問題... 改!!!
  4. 站外 LINK 不對
    其實這一點是搬完家才發現的,剛搬好 PAGE VIEW 低的可憐... 看一看 LOG 都是 404 Page Not Found ... 改!!!
  5. 沒有 COUNTER
    BlogEngine.Net 說實在話,以BLOG來說功能一點都不缺,不過很怪,竟然沒有最基本的 VIEW COUNT ? 所幸 BlogEngine.Net 有定好 Extension 的架構,要寫它的擴充程式很簡單,有個高手寫了 BlogEngine.Net 的 View Count Extension... 畫面不怎麼樣,不過很實用... 裝!!!
  6. 原有的 VIEW COUNT 沒匯入
    廢話,BlogEngine.Net 本來就沒內建 VIEW COUNT,那是我自己裝了擴充程式才有... 資料要匯,當然也只能自己想辦法 :~~ 改!!!
  7. 版面問題
    標準的版面我很喜歡,就是我要的那種素素的 STYLE,很標準的 ASP.NET Master / UserControl 架構,太棒了... 我要求的也不多,就放放廣告 (看廣告收益很有意思耶,好像電動裡打怪會賺錢或是經驗值那樣... 真的賺多少其實也不重要 :D),還有幾個我自己寫的 CONTROL ... 改!!!
  8. 我在CommunityServer加的功能
    沒辦法,自作孽,改了一堆只能自己搬... 有好幾個:
    • Google Ads (可以用)
    • FunP 推推王 (沒在用了)
    • Recent Comments (已經有內建,可以扔了)
    • 皮哥芸妹年齡 (跟太座的網站分家了,我這邊就不需要了)
    • Bot Check (還沒搞定要怎麼改 :~)
    • Code Formatter 在 BLOG SERVER 要配合的部份

 

 

上面這幾點,都是搬家時或多或少會碰到的小問題,不過很想哭的是,這六個最後都是搬出 Visual Studio 2008 出來才搞定的 @_@,什麼意思? 就是自己寫 CODE 來修啦... 真不知道該誇還是該罵,也因為這樣有機會 Trace 幾次它的 Code,忍不住想再誇它一次,要建起開發環境實在太容易了 [H] 哈哈...  它的 CODE 很精實,CODE 不多,架構很好,規規舉舉的很容易懂,這種 CODE 改起來真舒服.. (為什麼公司的 CODE 都沒有像這種的...),修改的難度大概只有 CommunityServer 的 1/3 .. (CommunityServer的作者很猛,把 M$ 在 2.0 才推出的那套架構在 1.1 時代就都實做了一套 [Y])

 

現在還有空在這裡慢慢打,當然是這些問題都解決完了,先看看成果吧,細節有空再補 HOWTO 文章。那些 LINK 不對的問題,各位翻翻舊文章,如果都看的到圖點的到東西,就是沒問題了。有問題的請再留話給我,我來修看看。

 

 

image

來看看加上 Google Ads 的版面,老實說這個版跟 Google Ads 還真搭... 看起來就像同一套的.. 我只調了 CSS ,跟 MASTER PAGE..

 

image

再來是站內文章互連的 LINK。這邊讓我傷了幾秒鐘的腦筋... 就放棄原本只想寫寫批次檔代換的念頭了。轉檔前跟本不知道轉檔後的新 LINK 是長什麼樣子,轉檔後就錯失先改好 BLOGML 再匯入的機會了... 想了一下,無解,一定要動用到 2 PASS 才行... 就乖乖的改轉檔程式了。第一輪就是基本的匯入,然後在原本的 BLOGML 附記新的 LINK 及 BlogEngine.Net 的 PostID,然後 PASS 2 再把舊文章逐一翻出來 SEARCH & REPLACE ... 上圖可以看到,內文 [四核 CPU] 的 LINK (在底下) 就已經是修正過的了,各位可以去試看看...

 

再來是站外的 LINK,站內我自己的可以改,站外可沒辦法... 拿最捧我場的 Darkthread 網站為例,搜尋一下就有七八篇是連到我這邊,怎麼可以辜負大人的好意... 動搖國本也要改! 現在我的 BlogEngine.Net 已經可以接受舊系統的網址了,而且會正確的轉到同一篇文章的新網址。不過為了不讓大家 "不知不覺" 就轉過來,我特地加了一頁提示,因為書上教的,不要把錯誤隱藏起來 :D,你可以用防禦性的方式寫 CODE,但是務必加上 ASSERT 及 TRACE 提醒自己這裡要注意... (出自一本古董書: Writing Solid Code... 太古董了實在找不到 LINK ... )

 

 

image 

就挑這篇來示範吧,黑暗大哥的文章裡有個 LINK,存的是舊的 CommunityServer 格式 URL,點下去之後會跳到我的網站...

 

 

image

倒數完或是你沒耐性直接按下去的話,就會跳到這篇文章... BINGO,原本的內容出現了!

 

 

image

 

 

嗯,總算修正回來了。其實修正網址是搬家最頭痛的問題了,這個搞定其它都好說 :D  留給有興趣想從 CommunityServer 搬家到 BlogEngine.Net 的人參考...

(小熊子別再撐了... 還有那個誰也是一樣...)



6/17/2008 2:01:24 AM

換到 BlogEngine.Net 了!

Microsoft.NET | BlogEngine.NET | CS | 技術隨筆

也許有人只是覺的換版面而以... 原本是打算升級到 CommunityServer 2008 的,不過自從 Community Server 商業化之後,個人版限制越來越多,整套系統也越來越大,常常出了一些問題都沒辦法自己解決 (連 Error Message 都藏的很隱密 -_-)...

 

其實上面這些也不算缺點,不然我也不會一路從 .Text 時代就用到現在,一用就用了四年多... 上禮拜無意間聽同時講到 BlogEngine.Net,一時好奇抓下來看看,馬上就被它的簡易安裝嚇到了.. 有多簡單? 步驟如下:

  1. 下載
  2. 解開
  3. 設定 IIS 虛擬目錄 / 用 DEV WEB 執行它
  4. 完成了

我已經很努力的把它寫複雜一點了... 它安裝就是這麼簡單,因為它可以不需要 DB (用一堆 XML 檔取代),因此一行 web.config 都不用改就可以用了... 驚喜之餘,也吸引我更深入的多試了幾個功能...

 

基本功能試過一次之後,發現它比 CS 還符合我的須要,怎麼說?

  1. 很簡單
    不只是設定簡單,它的功能也很專一,就是一套BLOG而以。沒有複雜的會員機制,也沒有帳號申請,也沒有多套BLOG管理 (不過它支援多個作者),除了 BLOG 也沒有其它功能... 不多不少,正好我要的都有!
  2. Open Source
    雖然 CS 也有 Source Code 可以看,不過它的原始碼越來越難找了... 每次逛它的網站都要找半天才找的到 SDK 在那裡下載...
  3. 不需要 DB
    雖然我自己 HOSTING 我的網站,DB並不是什麼大問題。不過不需要 DB 對我也是個大利多。一方面網站備份更容易,另一方面除錯及改程式也更容易... 更好用的是,未來我可以把整個網站目錄燒到 DVD 上 (不過兩百多篇文章,不到100MB,燒什麼 DVD...),只要再搭配 .NET 附的 DevWebServer,做個 AutoRun ... 想到可以幹嘛了嗎? 我的 BLOG 馬上就變成一份可以放在 CD,需要時就可以就地用 BROWSER 來看內容了!
  4. CODE 精簡,程式碼架構佳
    這點又免不了跟 CS 拿來比較一下... CS 的作者也是高手,CODE寫的很漂亮,不過跟 BE 最大的差別是,CS實在太肥了。肥到什麼功能都要繞個兩三圈... 要修改雖然不難,但是都要花點時間...
  5. 免費! 免費!
    心理作用,其實賣錢的 CS 送的免費版本,功能比完整的 BlogEngine.NET 還多... 不過商業化之後難免會有些功能得付費才能使用... Orz
  6. 小巧,易用,速度快
    CS 即使是在 LOCAL 執行,速度都沒辦法讓人覺的 "飛快",但是換了 BlogEngine.Net 就有這種感覺... 我目前的文章只有兩百多篇,不靠 DB 的速度都還很快。我試過灌了1000篇文章,速度依然很快... 我想這樣就夠了,我要寫到破千篇,不知道還要多久?

光是這幾個優點,就讓我決定試用只有一天的 BlogEngine.NET 換掉用了四年的 CS ... 剩下的問題只有 "怎麼轉" ? 各位看到現在都成功搬過來,那一定是搞定了... 哈哈... 沒錯,周末花了兩個晚上研究 + 寫匯入程式,今天就重新開張了 :D

轉檔的過程,改天再寫另一篇,有興趣的朋友請耐心等待續集...



11/12/2007 1:43:00 AM

網站升級: CommunityServer 2007.1

543 | CS | 水電工 | 技術隨筆

周日下午趁小孩都回外婆家, 花了點時間把家裡該裝的裝一裝, 該接的接一接, 還有一點空檔, 就把拖了很久的網站升級處理一下... 原本的版本是 CS 2007 (3.0), 中間推出了 3.0 SP1, SP2, SP3 beta 都跳過去沒理它, 這次 2007.1 (3.1) 出來手又癢了起來...

過程就沒啥好說了, 失敗了好幾次, 最後決定整個重裝... 抓了 2007.1 的官方版本, 把舊的 db 配上它的 upgrade script 執行完後掛上去, 基本功能就會動了, 最後再把 ~/blogs, ~/photos, ~/forums 等有 storage 的目錄搬過去, 再把我自己客制過的 themes 重改一次 ( my god, themes 裡的檔案全都調過, 原本的 themes 蓋過來可以跑, 不過心裡毛毛的 )... 總算大功告成. 事後順手也把同一台 server 另外兩套 CS 也順便升級了一下.

老實說我也沒很注意 2007.1 到底改了啥, 就貼一下吧, 搞不好大家之前碰到的鳥問題已經被解決掉了... 正好鴕鳥混過去, 哈哈 [H]

以下是 CS2007.1 release notes:

Below are changes available in Community Server 2007.1
-------------------------------------------------------------------

Enhancements
- Updated caching framework, performance updates, added locking support for several of the application-wide collections
- SQL performance updates and best-practices updates
- Added CreateEditWeblogPostForm, DeleteWeblogPostForm, and associated sub-form controls from CS2008 to support creating/editing/deleting blog posts in the front UI using Chameleon.
- Updated styles on the TinyMCE wrapper's content to provide some default spacing and use a larger default font size.
- Updated TagCloud controls to support disabling the "no tags" message and "no related tags" messages.  Updated all existing themes (except for tag browsing pages) to not render the "no tags" message.
- Updated SqlProviders to resolve LINQ SortOrder namespace ambiguity
- Added support for sorting and paging LinkCategory and Link objects in the API and via Chameleon.
- Added toggle button for enabling/disable application tokens
- Tweaked app tokens list a little bit to show the time for the last used column
- Added a new AdPlacementOptions to WrappedRepeater, AlternatingSeperator - places an ad after every other item starting after the first.
- Updated TinyMCE to use the latest wrapper.
- Updated the email job only retrieves as many messages as it will send from the email queue (prevent large queues from causing timeouts)
- Updated notifications and mass emails to enforce the check on a user's "Enable Email" global setting and "Allow Site to contact me" setting
- Updated email notifications to check the enable thread tracking for post replies
- Updated mass emailing to take place on a background thread
- Updated Telligent.Registration.dll to address an issue where the add-ons could get stuck if they start before SQL on a reboot/startup
- Updated Telligent.MailGateway.Common.dll to address issues with XML cleaning in the core library and downloading only as many messages as needed from the email queue
- Updated user date formats so that month-day-year is 6-1-2007 instead of 06-01-2007
- Updated Windows Live Writer support by implementing keywords for custom tags and removing excerpt support since it gets confused with text-mode.
- The error messages were updated so that the actual error message is displayed more prominently.
- Removed the AutoDeleteThreshold setting from the forum control panel since it is not implemented.
- Updated stylesheet to not underline the group expand/collapse toggle button.
- Updated version of CookComputing XML-RPC.NET library to use new .NET 2.0 optimized verison
- Updated list of default Weblog Ping URLS (removed Blo.gs and PubSub.com, added PingOMatic.com)
- Implemented TruncationEllipsisTemplate on the ObjectDataBase control to support custom markup/controls being used in the TruncationEllipsis
- Enabled adding new categories inline through Windows Live Writer
- Added rsd.ashx and wlwmanifest.ashx in web project, and added namespaces (Added support for RSD and WLWManifest).
- Updated MetaBlog to support excerpts, read-more, and post names
- Updated blog truncation to use readmore links
- Updated Metablog to default to the users current blog
- Added auto discovery for the current blogs metablog path
- Added basic site and blog theme
- Updated email templates for forum and forum thread emails to remove the background grey color.
- CSContext.User is only overridden with TokenUser when told via AllowTokenRequests(bool requirePrivateToken)
- Added rendering of news to the "Traveler" blog theme's sidebar.
- Added support for TemporaryUserTokens that expire after 3 hours
- Change password now uses a temporary user token
- Added support for disabling exception logging. It is disabled by default.
- Moved keep-alive code from global.js into the KeepAlive control.  Updated Editor control to *always* render a KeepAlive control.  Deleted web/utility/keepalive.aspx
- Added a few performance improvements to ThreadQueryBuilder classes: Only joining to cs_threads if we really have to, Adding a cs_Sections.ApplicationType filter back in
- Changed the expiration date from 30 days to 7
- Exception logging now occurs in background cache tasks

Bug Fixes:
- FileSystemWatcher pathing fix
- Request/Response encoding fix
- You can now resize the editor horizontally in the content editor modals
- You can now override an editor option without specifying type on the control
- You are no longer redirected to login when browsing a site that has forums at root while you are anonymous.
- Updated inline text editor to not overlap its popup container
- Updated Telligent.Glow.Modal to use frameborder='0' instead of frameborder='no'
- Create/Edit Blog Page Validation fixed so that appkey cannot be blank
- Added code and note bbcode and updated existing processing order of scrubbing modules
- Enabled checking of the user's Enable Email setting on a wide variety of message types
- Corrected all references in Chameleon controls to OpenWindow function in global.js to use a direct call to window.open.
- Updated Forum BreadCrumb control to use the current rewritten URL name instead of the rendered URL to determine the current page
- Updated EntryThumbnail control to render the file extension in the alt attribute.
- Updated EntryThumbnail control to render with an Image control and default to 0 border width and no alignment.
- The parent post cache is now expired properly when creating a new post in a thread.  This allows a reply to post to always display in a thread after it is created.
- Create edit blog post now maintains state better
- Added validation for the user's email address to Users.Create
- Fix for Gallery search results from searchbarrel linking to image not to gallery page
- Removed the ability to rename or delete the anonymous user
- Fixed issue where GalleryService.Update failed to set the PostID, which caused it to always fail.
- Updated cs_User_Delete sproc to update author/post ID's as well as names
- Disabled subforums no longer require user to login in parent forum
- Fixed theme cache name so that the cache key is correct.  Previously theme configuration were never getting retrieved from cache correctly.
- Changed create user page so that validation occurs when fields change as oppose to whenever a key was pressed.
- Group RSS Feed no longer causes Exception
- Pager added to the default aggregateentrylist control for the file gallery
- Clicking the Advanced Search link from a search results page now populates the advanced search options form for the lean and green theme as well as default
- Corrected QuickReply link to only refresh the page if false (and not undefined OR false) is passed as the callback parameter.
- Fixed EXIF page to show the full list of tags.
- Fixed photo post edit so it decodes the subject before populating the text box in the CP (to prevent double encoding)
- Fixed all auto-syndication registration to not re-html-encode section names.
- Fixed issue with users in the Member Administrators role not being able to change user passwords
- Fixed spelling error in the API... renamed User.EnableAvtar to User.EnableAvatar
- Updated default and leanandgreen themes to hide "view all users" link when "Display Member List" is set to "No" in the Control Panel.
- The SaveExtendedUserData call was moved into the event handler for the submit button, before the first call to sub-forms.
- You can now delete a tag that is disabled.
- User Points can now display without Post Points.
- Fixed issue with order of permissions not being handled properly
- Control Panel Report page title now shows correct text
- Fix for linking over to Shutterfly showing 0x0 as the picture's size.
- Fix for null reference on private messages from CS 2.x that were to users that were later deleted
- Fixed ForumSqlProvider to save sticky info on edited posts
- Corrected issue resulting in multiple encoding of the AvatarUrl property.
- Updated edit user form in the control panel to always show the user's Username in the "Alias" field.
- Updated blog admin control panel to properly decode the blog name.
- Corrected FireFox rendering issue on user+avatar lists in the default and lean and green themes.
- Fixed issue where Weblog XML-RPC pings do not get sent in some scenarios.
- Corrected misplaced </div> tag issue in PoisonIvy, Gertrude, Luxinterior, and Photos blog themes causing nested comments.
- Changed Roller Blog add-feed sproc to set Last Modified to current time - interval, so that the feed gets pulled the next time the job runs after the feed is added.
- Corrected rendering issue in the Control Panel in FireFox prior to JavaScript loading
- Updated the HTMLScrubber regex to use slightly different syntax which prevents infinite loop issue in FireFox.
- Corrected invalid anchor tag in blog themes.
- Added check for cs_Posts.IsIndexed in all SearchBarrel-generated queries.
- Fixed failed check to see if the user was anonymous within MailGateway
- Fixed how SPAM blocker counts links
- Fixed an issue with a missing resource label
- Updated CallbackPager to always render the PagedContent contents.
- Fixed issue with deserialization returning as successful when the output object is null
- Blog pages now show up in the tag post list if set to be aggregated, and the aggregate options are visible when creating a new page.
- Corrected thread view count to register one view per thread per rendered page regardless of the number of posts displayed on the page.
- Removed script to enable/disable "Join" button on the registration form in the default and lean-and-green themes to prevent issues with auto-complete.
- Updated TinyMCE wrapper to set the document_base_url TinyMCE option to the parent window's URL when the editor is opened in a Modal.
- Fixed notifications of message being flagged for moderation by MailGateway being queued with SettingsID of 0
- License usage colors are now cleared after uploading a license.
- Updated truncation ellipsis markup to render within the content wrapper (link) on ObjectDataBase control.
- Corrected next/previous thread links to direct to the thread's URL.
- Updated UserAvatarSubForm to set the remote avatar URL (if available) when an avatar is uploaded.
- cs_system_GenerateWeblogYearMonthDayList and cs_vw_weblog_PostByYearMonth now has some sql included to attempt to build the roll-up tables.
- Fixed regression from Bug Fix #1391 with AppKey being a required field on the blog creation page
- Selecting 'Hide Topics I've Read' in the forum filtered thread control now keeps the unread announcements visible on the first page
- You can now delete a forum post without it sending email
- Tweaks to cs_weblog_Post_Create and cs_weblog_Post_Update to ensure that UserTime was never NULL.
- Corrected potential XSS issue in User RSS Feeds
- Added EnsureHtmlEncoded calls to loaded TemporaryRssFeeds and TemporaryRssFeedItems content.
- Updated UserSearchForm to redirect to the rewritable URL instead of directly into the current theme.
- Pager fixed in the manage photo comments page so that you can page past the first 2 pages.
- Membership.GetRoles result set creation updated to ensure roles and role icons are re-populated after cache expiration
- Updated default Regex validation patterns for user names and passwords and ensured that these patterns always match the entire string when set.
- Updated sql to only change the regex pattern if the pattern [a-zA-Z]+[^\<\>]* was in the UsernameRegex before
- Added tabindex="-1" to all TinyMCE buttons to prevent tab-stops when navigating into the editor using the keyboard.
- Added validation of RSS feed URLs and external avatar URLs to ensure they are HTTP-based.
- Updated SearchBarrel to require Read access from applications supporting Read permissions.
- Adding ']' to a post no longer causes the post to pass the duplicate post check.
- Disabling post emoticons now hides the emoticon radio button list from the Forum options tab
- File Gallery comment URL's now work correctly, displaying the entry they belong to
- Corrected issue preventing section filters from being saved.
- Updated the form adapter to only update the form's action attribute when the page's URL has been rewritten by CS to ensure compatibility with external, non-rewritten pages within CS.
- Updated the thread queries used by blog and file gallery search indexing to specify IgnorePermissions=true so that all blogs and file gallery posts are indexed.
- Corrected infinite redirect issue when an invalid character exists in the URL.
- Changed const string cacheKey = "UserLookupTable" to include SettingsID
- Photo Gallery now supports HTMLEncoding a submitted user name field
- Added ApplicationName to the UserRoleNames cache key
- Corrected page height issue in IE when using tabbed panes.



5/5/2007 2:11:00 PM

偷偷升級到 CS2007 ..

Microsoft.NET | 543 | CS | 技術隨筆

好像沒啥人發現的樣子, 哈哈, 本站兩個禮拜前升級到 CS2007 了, 升級完面版馬上就調成舊的, 外觀看起來一模一樣...

功能當然有差, 不過我就不提了, 請直接到官方網站看就好. 升級很簡單, DB upgrade + File upgrade 就好了. 比較麻煩的是我自己客製過的 theme 跟 control ..

CS2007 的樣版系統, 從當年的 1.0 到 2.x 都一樣, 用了一堆動態載入 UserControl 的方式, 把版面配置的部份留在 User Control 的 TAG, 而後端的 data / logic 則是寫在 code. 因此要改它的樣版, 得花一番功夫瞭解它的作法.. 到了 CS2007, 總算改用 ASP.NET 2.0 標準作法了, 每套樣版就是一個 master page + config 而以 (theme.master, theme.config), 以 BLOG 來說, 每個頁面就很單純是一個 .aspx, 改起來方便多了, 不需要花什麼大腦就找的到要改那裡...

另一個 User Control, 舊的 API 有些都不能用了, 趁著這次改版我就直接把這幾個 User Control 改寫一次了. 以前都要寫 DLL 也是很麻煩, 這次一起改成 .ascx + .cs 就丟著了, deployment 方便嘛...

至於 CS2007 的新功能, 還沒很仔細的研究, 至少現在平台 ready 了 :D



2/17/2007 5:47:00 PM

Community Server 2007 Beta 1 Available Now

Microsoft.NET | 543 | CS | 技術隨筆

終於出來了, 從 scott 的 blog 看到的... 想要試看看的可以到這裡下載.

 

新版看來最大的改進就是換了 theme engine, 可以直接在 browser 上調整 UI, 效能也提高了.. 不過還沒試過也不曉得差在那裡 :P

其它改進我列幾個比較特別的:

  1. share membership store
    據官方說法, 可以好幾個友站 share 同一個會員資料庫... 我在猜大概是透過 web service, 實作一套 membership provider 吧...
  2. 可以直接把文章匯出成單一檔案, 包括圖片... ( .mht 檔? )
  3. demo.exe, 不需要安裝就可以試用... 應該是把 cassini 那種東西包進來吧, 不過試了一下, 我之前自己弄的批次檔還比較好用 :P

其它就等裝了再研究看看, 先祝大家新年快樂 :D



1/18/2007 12:17:00 AM

皮哥皮妹的年齡 user control ...

Microsoft.NET | 543 | ASP.NET | CS | 技術隨筆 | 家人

每次看 sea 在貼文章都會貼小皮幾歲幾個月, 妹妹幾個月... 就想說直接寫個 user control 就搞定了, 沒想到真的寫下去還有點小麻煩... 哈哈...

曆法的規則還真不少, 難怪每個教寫程式的書都會來一段萬年曆的 sample code.. 每個月天數都不一樣, 還有潤年不潤年的, 四年一潤, 百年不潤, 四百年又潤...

這堆原則弄下來, 單純的幾歲幾個月反而不好算了, 算從出生到現在共幾天, 去除 365 當歲數的誤差還好, 餘數再除 30 當月份的誤差就不小了, 最後的餘數再當天數就完全不對了...

弄了一下, 果然寫元件的爽度就是不一樣... 這個 control 寫好後的用法是這樣:

<CH:Age runat="server" birthday="2000/05/20" pattern="阿扁當總統已經 {0} 年 {1} 個月了" />

會顯示: 阿扁當總統已經 6 年 7 個月了

細節就不多說了, 以後進到 皮哥&皮妹的小天地 的左上角, 就看的到年紀, 純脆自己爽一下, 我們家的 blog 又跟別人的有一點點地方不一樣了 :D



3/19/2005 2:20:00 PM

修改 Community Server 的 blog editor

543 | ASP.NET | CS

好像每次換一套 blog, 我的宿命就是先改 editor, 讓它可以貼圖及貼表情符號... 哈哈

CommunityServer 用的是之前我介紹過的 FreeTextBox, 還不難改, 但是討厭的是 CS 並不是直接內嵌 FTB, 而是
中間多擋了一層 CS 自己的 Editor Wrapper... , 然後 CS 提供的 source code 就是少了這一塊...

沒辦法, 所以改出來的東西就有點格格不入, 多的工具列得排在畫面上方, 沒辦法加到原本 FTB 自己的工具列.
不然 FTB 其實還有很多好用的工具列可以打開... 真是可惜..



3/18/2005 1:02:00 PM

.Text Upgrade

543 | 技術隨筆 | CS

花了點時間, 把舊的 .Text Blog 0.95 升級到現在的 Community Server 1.0 RTM ...
看來還不錯嘛, 變成 Blog + Forum + Gallery 三合一了

網址做了點調整:

我的: http://community.chicken-house.net/blogs/chicken

sea的: http://community.chicken-house.net/blogs/sea



2/12/2005 3:59:00 AM

Community Server

543 | 技術隨筆 | CS

現在用的這套 blog, 就是 .Text 架的, 不過不會有更新版了... 因為作者跑去跟另外兩套軟體 ( ASPNET Forum, nGallery ) 的作者合作, 開了家公司, 直接把這三套軟體併成一套 community server...

community server 現在已經到了 RC2 版了, 看來相當不錯, 我抓測試版回來試用了一下... 放在這裡, 到時再來升級現在的 blog 跟 forum 吧, 我那個未完成的討論區也可以退休了



1/9/2005 12:37:00 PM

.TEXT 的編輯介面補強 (自己爽一下)..

Microsoft.NET | 技術隨筆 | CS

.TEXT 就是現在在用的 BLOG 系統, 相當簡單好用, 不過它內建的 editor (就是前幾篇介紹的 FreeTextBox, 只不過內建的是 v1.6) 雖然可以像word一樣的方式來編HTML, 不過就是少了插入圖片跟表情符號的功能...

我平常都是自己切到HTML source mode自己加tag, 不過實在是麻煩了點, 昨天就花了點時間自己改一下 code.. 現在多加了一排工具列可以用了 !! 底下是改好後的使用畫面, 留個紀念自己爽一下






精選文章

RUN! PC 文章及範例下載
2010/07. 結合檔案及資料庫的交易處理
2010/05. TxF讓檔案系統也能達到交易控制
2010/04. 生產者 vs 消費者 - 執行緒的供需問題
2008/11. 生產線模式的多執行緒應用
2008/09. 用ThreadPool發揮CPU運算能力
2008/06. SEMAPHORE在ASP.NET的應用
2008/04. 以ASP.NET開發同步WEB應用程式

如何學好 "寫程式" 系列
#1. 該如何學好 "寫程式" ??
#2. 為什麼 programmer 該學資料結構 ??
#3. 進階應用 - 資料結構 + 問題分析
#4. 你的程式夠 "可靠" 嗎?

#5. 善用 TRACE / ASSERT

安德魯是誰?

Andrew Wu | Create Your Badge

我喜歡鑽研物件導向、軟體工程及作業系統等相關技術。我會在這裡發表我的研究心得,也當作我自己的學習筆記。


Recent comments

Comment RSS