ExtJS是一套非常好的UI框架,已经有越来越多的企业级应用程序使用上了这个框架而从中受益。然后,在众多的项目当中,以J2EE项目居多,原因是ExtJS与Java的集成化越来越强。而对于使用.NET平台的开发者来说,想要在自己的项目当中使用ExtJS却困难重重,原因在于数据通信很难达到统一。在.NET 3.5以前,.NET平台提供有限的JSON原生支持。因而很多程序员都是使用第三方的组件。例如LitJson.net组件。

  在.NET 3.5中,框架提供了DataContractJsonSerializer类,可以方便地对对象进行JSON序列化跟反序列化。另外,.NET3.5提供了扩展方法跟LINQ,更是对我们的开发如虎添翼。在这篇BLOG中,我将使用这些新特性,对如何把ExtJS与.NET通信进行集成进行了分析。有什么错误,请大家指正,欢迎交流。

  一、使用DataContractJsonSerializer类

  该类用于对对象进行JSON序列化跟反序列化。该类位于System.Runtime.Serialization.Json命名空间中。是.NET3.5平台新增的类。主要使用WriteObject()跟ReadObject()方法对对象进行相应的操作。相关的API,可参考MSDN。

  二、扩展方法

  扩展方法,是.NET 3.5提供的新特性,用于增强原生对象的功能支持,扩展对象的功能。相关的介绍,请参照MSDN或相关书籍。

  三、泛型

  泛型对于许多.NET的程序员并不陌生。在.NET 2.0之后,已经在框架中添加了对泛型的支持。泛型使到我们减少了对象在装箱跟拆箱的过程中资源的损耗。

  接下来,我们可以编写如下的代码,用以扩展类的JSON序列化功能。我使用了扩展方法,并且使用泛型约束,约束了类型必须为类。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.IO;
using System.Text;
using System.Runtime.Serialization.Json;

/// 
/// Summary description for JsonExtends
/// 
public static class JsonExtends
{
    
public static string ToJson<T>(this T obj) where T: class
    {
        DataContractJsonSerializer ser 
= new DataContractJsonSerializer(obj.GetType
());
        
string output = string.Empty;
        
using (MemoryStream ms = new MemoryStream())
        {
            ser.WriteObject(ms, obj);
            StringBuilder sb 
= new StringBuilder();
            sb.Append(Encoding.UTF8.GetString(ms.ToArray()));
            output 
= sb.ToString();
        }
        
return output;
    }

    
public static T FromJson<T>(this string jsonString) where T : class
    {
        T ouput 
= null;
        
try
        {
            DataContractJsonSerializer ser 
= new DataContractJsonSerializer(typeof(T
));
            
using (MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes
(jsonString)))
            {
                ouput 
= (T)ser.ReadObject(ms);
            }
        }
        
catch (Exception) { }
        
return ouput;
    }
}

 

  建立实体类,注意:为了序列化类及类成员,必须是类成员上使用DataContract属性,成员则需要使用DataMember属性,忽略DataMember属性的成员将不被序列化。同时,DataMember属性也适合集合成员,其序列化的结果将是一个jSON数组。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Runtime.Serialization;

/// 
/// Summary description for Employee
/// 
[DataContract]
public class Employee
{
    [DataMember]
    
public string FirstName { getset; }
    [DataMember]
    
public string LastName { getset; }
    
//public List Payments { get; set; }
}

 

建立一般处理程序EmployeesPayment.ashx,用以向ExtJS交互数据的接口。用ashx而不用aspx的好处,是ashx不用经历复杂的页面生命周期,效率大大提高。

using System;
using System.Web;
using System.Collections.Generic;

public class EmployeesPayment : IHttpHandler {
    
    
public void ProcessRequest (HttpContext context) {
        context.Response.ContentType 
= "application/x-json";
        Employee employee 
= new Employee { LastName = "光年", FirstName = "巴斯" };
        context.Response.Write(employee.ToJson
<Employee>());
    }
 
    
public bool IsReusable {
        
get {
            
return false;
        }
    }

}

 

JSON表现层

Ext.BLANK_IMAGE_URL = 'resource/images/default/s.gif';
Ext.onReady(
function() {
    
var fr = new Ext.FormPanel({
        title: 
'测试JSON',
        frame: 
true,
        id: 
'frJson',
        autoHeight: 
true,
        applyTo: 
'con',
        width: 
200,
        labelWidth: 
30,
        items: [
            
new Ext.form.TextField({
                fieldLabel: 
'',
                id: 
'FirstName'
            }),
            
new Ext.form.TextField({
                fieldLabel: 
'',
                id: 
'LastName'
            })
        ],
        buttons: [
            {
                text: 
'提取数据',
                handler: 
function() {
                    Ext.MessageBox.wait(
'正在加载数据''加载数据');
                    
var config = {
                        url: 
'EmployeesPayment.ashx',
                        method: 
'GET',
                        success: 
function(res, op) {
                            Ext.MessageBox.hide();
                            
var obj = Ext.decode(res.responseText);
                            Ext.getCmp(
'FirstName').setValue(obj.FirstName);
                            Ext.getCmp(
'LastName').setValue(obj.LastName);
                        }
                    };
                    Ext.Ajax.request(config);
                }
            }
        ]
    });
});