通常在 MasterPage 中會引用一些 CSS,但是很詭異的是在 ContentPlaceHolder 使用那些定義於 CSS 中的 class 時,儘管實際 render 網頁的時候是正確的,但每次看到編譯完後 MS Visual Studio 2008 出現一排警告訊息還是覺得很厭煩...
MS-VS-class-error

雖然有網友說安裝完 VS SP1 後就可以解決上述的問題,不過在我的開發環境還是一樣會出現這些警告訊息;下列的程式碼是從 Tired of Visual Studio Telling You "The class or CssClass value is not defined"? 擷取出來的,原作者把原本的引用路徑複製一份到 <asp: Literal...> 中,且把該控制項設定為 Visible="false",編譯後檢視網頁原始碼會發現並沒有什麼不同(因為 Visible="false"),但是對 Visual Studio 而言就不會出現那些警告訊息了,雖然不是最佳解,但還是有蠻好的效果的。

<head runat="server">
  <title>The Page</title>
  <asp:Literal Visible="false" runat="server">
    <link href="~/Content/SuppressCssWarnings.css"
        rel="stylesheet" type="text/css" />
  </asp:Literal>
  <!-- You probably have more here... -->
  <link href="~/Content/SuppressCssWarnings.css"
      rel="stylesheet" type="text/css" />
</head>

Firefox Extension:IDE Environment Setup

接觸 Firefox 以來,對多樣化且功能強大的 Extensions 印象很深刻,但從沒想過有一天也需要去開發擴充套件...一切就從老闆的需求開始去硬K...這個系列(如果還有下一篇的話),比較不會用市面上常見的電腦教學書一般,用一個大案子貫穿整個主題(因為我也不太熟XD),比較會傾向用 case 的方式來說明,希望能減少有興趣踏入的朋友一些摸索撞牆的時間...若文中內容有誤,也請不吝賜教 ^o^

開發勢必要會的知識:Javascript 和 XUL(XML User Interface Language),官網上有詳細的中文說明,煩請參閱...本文主要是想介紹自己常用的開發環境設定。撰寫 Javascript Code 方面,我是使用 Spket IDE - 可以直接整合到 eclipse 中,安裝好後,可以直接建立一個 Firefox Extension Project(如下圖所示)。


這樣做的好處是,Spket IDE 可以快速的幫我們開出一個符合 Firefox Extension 的檔案架構(如下圖)。且用 eclipse 的好處是,可以直接對著根目錄的 build.xml 按下右鍵後選取 "Ant Build" 會直接幫你打包成 .xpi(其實本身也是一個壓縮檔,裡面有包好的 .jar 等檔案)。


XUL 中定義了很多常見的控制項(XUL controls),如果怕敲錯字或不想看文件的話,可以用 XUL Explorer 小工具來建構你想打造的 Extension 外觀。工具左邊是你想要放的控制項,像是按鈕或是選單之類的,拖到右邊後,可以按下 Preview 就會是在 Extension 中長的樣子。


長久被 MS Visual Studio 養慣...實在會覺得整個 IDE Solution 相對沒有非常友善...因為我敲錯字或多一個 ; 還是可以 build 成功...有時候會 debug 很久..因為 console 也看不到錯誤...實在很難想像大如 firebug 的套件是怎麼快速開發和維護的。

JSON serialization and deserialization in .NET

近期常用到 AJAX 方式去呼叫後端的 Web Services,資料的傳遞交換均是用 JSON (JavaScript Object Notation),這篇主要是整理一些在 .NET 上序列化 (Serialization)和反序列化 (Deserialization)的小技巧和心得。
對於 JSON 的入門觀念可以參閱 Introducing JSON 或是 syshen's blog 中的 JSON 介紹。JSON 的資料格式簡言之可以看成是 Object 和 Array 的組合;Object 是指用大括號 {} 包起來的 string:value 的組合,如果多組組合的話,中間則是以逗號區隔,例如:{string1:value1, string2:value2, ....}。而 Array 的特徵則是用中括號 [] 包住以逗號區隔的 values。

接下來分別整理一下在 .NET 中對 JSON 做序列化和反序列化的動作。

序列化 (Serialization)
假設情境是,前端的 AJAX 對後端的 Web Service 做了一個呼叫,而我們想要回傳 JSON Data 的話,可以用下列的方式。
var query = from _table in DataContext
    .Table select _table; // obtain data by Linq 

System.Web.Script.Serialization.JavaScriptSerializer serializer 
    = new System.Web.Script.Serialization.JavaScriptSerializer();

List<Dictionary<string, object>> rows 
    = new List<Dictionary<string, object>>();

Dictionary<string, object> row;

foreach (var item in query) { 
    // each object can contains the number of string/value pairs 
    row = new Dictionary<string, object>();
    row.Add("string1", value1);
    row.Add("string2", value2);
}

return serializer.Serialize(rows);
反序列化 (Deserialization)
可能的情境是,後端的 Web Service 接收到前端的資料格式為 JSON 結構,可能是單筆也可能是多筆資料的集合;目前的話 .NET 3.5 以上可以用 DataContractJsonSerializer 類別來處理,或是可以用 Json.NET 做解析,使用上最大的差異在於 Json.NET 在做解析(parse)的時候並不需要事前建立對應的 Mapping-Table,但是 DataContractJsonSerializer 使用上必須對應到強型別的物件上 (strongly managed objects),所以需要事先宣告外,在資料結構上有異動時,還需要連動變更。

DataContractJsonSerializer Class
// before using DataContractJsonSerializer class
// , we need to claim the mapping data-types
[Serializable]
[DataContract]
public class DataObject
{

  [DataMember(Name = "title")]
  // can assign the custom property
  public string Title { get; set; }

  [DataMember(Name = "url")]
  public string URL { get; set; }
}


DataContractJsonSerializer ser 
    = new DataContractJsonSerializer(typeof(DataObject));

MemoryStream ms 
    = new MemoryStream(Encoding.Unicode.GetBytes(jsondata));

DataObject o = ser.ReadObject(ms) as DataObject;
但如果 JSON 內含有多筆的資料要如何處理呢? 例如:[{items:{"title": value, "url": value},{"title2": value, "url2": value}}]
// here we need defined List&lt;DataObject&gt;
[DataContract]
public class DataObjects
{
    [DataMember(Name = "items")]
    public List&lt;DataObject&gt; items { get; set; }
}

DataContractJsonSerializer ser 
    = new DataContractJsonSerializer(typeof(DataObjects));

MemoryStream ms 
    = new MemoryStream(Encoding.Unicode.GetBytes(jsondata));

DataObjects os = ser.ReadObject(ms) as DataObjects;


// loop data
foreach (DataObject o in os.items)
{
    Console.WriteLine(o.Title);
    Console.WriteLine(o.URL);
}
References:
Json.NET
如果是使用 Json.NET 的話,就不需要先宣告對應的型別,相對而言較彈性與簡潔;例如輸入的資料格式為:json = [{},{},{},.....,{}]
JArray a = JArray.Parse(json);
foreach (var item in a)
{
    JObject o = item as JObject;
    // Console.WriteLine((string)o["title"]);
}