带 AJAX 的通用数据交换框架
一个通用的 AJAX 数据交换框架。
引言
互联网编程必须是尴尬且用户不友好的吗?是的,它是,并且将继续如此,直到互联网编程模型从 HTTP/HTML 更改为另一种模型。我已经听到非常愤怒的批评说,这个模型被成千上万的程序员成功地使用了。是的,这是真的。但是,你是否曾经问过自己这样的问题:十多年来互联网存在,却没有一个像样的 HTML 编辑器,这不是很奇怪吗? HTML 页面的开发总是需要调整 HTML 标签。这些编辑器是由无能的初学者开发的吗?不,它们是由非常有能力的人设计的,但 HTML 语言无法胜任。但这还不是全部。服务器和客户端之间的数据交换非常原始。没有通用对象。即使是 ASP.NET,情况也没有太大改善。不幸的是,模型无法立即改变。我们必须为此再忍受几年,而本文将讨论如何解决一些互联网数据交换问题。
统一客户端和服务器编程
用与服务器相同的方式编程客户端(通过对象,而不是通过 HTML 和 DOM 术语)会不会很好?富客户端开发的主要问题是什么?问题在于富应用程序(基于 Windows Forms 或 Web Forms)总是依赖于富对象。富意味着结构良好、分层的类以及操作这些结构的手段。不幸的是,客户端没有任何东西可以帮助完成这项任务。我们有 JavaScript 语言——一种相当不错的语言,它在语法上允许操作结构化数据,但没有机制可以将这些结构从服务器传输到客户端,再从客户端传回服务器。充其量,我们可以使用 XML 解析器。但是,我们必须这样做吗?
这里介绍的框架解决了这些问题。所有对象都源自服务器。我们在服务器上创建几乎任何复杂度的对象(类),初始化它们,将它们注册到框架(RWCDF),然后框架将已经初始化的对象生成给客户端。在客户端完成数据操作后,对象将通过传统的 Postback 或 AJAX(以及)传回服务器。您还可以使用 AJAX 调用直接在服务器上调用方法,并将对象(类)作为参数传递。为了高效地进行数据操作,我们还需要集合。没有像 ArrayList
和 Hashtable
这样的动态结构,实现任何严肃的数据操作引擎都非常耗时。框架中已经实现了并包含 JavaScript ArrayList
和 Hashtable
。换句话说,该框架统一了服务器和客户端的数据操作。有了这个框架,Web 客户端的编程几乎与服务器的编程相同。但请注意,这不是万能药。JavaScript 的性能是主要的障碍。除此之外,JavaScript 的数据类型也非常松散。
框架编程
第一个合乎逻辑的步骤是创建满足我们需求的数据结构。
public class EmployeeAddress
{
public string City;
public string Country;
public string Street;
public string Phone;
public ArrayList PhotoAlbum = new ArrayList();
}
public class Employee
{
public long somelong = 8598065;
public double Salary = 787878.344;
public float Scale = 8.66F;
public string Name;
public string SName;
public string Title;
public string Position;
public int Age;
public DateTime Date;
public string PictureUrl;
public EmployeeAddress Address;
public bool Married = true;
public ArrayList SomeDataCollection;
public Employee
{
Address = new EmployeeAddress();
}
}
请注意,EmployeeAddress
类的实例是 Employee
类的成员。实际上,嵌套类的深度没有限制。我们创建 Employee
实例并对其进行初始化。
ArrayList MyEmployees = new ArrayList();
Employee emp = new Employee()
emp1.Name = "Bob";
emp1.SName = "Smith";
emp1.Title = "Mr";
emp1.Position = "waiter";
emp1.Date = new DateTime(2003, 2, 6);
emp1.Address.City = "London";
emp1.Address.Phone = "(043)8984 63535";
emp1.Age = 33;
emp1.PictureUrl = "BobSmith.jpg";
//add employee to ArrayList
MyEmployees.Add(emp);
//....then create more employees and also add them to ArrayList
MyEmployees.Add(emp1);
之后,我们只需要注册我们希望在客户端上使用的对象 - 在本例中,它是 Employee
对象集合 - MyEmployees
。
Convertor.RegisterObject("MyObjectKey", MyEmployees);
注册对象的数量没有限制。之后,客户端可以通过 JavaScript 类 ArrayList
访问 MyEmployees
对象。
var EmployeesArrList = _Get("MyObjectKey");
获取第一个员工
var emp = EmployeesArrList.GetAt(0);
alert(emp.SName + ", " + emp.Name + "," + emp.Title + "," +
emp.Position + "," + emp.Address.Street);
其他员工也是如此。
集合中的员工可以被修改并通过传统的 Postback 或 AJAX(以及)发送回服务器。您也可以通过参数为 EmployeesArrList
(或其他类)调用服务器上的方法。
var Params = new Array();
Params.push(EmployeesArrList );
var Ret = r.Invoke("ReadEmployeesMethod", Params);
您可以创建 Employee
实例并对其进行初始化
var Emp1 = new Employee ();
Emp1.Name = "Peter";
Emp1.Age = 20;
依此类推……将此员工添加到集合中。
工作原理
服务器上的业务对象被初始化,然后序列化为 XML 格式。然后,此代码将被注入 HTML 页面的 body 中,并发送到客户端进行渲染。数据保存在隐藏字段中。页面加载时,序列化数据会在客户端反序列化为 JavaScript 对象集合。
数据同步
现在我们有了服务器端的数据,形式是 JavaScript 对象,例如 Employee
对象,我们可以更改这些类的字段。
emp.Position = "waiter";
下一步是将对象发送回服务器。这可以通过两种方式完成:Postback 和 AJAX。**更新服务器对象只需要调用方法**。
_Put("MyEmployeesArr", EmpArrList);
在 Postback 发生之前。
更新服务器对象的另一种方法是通过 XmlHttp
发送集合。为此,只需调用
r.Send ("some string data from client");
在此特定情况下,字符串“some string data from client”将被发送到服务器。
服务器上定义的(并在客户端上重新创建的)对象,例如 Employee
,也可以被发送
r.Send(emp);
或者对象集合
r.Send(EmployeesArrList);
其中 r
是 Remoting
(在 Rwc.js 中定义的 JavaScript 对象)。
此外,还可以使用 Invoke
方法(同样在 Rwc.js 中定义)在服务器上调用方法。
var Ret = r.Invoke("ReadABCD", Param1);
其中 ReadABCD
是服务器上的方法名称。Param1
是对象(任何在服务器上定义并注册过的对象)。
这是一个调用 Invoke
的示例
var Params = new Array();
Params.push(EmployeesArrList );
var Ret = r.Invoke("ReadEmployeesMethod", Params);
您可以在客户端创建 Employee
实例并对其进行初始化
var Emp1 = new Employee ();
Emp1.Name = "Peter";
Emp1.Age = 20; //..... And so on ...
将此员工添加到集合中
var EmpCollection = new ArrayList();
EmpCollection.Add(Emp1);
添加其他员工并将此集合发送到服务器(Postback/AJAX)。在服务器端,对象以先前已注册的对象实例的形式接收。
在服务器端,通过 AJAX 发送的对象由 l_DataReceivedEvent
处理程序接收。
private object l_DataReceivedEvent(object obj)
{
if (obj is Hashtable)
// check the type of the object sent from the client
{
return "Server: Update OK";
}
return "Return a string ";
// can be returned any registered object
}
如果使用的是标准 Postback,则使用 l_PostBackDataReceivedEvent
处理程序接收对象。
private void l_PostBackDataReceivedEvent(object obj)
{
Hashtable ht = (Hashtable)obj;
// all objects on the client are packed to hashtable when PostBack is used
ArrayList emps = (ArrayList)ht["MyEmployeesArr"];
Convertor.RegisterObject("MyEmployeesArr", emps);
}
数据类型
没有 JavaScript 表示形式的数据类型是完全无用的。例如,如果一个类有一个成员字段定义为 TimeSpan
,那么它就无法转换为 JavaScript。
支持的数据类型
int
char
bool
float
double
字符串
日期时间
ArrayList
哈希表
框架和 ASP.NET 组件
该框架与 ASP.NET 组件无关;它只是一个通用的、结构化的数据传递机制。但是,该框架对于这类组件的设计可能非常有用——它可以为组件提供结构化数据,并可以轻松地与组件框架集成。
在线演示
此处提供一个实时演示:RWC_Live。
版本
当前版本是 1.0.2。
致谢
为了获得更好的性能,该框架使用了 Eric Woodruff 的 JavaScript 压缩器。
如果发布了新版本,可以从 www.dotnetremoting.com 下载,以及其他有用的组件。