我正在尝试使用.Net来使用iseries Web服务。我已经成功地与iSeries上的其他Web服务进行通信,但是对于这个特定的服务,我有一个非常奇怪的问题。
以下是来自iSeries的Web服务的wsdl。
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<wsdl:definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:tns="http://example.com/ZCntInfFr/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="ZCntInfFr"
targetNamespace="http://example.com/ZCntInfFr/">
<wsdl:types>
<xsd:schema targetNamespace="http://example.com/ZCntInfFr/">
<xsd:element name="GetContactInfoOperation">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="ShipToAcct" minOccurs="1"
maxOccurs="1">
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:length value="6"></xsd:length>
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="GetContactInfoOperationResponse">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="Contacts"
type="tns:ContactsType" minOccurs="1" maxOccurs="1">
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:complexType name="ContactDataType">
<xsd:sequence maxOccurs="unbounded" minOccurs="0">
<xsd:element name="ContactType" minOccurs="0"
maxOccurs="1">
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:minLength value="0"></xsd:minLength>
<xsd:maxLength value="5"></xsd:maxLength>
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
<xsd:element name="ContactTypeDesc" minOccurs="0"
maxOccurs="1">
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:minLength value="0"></xsd:minLength>
<xsd:maxLength value="50"></xsd:maxLength>
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
<xsd:element name="ContactName" minOccurs="0"
maxOccurs="1">
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:minLength value="0"></xsd:minLength>
<xsd:maxLength value="25"></xsd:maxLength>
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
<xsd:element name="ContactTitle" minOccurs="0"
maxOccurs="1">
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:minLength value="0"></xsd:minLength>
<xsd:maxLength value="20"></xsd:maxLength>
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
<xsd:element name="ContactEmail" minOccurs="0"
maxOccurs="1">
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:minLength value="0"></xsd:minLength>
<xsd:maxLength value="128"></xsd:maxLength>
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
<xsd:element name="ContactPhone" minOccurs="0"
maxOccurs="1">
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:minLength value="0"></xsd:minLength>
<xsd:maxLength value="15"></xsd:maxLength>
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
<xsd:element name="ContactExtension" minOccurs="0"
maxOccurs="1">
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:minLength value="0"></xsd:minLength>
<xsd:maxLength value="5"></xsd:maxLength>
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
<xsd:element name="ContactFax" minOccurs="0" maxOccurs="1">
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:minLength value="0"></xsd:minLength>
<xsd:maxLength value="15"></xsd:maxLength>
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="ContactsType">
<xsd:sequence maxOccurs="unbounded" minOccurs="0">
<xsd:element name="ContactData" type="tns:ContactDataType" maxOccurs="1" minOccurs="0"></xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
</wsdl:types>
<wsdl:message name="GetContactInfoOperationRequest">
<wsdl:part name="parameters" element="tns:GetContactInfoOperation"></wsdl:part>
</wsdl:message>
<wsdl:message name="GetContactInfoOperationResponse">
<wsdl:part name="parameters" element="tns:GetContactInfoOperationResponse"></wsdl:part>
</wsdl:message>
<wsdl:portType name="ZCntInfFr">
<wsdl:operation name="GetContactInfoOperation">
<wsdl:input message="tns:GetContactInfoOperationRequest"></wsdl:input>
<wsdl:output message="tns:GetContactInfoOperationResponse"></wsdl:output>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="ZCntInfFrSOAP" type="tns:ZCntInfFr">
<soap:binding style="document"
transport="http://schemas.xmlsoap.org/soap/http" />
<wsdl:operation name="GetContactInfoOperation">
<soap:operation
soapAction="http://example.com/ZCntInfFr/GetContactInfoOperation" />
<wsdl:input>
<soap:body use="literal" />
</wsdl:input>
<wsdl:output>
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="ZCntInfFr">
<wsdl:port binding="tns:ZCntInfFrSOAP" name="ZCntInfFrSOAP">
<soap:address location="http://server:8181/myrxs/ZCntInfFr" />
</wsdl:port>
</wsdl:service>
当我在SoapUI中测试时,这是我收到的请求/响应:
SoapUI请求:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:zcn="http://example.com/ZCntInfFr/">
<soapenv:Header/>
<soapenv:Body>
<zcn:GetContactInfoOperation>
<ShipToAcct>099039</ShipToAcct>
</zcn:GetContactInfoOperation>
</soapenv:Body>
</soapenv:Envelope>
SoapUI响应:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:zcn="http://example.com/ZCntInfFr/">
<soapenv:Header/>
<soapenv:Body>
<zcn:GetContactInfoOperationResponse>
<Contacts>
<ContactData>
<ContactType>ADMIN</ContactType>
<ContactTypeDesc>Administrator</ContactTypeDesc>
<ContactName>Name</ContactName>
<ContactTitle/>
<ContactEmail>Email</ContactEmail>
<ContactPhone/>
<ContactExtension/>
<ContactFax/>
</ContactData>
</Contacts>
</zcn:GetContactInfoOperationResponse>
</soapenv:Body>
</soapenv:Envelope>
响应正是我所期待的。请注意我正在找回一个联系人,这是正确的。
当我从.Net调用iSeries Web服务时,这是我在看Fiddler时看到的请求/响应:
.Net请求
<?xml version="1.0" encoding="iso-8859-1"?><s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<GetContactInfoOperation xmlns="http://www.mysitye.com/ZCntInfFr/">
<ShipToAcct xmlns="">099039</ShipToAcct>
</GetContactInfoOperation>
</s:Body>
</s:Envelope>
.Net回复
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:zcn="http://example.com/ZCntInfFr/">
<soapenv:Header/>
<soapenv:Body>
<zcn:GetContactInfoOperationResponse>
<Contacts>
</Contacts>
</zcn:GetContactInfoOperationResponse>
</soapenv:Body>
</soapenv:Envelope>
在这种情况下,当我从.Net调用它时,我收到一个空节点。没有联系人。
为了完整性,这里是我使用以下命令从svcutil创建的代理类:
svcutil /n:*,Services.Web.Proxy.ISeriesContact /o:ContactProxy /s http://server:8181/ZCntInfFr.wsdl
类别:
namespace Services.Web.Proxy.ISeriesContact
{
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
[System.ServiceModel.ServiceContractAttribute(Namespace = "http://example.com/ZCntInfFr/", ConfigurationName = "Services.Web.Proxy.ISeriesContact.ZCntInfFr")]
public interface ZCntInfFr
{
// CODEGEN: Parameter 'Contacts' requires additional schema information that cannot be captured using the parameter mode. The specific attribute is 'System.Xml.Serialization.XmlElementAttribute'.
[System.ServiceModel.OperationContractAttribute(Action = "http://example.com/ZCntInfFr/GetContactInfoOperation", ReplyAction = "*")]
[System.ServiceModel.XmlSerializerFormatAttribute()]
[return: System.ServiceModel.MessageParameterAttribute(Name = "Contacts")]
Services.Web.Proxy.ISeriesContact.GetContactInfoOperationResponse GetContactInfoOperation(Services.Web.Proxy.ISeriesContact.GetContactInfoOperationRequest request);
[System.ServiceModel.OperationContractAttribute(Action = "http://example.com/ZCntInfFr/GetContactInfoOperation", ReplyAction = "*")]
System.Threading.Tasks.Task<Services.Web.Proxy.ISeriesContact.GetContactInfoOperationResponse> GetContactInfoOperationAsync(Services.Web.Proxy.ISeriesContact.GetContactInfoOperationRequest request);
}
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("svcutil", "4.0.30319.33440")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(Namespace = "http://example.com/ZCntInfFr/")]
public partial class ContactDataType
{
private string[] itemsField;
private ItemsChoiceType[] itemsElementNameField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("ContactEmail", typeof(string), Form = System.Xml.Schema.XmlSchemaForm.Unqualified, Order = 0)]
[System.Xml.Serialization.XmlElementAttribute("ContactExtension", typeof(string), Form = System.Xml.Schema.XmlSchemaForm.Unqualified, Order = 0)]
[System.Xml.Serialization.XmlElementAttribute("ContactFax", typeof(string), Form = System.Xml.Schema.XmlSchemaForm.Unqualified, Order = 0)]
[System.Xml.Serialization.XmlElementAttribute("ContactName", typeof(string), Form = System.Xml.Schema.XmlSchemaForm.Unqualified, Order = 0)]
[System.Xml.Serialization.XmlElementAttribute("ContactPhone", typeof(string), Form = System.Xml.Schema.XmlSchemaForm.Unqualified, Order = 0)]
[System.Xml.Serialization.XmlElementAttribute("ContactTitle", typeof(string), Form = System.Xml.Schema.XmlSchemaForm.Unqualified, Order = 0)]
[System.Xml.Serialization.XmlElementAttribute("ContactType", typeof(string), Form = System.Xml.Schema.XmlSchemaForm.Unqualified, Order = 0)]
[System.Xml.Serialization.XmlElementAttribute("ContactTypeDesc", typeof(string), Form = System.Xml.Schema.XmlSchemaForm.Unqualified, Order = 0)]
[System.Xml.Serialization.XmlChoiceIdentifierAttribute("ItemsElementName")]
public string[] Items
{
get
{
return this.itemsField;
}
set
{
this.itemsField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("ItemsElementName", Order = 1)]
[System.Xml.Serialization.XmlIgnoreAttribute()]
public ItemsChoiceType[] ItemsElementName
{
get
{
return this.itemsElementNameField;
}
set
{
this.itemsElementNameField = value;
}
}
}
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("svcutil", "4.0.30319.33440")]
[System.SerializableAttribute()]
[System.Xml.Serialization.XmlTypeAttribute(Namespace = "http://example.com/ZCntInfFr/", IncludeInSchema = false)]
public enum ItemsChoiceType
{
/// <remarks/>
[System.Xml.Serialization.XmlEnumAttribute(":ContactEmail")]
ContactEmail,
/// <remarks/>
[System.Xml.Serialization.XmlEnumAttribute(":ContactExtension")]
ContactExtension,
/// <remarks/>
[System.Xml.Serialization.XmlEnumAttribute(":ContactFax")]
ContactFax,
/// <remarks/>
[System.Xml.Serialization.XmlEnumAttribute(":ContactName")]
ContactName,
/// <remarks/>
[System.Xml.Serialization.XmlEnumAttribute(":ContactPhone")]
ContactPhone,
/// <remarks/>
[System.Xml.Serialization.XmlEnumAttribute(":ContactTitle")]
ContactTitle,
/// <remarks/>
[System.Xml.Serialization.XmlEnumAttribute(":ContactType")]
ContactType,
/// <remarks/>
[System.Xml.Serialization.XmlEnumAttribute(":ContactTypeDesc")]
ContactTypeDesc,
}
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("svcutil", "4.0.30319.33440")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(Namespace = "http://example.com/ZCntInfFr/")]
public partial class ContactsType
{
private ContactDataType[] contactDataField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("ContactData", Form = System.Xml.Schema.XmlSchemaForm.Unqualified, Order = 0)]
public ContactDataType[] ContactData
{
get
{
return this.contactDataField;
}
set
{
this.contactDataField = value;
}
}
}
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
[System.ServiceModel.MessageContractAttribute(WrapperName = "GetContactInfoOperation", WrapperNamespace = "http://example.com/ZCntInfFr/", IsWrapped = true)]
public partial class GetContactInfoOperationRequest
{
[System.ServiceModel.MessageBodyMemberAttribute(Namespace = "http://example.com/ZCntInfFr/", Order = 0)]
[System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified)]
public string ShipToAcct;
public GetContactInfoOperationRequest()
{
}
public GetContactInfoOperationRequest(string ShipToAcct)
{
this.ShipToAcct = ShipToAcct;
}
}
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
[System.ServiceModel.MessageContractAttribute(WrapperName = "GetContactInfoOperationResponse", WrapperNamespace = "http://example.com/ZCntInfFr/", IsWrapped = true)]
public partial class GetContactInfoOperationResponse
{
[System.ServiceModel.MessageBodyMemberAttribute(Namespace = "http://example.com/ZCntInfFr/", Order = 0)]
[System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified)]
public Services.Web.Proxy.ISeriesContact.ContactsType Contacts;
public GetContactInfoOperationResponse()
{
}
public GetContactInfoOperationResponse(Services.Web.Proxy.ISeriesContact.ContactsType Contacts)
{
this.Contacts = Contacts;
}
}
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
public interface ZCntInfFrChannel : Services.Web.Proxy.ISeriesContact.ZCntInfFr, System.ServiceModel.IClientChannel
{
}
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
public partial class ZCntInfFrClient : System.ServiceModel.ClientBase<Services.Web.Proxy.ISeriesContact.ZCntInfFr>, Services.Web.Proxy.ISeriesContact.ZCntInfFr
{
public ZCntInfFrClient()
{
}
public ZCntInfFrClient(string endpointConfigurationName) :
base(endpointConfigurationName)
{
}
public ZCntInfFrClient(string endpointConfigurationName, string remoteAddress) :
base(endpointConfigurationName, remoteAddress)
{
}
public ZCntInfFrClient(string endpointConfigurationName, System.ServiceModel.EndpointAddress remoteAddress) :
base(endpointConfigurationName, remoteAddress)
{
}
public ZCntInfFrClient(System.ServiceModel.Channels.Binding binding, System.ServiceModel.EndpointAddress remoteAddress) :
base(binding, remoteAddress)
{
}
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
Services.Web.Proxy.ISeriesContact.GetContactInfoOperationResponse Services.Web.Proxy.ISeriesContact.ZCntInfFr.GetContactInfoOperation(Services.Web.Proxy.ISeriesContact.GetContactInfoOperationRequest request)
{
return base.Channel.GetContactInfoOperation(request);
}
public Services.Web.Proxy.ISeriesContact.ContactsType GetContactInfoOperation(string ShipToAcct)
{
Services.Web.Proxy.ISeriesContact.GetContactInfoOperationRequest inValue = new Services.Web.Proxy.ISeriesContact.GetContactInfoOperationRequest();
inValue.ShipToAcct = ShipToAcct;
Services.Web.Proxy.ISeriesContact.GetContactInfoOperationResponse retVal = ((Services.Web.Proxy.ISeriesContact.ZCntInfFr)(this)).GetContactInfoOperation(inValue);
return retVal.Contacts;
}
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
System.Threading.Tasks.Task<Services.Web.Proxy.ISeriesContact.GetContactInfoOperationResponse> Services.Web.Proxy.ISeriesContact.ZCntInfFr.GetContactInfoOperationAsync(Services.Web.Proxy.ISeriesContact.GetContactInfoOperationRequest request)
{
return base.Channel.GetContactInfoOperationAsync(request);
}
public System.Threading.Tasks.Task<Services.Web.Proxy.ISeriesContact.GetContactInfoOperationResponse> GetContactInfoOperationAsync(string ShipToAcct)
{
Services.Web.Proxy.ISeriesContact.GetContactInfoOperationRequest inValue = new Services.Web.Proxy.ISeriesContact.GetContactInfoOperationRequest();
inValue.ShipToAcct = ShipToAcct;
return ((Services.Web.Proxy.ISeriesContact.ZCntInfFr)(this)).GetContactInfoOperationAsync(inValue);
}
}
}
我已经启用了WCF跟踪,并且在.svclog文件中没有任何内容。我一直在疯狂搜索,并且已经看到在WSDL中可能存在一些与minOccurs有关的问题。我的想法是,它可能与.Net中的反序列化过程有关。
作为附注和练习,我能够使用WebClient对象调用SOAP服务,并使用其中的联系人检索正确的原始XML。这也让我想到了反序列化正在发生的事情。
我还尝试使用wsdl.exe生成代理,但我仍然返回一个空的客户端节点。
我应该提到的另一件事是,当我在项目中将对iSeries Web服务的引用添加到服务引用时,我得到完全相同的结果:没有联系人。
任何帮助,推动,建议或指示都将不胜感激。我已经在这方面工作了两天,我仍然没有完全理解这里发生了什么。
非常感谢您的帮助。
感谢。
答案 0 :(得分:1)
所以对bvstone大喊大叫。
事实证明,iSeries开发人员正在手动解析请求。因此,尽管SoapUI和.Net的请求生成功能相同,但结构却不同。在iSeries代码中无法正确处理。
我不是iSeries的专家,但我建议我们使用标准的xml库,如果它们存在,iSeries正确地解析xml请求。
谢谢,bvstone指出我正确的方向。
答案 1 :(得分:0)
我开发了许多在iSeries中公开和使用数据的服务,我认真推荐Scott Klement HTTPAPI来完成这项工作。试一试,你不会后悔。