在第二章中已经对前台处理部分进行了编码,此章将探讨后台(.NET,C#为例)部分的编码。
从第一章的构架分析:后台的任务主要是构造符合前台解析规则的“消息协议”。接下来我们先分析这种协议的特点:
1、需要有头信息(必须),用于对请求状态的标示。包括 _Success,_Fail,_Action 三个状态
2、必须有自定义信息,用于进行用户自定义数据的传送
3、对头信息中的标示采用属性方式设定,对于自定义信息中的数据必须能实现:添加、删除单个
删除所有、重设单个的功能
4、最后必须输出标准的Json字串
根据以上特点便可以编码出这种消息协议对象(JsonInfo)。因为要使用Json作为传输介质,因此
我们必须引用“Newtonsoft.Json” 即Json.Net dll组件。为了让我们的JsonInfo能够支持更多的对象
序列化,还必须考虑弥补Json.Net对DataSet和DataTable的不足。我们需要增加这两种解析方式。
从上面的四点可知,不论是头信息还是自定义信息,其实都是Key/Value的形式,我们可以通过编程
手段将两者归为一个对象中。这里我采用泛型Dictionary<string, object>来存储信息。代码见下:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using Newtonsoft.Json; using System.Data; namespace PersonalTool { /// <summary> /// 用于进行Ajax数据交流的后台类 /// </summary> public class JsonInfo { Dictionary<string, object> DT = new Dictionary<string, object>(); static List <string> ProtectKey = new List<string> {"_Success","_Fail","_Action"}; /// <summary> /// 返回所有的键值字典 /// </summary> public Dictionary<string,object> ItemDictionary { get { return DT; } } /// <summary> /// 成功信息 /// </summary> public string Success { get { return DT["_Success"].ToString (); } set { DT["_Success"] = value; } } /// <summary> /// 失败信息 /// </summary> public string Fail { get { return DT["_Fail"].ToString (); } set { DT["_Fail"] = value; } } /// <summary> /// 后续动作 /// </summary> public string Action { get { return DT["_Action"].ToString (); } set { DT["_Action"] = value; } } public JsonInfo() { DT.Add("_Success", ""); DT.Add("_Fail", ""); DT.Add("_Action", ""); } /// <summary> /// 添加自定义键值 /// </summary> /// <param name="KeyName">键名称<para>(不能为以下值 _Success,_Fail,_Action)</para></param> /// <param name="Object">键对象</param> public void AddItem(string KeyName, object Object) { if (ProtectKey.Contains(KeyName)) SetItem(KeyName, Object); else DT.Add(KeyName, Object); } /// <summary> /// 设定键值 /// </summary> /// <param name="KeyName">键名</param> /// <param name="Object">键值对象</param> public void SetItem(string KeyName, object Object) { DT[KeyName] = Object; } /// <summary> /// 删除指定的键 /// </summary> /// <param name="KeyName"></param> public void DelKey(string KeyName) { if (ProtectKey.Contains(KeyName)) SetItem(KeyName, ""); else { if (DT.ContainsKey(KeyName)) DT.Remove(KeyName); } } /// <summary> /// 清除所有的键值,恢复默认值 /// </summary> public void ClearAll() { DT.Clear(); DT.Add("_Success", ""); DT.Add("_Fail", ""); DT.Add("_Action", ""); } /// <summary> /// 返回格式化了的Json字串 /// </summary> /// <returns></returns> public string ToJson() { return JsonConvert.SerializeObject(DT,new DataSetConverter(),new DataTableConverter()); } /// <summary> /// 输出格式化了的Json字串,并结束当前的处理流(即Response.End()),因此在使用时需要考虑try…catch的情况 /// </summary> public void ToJsonAndStop() { System.Web.HttpContext.Current.Response.Write(ToJson()); System.Web.HttpContext.Current.Response.End(); } } /// Json 补充的类 class DataSetConverter : JsonConverter { public override bool CanConvert(Type objectType) { return typeof(DataSet).IsAssignableFrom(objectType); } public override Object ReadJson(JsonReader reader, Type objectType, JsonSerializer serializer) { return null; } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { DataSet ds = (DataSet)value; writer.WriteStartObject(); foreach (DataTable dt in ds.Tables) { writer.WritePropertyName(dt.TableName); writer.WriteStartArray(); foreach (DataRow dr in dt.Rows) { writer.WriteStartObject(); foreach (DataColumn dc in dt.Columns) { writer.WritePropertyName(dc.ColumnName); writer.WriteValue(dr[dc].ToString()); } writer.WriteEndObject(); } writer.WriteEndArray(); } writer.WriteEndObject(); } } class DataTableConverter : JsonConverter { public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { DataTable dt = (DataTable)value; writer.WriteStartArray(); foreach (DataRow dr in dt.Rows) { writer.WriteStartObject(); foreach (DataColumn dc in dt.Columns) { writer.WritePropertyName(dc.ColumnName); writer.WriteValue(dr[dc].ToString()); } writer.WriteEndObject(); } writer.WriteEndArray(); } public override Object ReadJson(JsonReader reader, Type objectType, JsonSerializer serializer) { return null; } public override bool CanConvert(Type objectType) { return typeof(DataTable).IsAssignableFrom(objectType); } } }
从上可以看出对于头信息中的三个标示采取一定的保护措施。在Json 补充的类,我们扩展了原有的
转换,由于本消息协议只关心序列化,因此在对DataTableConverter和DataSetConverter中ReadJson
这个抽象方法上并未做实现。
到此,后台部分也就完成了。后台不但能够方便的实现常用对象的序列化,同时还可以很好的序列化DataSet
和DataTable。有了这些对于常用的交互需求应该算是有了很好的支持。
小提示:
1、 对于String,Int……等对象序列化后是很好通过Js访问的,这里需要指出是对于DataSet和DataTable的访问。
当然您可以查看ToJson方法输出的字串信息。在这里我简要说明一下。
如果是DataSet则返回的信息格式参考如下:
服务端:XX.AddItem(“DataSet”,DS);//DS为一个DataSet对象
客户端收到的字串:
”DataSet”:{“Table1”:[
{“UserName”:”FoxHunter”,”Age”:23,”Sex”:1},
{“UserName”:”FoxHunter2”,”Age”:23,”Sex”:1},…],
”Table2”:[
{“Right”:”Admin”,”NickName”:”Fox”},
{“Right”:”Guest”,”NickName”:”Guest”},…],…}
Js转换成Object后:
?.DataSet.Table1[0].UserName ; ?.DataSet.Table1[1].Age ; ?.DataSet.Table2[0].Right ; 这样您就可以方便的访问了。
如果是DataTable则情况如下:
服务端:XX.AddItem(“DataTable”,DT);//DT为一个DataTable对象
客户端收到的字串:
”DataTable“:[
{“UserName”:”FoxHunter”,”Age”:23,”Sex”:1},
{“UserName”:”FoxHunter2”,”Age”:23,”Sex”:1},…]
JS转化为Object后:
?.DataTable[0].UserName ; ?.DataTable[1].Age ;
总之记住规律(注意颜色标示):对于表(例如 Table1 Table2 DataTable )的访问可以直接书写其名字。而对于表格中的Row(例如 方括号中的 大括号对 表示Row)必须通过在前面的表名中加上索引值来访问(因为他们是数组的形式),当你访问到Row后,row中的字段值就可以直接用”.“语法来访问了。“?”是因为我省略了一个对象这个对象是前台回调函数中的第一个参数,因此此处无法标明。
2、您可以在前一篇的JS代码中加入以下内容,以便于您Ajax交互时查看后台传回的字串(调试完后记得删除,下面粗体部分)
$.ajax({ type: reqObject.type, dataType: "json", //设置解析数据方式为json url: reqObject.url, cache: reqObject.cache, data: reqObject.data, complete: doJsonInfoComplete,//正式使用时记得删除或注掉 success: function(e) { doJsonInfoCallBack(e, reqObject) }, //成功执行ajax后的回调函数,e为服务端返回的Javascript Object对象 timeout: reqObject.timeout, // 超时时间 error: function(XMLHttpRequest, textStatus, errorThrown) { doJsonInfoError(XMLHttpRequest, textStatus, errorThrown, reqObject) } //ajax执行发生错误后调用 });
var doJsonInfoComplete = function(XMLHttpRequest, textStatus) { alert(XMLHttpRequest.responseText); } var doJsonInfoCallBack = function(e, reqObject) {...
OK,在此后台和注意事项便交代完毕了,相信对Asp.Net和Javascript了解的应该已经知道整个
模型如何使用了,接下来就是最后一章,关于模型使用的演示代码和所有源文件了。
[Come From: http://foxhunter.yo2.cn/articles/ajax-aspnet-03.html]