首先看一下ASP.NET AJAX伺服器端對日期類型JSON序列化的處理:(詳見Ajax擴充源碼中的JavaScriptSerializer.cs)
internal static readonly long DatetimeMinTimeTicks = (new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).Ticks;
private static void SerializeDateTime(DateTime datetime, StringBuilder sb) {
sb.Append(@"""//Date(");
sb.Append((datetime.ToUniversalTime().Ticks - DatetimeMinTimeTicks) / 10000);
sb.Append(@")//""");
}
最早期,微軟使用下面方法進行序列化:
ASP.NEXT 中的 AJAX JSON 序列化程式將 DateTime 執行個體編碼為 JSON 字串。在預發布周期中,ASP.NET AJAX 使用格式“@ticks@”,其中 ticks 表示從通用協調時間 (UTC) 1970 年 1 月 1 日起經過的毫秒數。以 UTC 表示的日期和時間(如 1989 年 11 月 29 日 4:55:30 AM)會編碼為“@62831853071@”。雖然簡單易懂,但此格式無法區分序列化的日期和時間值與看起來像序列化日期但又不需要進行還原序列化的值。因此,ASP.NET AJAX 團隊對最終版本進行了更改,通過採用“//Date(ticks)//”格式解決了這一問題。
新格式藉助一個小技巧減少了誤解的可能性。在 JSON 中,字串中的正斜杠 (/) 字元可以用反斜線 (/)
進行轉義(即使沒有對此進行嚴格要求)。ASP.NET AJAX 團隊利用這點修改了 JavaScriptSerializer,將
DateTime 執行個體編寫為字串“//Date(ticks)//”。兩個正斜杠的轉義只是表面的,但對 JavaScriptSerializer 至關重要。按照 JSON 規則,“//Date(ticks)//” 在技術上相當於 “/Date(ticks)/”,但 JavaScriptSerializer 會將前者還原序列化為 DateTime,將後者還原序列化為 String。因此與預發布版本的“@ticks@”格式相比,混淆的可能性會大大減少。
註:此段文字來源於MSDN文章《JavaScript 和 .NET 中的 JavaScript Object Notation (JSON) 簡介》
這裡我要補充一個技巧,大家知道,在document中如果出現<script>和</script>那麼腳步解譯器就會對其中文本進行解析,所以如果你編寫下面的代碼,則會提示錯誤:
<script>
document.write("<script>alert(1);</script>");
</script>
因為中間出現了“</script>”這樣的代碼,那麼我們可以使用:
<script>
document.write("<script>alert(1);</scr"+"ipt>");
</script>
來避免這種錯誤,這時我們還可以使用“/”來轉義:
<script>
document.write("<script>alert(1);<//script>");
</script>
-----------------------------------------------------------------------------------------------------
執行個體解決:
Class rssItem
[Property(NotNull = true, Column = "PubDate")]
public virtual DateTime PubDate
{
get { return _pubDate; }
set { _pubDate = value; }
}
webservice .cs中
[WebMethod(Description="1234567")]
[SoapHeader("Credentails", Direction = SoapHeaderDirection.In)]
[CredentialExtension]
//[ScriptMethod(ResponseFormat=ResponseFormat.Json)]
public DB.RSSItem[] GetArray()
{
//this.VerifyCredential(this);
DB.RSSItem[] objs = ActiveRecordBase<DB.RSSItem>.SlicedFindAll(0, 5);
foreach (RSSItem obj in objs)
{
obj.TClass = new TClass();
//obj.TClass.Item = obj;//
}
return objs;//
}
[WebMethod]
public DB.RSSItem GetItem()
{
DB.RSSItem obj = GetArray()[0];// ActiveRecordBase<DB.RSSItem>.FindFirst();
return obj;//
}
[WebMethod]
[SoapHeader("Credentails", Direction = SoapHeaderDirection.In)]
[CredentialExtension]
//[GenerateScriptType(typeof(RSSItem))]
//[GenerateScriptType(typeof(TClass))]
public DB.RSSItem[] GetArray2(RSSItem obj)
{
return GetArray();
}
用戶端 JS.aspx
<script type="text/javascript" src="Content/script/jquery-1.2.6.pack.js"></script>
<script type="text/javascript" src="http://www.json.org/json2.js"></script>
<script language="javascript" type="text/javascript">
//1、WebService請求類型都為Post,WebService的Url為“[WebServiceUrl]/[WebMethod]”
//2、contentType聲明為Json
//3、data要用Json的字串格式傳入
//4、設定了dataType為json後,result就直接為返回的Json對象。
var dd;
$(function()
{
//調用無參數
$("#btnHelloWorld").click(function(){
$.ajax({
type:"POST",
contentType:"application/json",
url:"WebServices/WebService1.asmx/GetItem",
data:"{}",
dataType:'json',
success:function(result){
dd=result.d;
alert(result.d);
}
});
});
//傳入一個參數
$("#btnHello").click(function(){
var jsonStr = JSON.stringify(dd); //用Json2.js產生Json字串
//jsonStr = jsonStr.replace(new RegExp('(^|[^////])//"/////Date//((-?[0-9]+)//)///////"', 'g'), "$1new Date($2)");//將“"//Date(ticks)//"”轉化為“new Date(ticks)”
//jsonStr = jsonStr.replace(new RegExp('(^|[^////])//"/Date//((-?[0-9]+)//)///"', 'g'), "$1new Date($2)");//將“"/Date(ticks)/"”轉化為“new Date(ticks)”
jsonStr = jsonStr.replace(new RegExp('(^|[^////])//"/Date//((-?[0-9]+)//)///"', 'g'), '$1/"///Date($2)////"');//將“"/Date(ticks)/"”轉化為“"//Date(ticks)//"”不然會出錯!!!
//alert(jsonStr);
$.ajax({
type:"POST",
contentType:"application/json",
url:"WebServices/WebService1.asmx/GetArray2",
//data:"{obj:99}",//
data:"{obj:"+jsonStr+"}",//
dataType:'json',
success:function(result){
alert(result.d);
}
});
});
解決了傳GetArray2參數中傳自訂RSSItem類型的問題.....OK!!!