众所周知,web应用是一个比较“麻烦”的模式,既使数据可以正确的提交到服务器上(服务端操作),又要照顾到客户体验(客户端操作,如利用AJAX)。怎么能使数据提交到服务器上,而客户端又不需要刷新,还可以获得服务器端回传的消息,整个操作就好像是在客户端进行的一样?当然有办法,毕竟“只有想不到,没有做不到”嘛!
我开发的项目遇到的问题起初还真不是客户端和服务端数据交互的问题,而是客户端输入数据的临时存储的问题,客户端的数据在选择和录入后可以使用文件方式、cookie方式保存在客户机上,也可以随时提交保存在服务器上,或者保存在数据库的临时表中。但保存到服务器上的方法是需要耗费资源、可能造成操作延迟;保存在客户机文件中或使用cookie会有“数据隐藏”的风险,即并不能随时看到文件或cookie中的数据,可能会造成数据的不一致。虽然这些方法可以达到所需的目的,但它们的缺点会给项目造成可预知的严重影响,以及不可预知的后果。
遇到这个问题后,我没有立刻对这些方式进行实例开发和解决,而是请教其他同事帮我共同研究确定一个好的解决方法。
幸亏我就此和同事交流了一次,剑走偏锋,让我知道了一个更好的解决方法。
在此感谢我的同事王超,他告诉了我有这样一个方法,抛开了数据存储问题,而是把目标锁定在对客户端和服务器端数据交互上,不需要对数据进行存储就可以完全满足我的需要。
其实我们的技术水平不是差,而是有好多的资源我们不知道它们的存在。
进入正题:
我所开发的项目中有一个模块,有上下两个表,上面的表是从数据库中获取数据,然后选择将需要的数据“转移”到下面的表中。下面的表中不仅可以接收数据,而且可以在表中由使用者自行增加数据。原来的做法是将这些数据通过临时数据表或者服务器端的DataSet或DataTable作为临时存储的中间层进行数据保存、编辑,这样会反复的往返于客户端和服务器之间进行操作。
新的方法是,不对其进行特殊保存操作,而是数据仍旧留在客户端,每次对数据的操作是在客户端js脚本中用object对其进行保存,并使用js脚本将数据拼接成table表格的样式进行页面显示,对客户端的数据编辑完成(在我的项目中是选择数据,新增数据)后,调用服务端的方法对其进行最终的保存。这个流程中用到了两个知识点:一个是PageMethods,用于客户端调用服务端的方法;另一个JSON,用于客户端与服务端的数据传输。
PageMethods:
1、在客户端页面中加入控件<asp:ScriptManager ID="scriptManager" runat="server" EnablePageMethod="true"></asp:ScriptManager> (使用了FrameWork 3.5的AJAX控件,如果是FrameWork2.0的话可以单独安装)。这个控件为客户端与服务端的交互提供了支持。注意EnablePageMethod="true" 这个属性是必须的。
2、在服务端创建静态方法:
[System.Web.Services.WebMethod] // 这个属性也是必须的
public static String SaveInfo(ObjectInfo[] objInfo)
{
// 对objInfo类数组进行操作
... ...
return "服务端数据保存成功!";
}
3、在客户端编写JS脚本,调用服务端方法:
function OnSave() // 这个方法是按钮OnClick执行的方法
{
// objectArray是需要服务端SaveInfo方法的参数,即需要保存的类数组,Save是接收服务端方法的返回值并将其显示的方法。
PageMethods.SaveInfo(objectArray,Save);
}
function Save(result)
{
alert(result);
}
4、用JSON格式保存客户端和服务端的数据(此内容推荐学习一下JSON数据交换格式,在此不对JSON进行说明)
var obj = [{"Name":"张三","Code":1234653},{"Name":"李四","Code":98765424}]
这个obj就可以作为SaveInfo方法的参数进行传递了。
但是数据不是常量,而是变量,所以我们就需要“制作”这个类数组了。
js:
var arrObj; // 保存数据的字符串数组
var index; // 数组索引
var strObj;
index = arrObj.length;
// 这只是对数组的一个赋值操作,在真是的情况中需要循环。
arrObj[index] = "/Name/":/""+ nameValue +"/",/"Code/":"+ codeValue;
// 将数组转化为JSON信息格式
strObj="[";
for(i=0; i<arrObj.length; i++)
{
strObj += "{"+ arrObj[i] +"},";
}
strObj = strObj.substring(0,strObj.length-1);
strObj += "]";
var obj= eval(strObj); // 这就是制作好的类数组,它就是客户端与服务端进行传输的参数。
5、在服务端方法中,可以以objInfo[index].Name直接访问类属性。
因为项目要比上述的多很多,所以只能简化讲述。上面的代码在实际使用时也需要重新的整理和安排,在此仅希望可以对大家起到抛砖引玉的作业。