关于SOAPpy传递对象参数调用WebService的问题总结
2008-12-01 00:37 Jaypei 阅读(5422) 评论(6) 编辑 收藏 举报第一次使用SOAPpy传递对象,谁知遇到了好多麻烦的问题,于是网上搜啊搜,找到了CPyUG中qgg的一篇“使用SOAPpy的体会”,借鉴了一些经验,得到一些启发,感谢qgg。
以SOAPpy调用.net写的WebService为例。
UserInfo.py{
protected string _userName;
protected string _password;
protected DateTime _birthday;
protected int _salary;
public string UserName
{
get { return this._userName; }
set { this._userName = value; }
}
public string Password
{
get { return this._password; }
set { this._password = value; }
}
public DateTime Birthday
{
get { return this._birthday; }
set { this._birthday = value; }
}
public int Salary
{
get { return this._salary; }
set { this._salary = value; }
}
}
public class UserService : System.Web.Services.WebService {
…
[WebMethod]
public string Register(UserInfo user)
{
string result = string.Format("Result : (UserName: {0}, Password: {1}, Birthday: {2}, Salary: {3})",
user.UserName, user.Password, user.Birthday.ToString("yyyy-MM-dd HH:mm:ss"), user.Salary.ToString());
return result;
}
…
描述格式如下:
Host: localhost
Content-Type: text/xml; charset=utf-8
Content-Length: length
SOAPAction: "http://testwebservice.localhost/Register"
<?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>
<Register xmlns="http://testwebservice.localhost/">
<user>
<UserName>string</UserName>
<Password>string</Password>
<Birthday>dateTime</Birthday>
<Salary>int</Salary>
</user>
</Register>
</soap:Body>
</soap:Envelope>
在构建对象时,刚开始我简单的这么想的:
pass
...
u = UserInfo()
u.UserName = "jaypei"
u.Password = "*************"
u.Birthday = SOAPpy.dateTimeType((2008,1,1,0,0,0))
u.Salary = 10
<SOAP-ENV:Envelope
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance"
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/1999/XMLSchema">
<SOAP-ENV:Body>
<ns1:Register xmlns:ns1="http://testwebservice.localhost/" SOAP-ENC:root="1">
<user xsi:type="xsd:UserInfo"><__main__.UserInfo object at 0x00D8C190></user>
</ns1:Register>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
看来需要实现__str__函数,但是这么做在逻辑层牵扯到SOAP的传递格式了,显然不会是它本意。
于是看Demo里面发现了SOAPpy.types。于是,模仿demo改了一下程序:
u._addItem('UserName', 'jaypei')
u._addItem('Password', '************')
u._addItem('Birthday', SOAPpy.dateTimeType((2008,1,1,0,0,0)))
u._addItem('Salary', 10)
<SOAP-ENV:Envelope
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance"
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd3="http://www.w3.org/2001/XMLSchema"
xmlns:xsd="http://www.w3.org/1999/XMLSchema">
<SOAP-ENV:Body>
<ns1:Register xmlns:ns1="http://testwebservice.localhost/" SOAP-ENC:root="1">
<xsd:user>
<UserName xsi:type="xsd:string">jaypei</UserName>
<Password xsi:type="xsd:string">************</Password>
<Birthday xsi:type="xsd3:dateTime">2008-01-01T00:00:00Z</Birthday>
<Salary xsi:type="xsd:int">10</Salary>
</xsd:user>
</ns1:Register>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
还是报类型错误。于是仔细研究格式上的不同。
首先是user的命名空间不同,描述中的user是没有指定命名空间的,说明是默认命名空间,读了一下types.py的代码,发现anyType是类型的基类,刚刚用到的structType的继承关系是anyType - compoundType – structType,再往下又发现了一个bodyType,于是想到UserInfo应该继承自bodyType才对。在anyType的__init__中有一个成员_validURIs,默认赋了(NS.XSD, NS.XSD2, NS.XSD3, NS.ENC),但是从代码中只看到用了_validURIs[0]。
于是UserInfo写成:
_validURIs = ("http://testwebservice.localhost/", )
user的命名空间问题解决了,又请求发现还是格式不对,困惑了好半天忽然想到可能是参数的命名空间的问题,于是又翻查代码想看看参数的命名空间如何加。不知是没有这接口还是我没找到,我就想了一个不是很漂亮的解决方法,就是注册Item的时候直接把命名空间写上(如果有谁知道的话请留言告诉我)。。
至此,终于搞定了,SOAPpy代码虽没细看但结构也看的差不多了 :)
调用代码如下:
import SOAPpy
class UserInfo(SOAPpy.bodyType):
_validURIs = ("http://testwebservice.localhost/", )
def main():
proxy = WSDL.Proxy('http://localhost:xxxx/UserService.asmx?WSDL')
#proxy.soapproxy.config.dumpSOAPOut = 1
#proxy.soapproxy.config.dumpSOAPIn = 1
proxy.methods['Register'].namespace = ("nsl", "http://testwebservice.localhost/")
u = UserInfo()
u._addItem("nsl:UserName", "jaypei")
u._addItem("nsl:Password", "*************")
u._addItem("nsl:Birthday", SOAPpy.dateTimeType((2008,1,1,0,0,0)))
u._addItem("nsl:Salary", 10)
proxy.Register(user=u)