
3.2.4 使用一般处理程序生成JSON
在AJAX程序中,经常需要向浏览器返回JSON格式的数据结果,JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,易于人阅读和编写,同时也易于机器解析和生成。它是基于JavaScript Programming Language, Standard ECMA-262 3rd Edition - December 1999的一个子集。JSON采用完全独立于语言的文本格式,但是也使用了类似于C语言家族的习惯(包括C, C++, C#, Java, JavaScript, Perl, Python等)。这些特性使JSON成为理想的数据交换语言。详细的JSON 规范可以参考 http://www.json.org/json-zh.html。
在第2章中,我们已经实现了自定义的上传管理,甚至已经在上下文对象中保存了上传进度的信息。通过JSON,我们可以向客户端返回服务器端的上传进度。
对于服务器端来说,所谓的JSON实际上就是一段字符,我们可以直接通过拼接字符串的形式来生成。需要注意的是,JSON中通过{ }来表示对象,这两个符号与c#字符格式化串中使用的展位符号{ }冲突,为了在格式化串中使用{ },可以将符号重复一次即可。例如,当需要输出一个{的时候,在C#的字符串中需要连续写两个{{。
为了防止浏览器缓冲服务器返回的内容,通过回应头禁止客户端的缓存,代码如下所示:
context.Response.Cache.SetCacheability(System.Web.HttpCacheability.NoCache);
其他代码如代码清单3-2所示。
代码清单3-2 一般处理程序JSON
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace DiskFileUpload { public class UploadPercnetHandler: System.Web.IHttpHandler { #region IHttpHandler Members public bool IsReusable { get { return true; } } public void ProcessRequest(System.Web.HttpContext context) { string key = context.Request[DiskFileUpload.UploadFiles. DiskFileUpload_GUID]; DiskFileUpload.UploadFiles item = context.Application[key] as DiskFileUpload.UploadFiles; int uploadPercent = 0; if (item != null) { uploadPercent = item.CompletePercent; } string json = string.Format( "{{ \"percent\":{0} }}", uploadPercent ); context.Response.Cache.SetCacheability(System.Web.HttpCacheability. NoCache); context.Response.ContentType = "application/json"; context.Response.Write(json); } #endregion } }
配合JavaScript脚本,可以实现上传过程中的动态显示。
<script type = "text/javascript"> function uploadProgress() { var elemBar = document.getElementById("barCell"); var elemPercent = document.getElementById("percentCell"); var uploadid = document.getElementById("DiskFileUpload_GUID").value; alert(uploadid); var timerid = window.setInterval( function() { var xhr; if (window.ActiveXObject) xhr = new ActiveXObject("Microsoft.XMLHTTP"); else xhr = new XMLHttpRequest(); xhr.open("get","progress.ashx?DiskFileUpload_GUID=" + uploadid, false); xhr.send(null); if (xhr.readyState == 4) { if (xhr.status == 200) { var result = eval("(" + xhr.responseText + ")"); elemBar.style.width =result.percent + "%"; elemPercent.innerHTML = result.percent + "%" } } } , 1000 ); } </script>
当用户单击上传按钮之后,启动上传进度的处理函数,显示当前的上传进度。
<asp:Button ID="Button1"runat="server"Text="Button" onclick="Button1_Click" OnClientClick="uploadProgress();" />
实际上传的效果如图3-2所示。

图3-2 显示上传进度
在.NET 3.5之后,定义在命名空间System.Runtime.Serialization.Json中的DataContractJsonSerializer可以帮助我们直接将一个对象格式化成JSON,或者将一个JSON反序列化为一个.NET中的对象实例。这样,实现起来可以更加简单,参见代码清单3-3。
代码清单3-3 .NET 3.5之后的实现
using System; using System.Web; public class Result { public int percent { get; set; } } public class JsonHandler: IHttpHandler { public void ProcessRequest(HttpContext context) { context.Response.ContentType = "application/json"; context.Response.Cache.SetCacheability(HttpCacheability.NoCache); System.Type type = typeof(Result); System.Runtime.Serialization.Json.DataContractJsonSerializer serializer = new System.Runtime.Serialization.Json.DataContractJsonSerializer(type); Result result = new Result(); result.percent = 80; serializer.WriteObject(context.Response.OutputStream, result); } public bool IsReusable { get { return false; } } }