扫一扫
分享文章到微信
扫一扫
关注官方公众号
至顶头条
作者:builder.com.cn 来源:来源网站 2007年11月25日
关键字: WebService Atlas
在本页阅读全文(共19页)
近日拜读陈黎夫先生所著并发布在网上的《ASP.NET AJAX程序设计 第II卷:客户端Microsoft AJAX Library相关》的第三章《异步调用Web Service和页面中的类方法》(请参见陈先生博客http://www.cnblogs.com/dflying/archive/2007/06/12/780052.html),自己做了些实验以了解类型传递的原理,颇有些收获,现陈述如下,希望对ASP.NET AJAX的初学者有所帮助,并希望大家就其中不足多多给予指正。
using System;
using System.Web;
using System.Collections;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.Web.Script.Services;
public class Employee
...{
private int m_id;
public int Id
...{
get ...{ return m_id; }
set ...{ m_id = value; }
}
public string m_name;
public string Name
...{
get ...{ return "My name is " + m_name + "!"; }
set ...{ m_name = value; }
}
private string m_email;
public string Email
...{
get ...{ return m_email; }
set ...{ m_email = value; }
}
public int m_salary;
[System.Web.Script.Serialization.ScriptIgnore]
public int Salary
...{
get ...{ return m_salary; }
set ...{ m_salary = value; }
}
public Employee()
...{
;
}
public Employee(int id, string name, string email, int salary)
...{
m_id = id;
m_name = name;
m_email = email;
m_salary = salary;
}
}
[ScriptService]
[WebService(Namespace = "Delete.Ra")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[GenerateScriptType(typeof(Employee))]
public class WebService : System.Web.Services.WebService ...{

public WebService () ...{
//如果使用设计的组件,请取消注释以下行
//InitializeComponent();
}
[WebMethod]
public Employee CreateNewEmployee()
...{
//返回一个已声明了GenerateScriptType的类
return new Employee(0, string.Empty, string.Empty, 0);
}
[WebMethod]
public bool SaveEmployee(Employee em)
...{
// 保存到数据库中...
return true;
}
}注意:其中与原文程序在访问权限上有微妙的不同。
WebService.CreateNewEmployee(onSucceeded);
稍加整理,可以得到如下的流程图(图中断点的符号表示被运行的语句或语句段):
从SOAP中可以看出,
传给客户端的信息中只有<名,值>的有序偶,而并没有将涉及对象内部的关联。
那么是不是在页面加载的一开始,类的内部关系就已经拷贝到客户端了呢?

function Button4_onclick() ...{
WebService.CreateNewEmployee(onSucceeded);
}
function onSucceeded(result) ...{
debugger;
result.Name="Delete";
result.Email = "Delete.Ra@gmail.com";
result.m_name="Ra";
debugger;
}注意:m_name应该是Name的内涵,在本程序中同时修改了这两个东西会发生什么事呢?加入断点进行调试。
属性被修改前:
属性被修改后:
可以看出,在客户端m_name和Name并无联系,Name属性对于客户端来说与m_name是对等的,都是简单的<名,值>关系。至于本程序中矛盾地对二者进行赋值到了服务端会怎么样请见实验3.2。
结论:
1.服务端的类在客户端并无内在联系。
2.能够表示成简单的<名,值>关系的数据才能被传递。
所以类的方法为什么不能传递就很好解释了。
实验3.1.从客户端向服务端传递(客户端篇)
Step1.在客户端加入代码:

function pageLoad() ...{
var e = new Employee();
debugger;
e.Name = "Wo";
e.Email="Wp@abc.com";
e.SpecialMember = 123;
WebService.SaveEmployee(e);
}值得注意的是,SpecialMember成员并没有在类的定义中出现,这样能行吗?运行一下试试。
运行到debugger语句:
(对象里什么都没有……)
赋值完毕:
(对象里面什么都有了,包括不该有的也有了……没办法,这是JavaScript的特性嘛~)
那么,这一数据能否顺利调用服务端的存储方法呢?测试一下webService的SaveEmployee方法就知道了:
POST /AJAXFuturesEnabledWebSite4/WebService.asmx HTTP/1.1
Host: localhost
Content-Type: text/xml; charset=utf-8
Content-Length: length
SOAPAction: "Delete.Ra/SaveEmployee"
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<SaveEmployee xmlns="Delete.Ra">
<em>
<m_name>string</m_name>
<m_salary>int</m_salary>
<Id>int</Id>
<Name>string</Name>
<Email>string</Email>
<Salary>int</Salary>
</em>
</SaveEmployee>
</soap:Body>
</soap:Envelope>上传的数据中压根就没有其它人什么事,所以不用担心SpecialMember这种异类会入侵到老家去。
但是万一要是客户端的程序把正确的属性名打错了一个字字母,那就废了,值又传不过去(SOAP所限),又不报错(Javascript所限),死活查不出问题。
实验3.2.从客户端向服务端传递(服务端篇)
继续跟踪服务端存储过程,可以得到如下流程图:
还记得我们在实验2中做了一个奇怪的赋值吗?将作为内核的m_name先赋值,再给其外延Name属性赋不同的值,这样做在上传的SOAP中肯定没有问题,那里有它们两个的位置,但在服务端存储过程中它们这对水火不容的冤家会怎样呢?
刚刚调用完类的默认构造函数之后:
可以看到,在刚刚构建好一个空的对象之后,第一个属性的setter被调用前,m_name就已经有值了,该值是我们在客户端程序中直接给m_name赋的值。说明在这之间有一步(即图中步骤2),传递了同名成员变量的值。
调用完Name的setter之后:
属性值覆盖了成员变量的赋值。因此,我们知道在客户端的这种矛盾的赋值并不会引起什么大的异常,只是我们白赋了一个值,白传了一个参数,白白浪费了一点点带宽。
结论:如果WebService的类设计不当,让使用者既能操作成员变量又能操作包装该成员变量的属性,则很可能引起逻辑上的错误。
实验3.3.传递错误的对象
结果:程序运行到图中第5步,即调用WebService方法时,抛出类型异常,程序中止。
结论:白传了一组数据,服务端白跑了4步程序。
额外的结论:
客户端Javascript的松散,与服务端C#的严谨构成了一对矛盾,后台编写者必须为更加严谨地为前台提供松散的服务,否则客户端的胡乱使用会给网络和服务器造成不必要的负担。
一点问题:
不是说要传递复杂的类型就要加上[GenerateScriptType(typeof(Employee))]声明吗?为什么把该声明注释掉之后程序依然照常运行呢?
Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1901439
如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。