.net消费iSeries网络服务
我想用.Net来使用iseries web服务。我已经成功地与iSeries上的其他Web服务进行通信,但在这个特定的服务器上,我遇到了一个很奇怪的问题。.net消费iSeries网络服务
以下是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服务这里是请求/响应我看到在看提琴手时:
净请求
<?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>
净响应
<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服务时,我得到完全相同的结果:没有联系人。
任何帮助,微推,意见,或方向将不胜感激。我已经为此工作了两天,但我仍然不完全理解这里发生的事情。
非常感谢您的帮助。
谢谢。
所以大声说出来。
事实证明,iSeries开发人员是手解析请求。所以即使从SoapUI和.Net生成的请求在功能上是等效的,结构也是不同的。这在iSeries代码中没有正确处理。
我不是iSeries的专家,但我建议我们使用标准xml库(如果存在的话),以便iSeries正确解析xml请求。
谢谢,宝石指点我在正确的方向。
我已经开发了许多服务,在iSeries中公开和使用数据,我为此作业严重推荐Scott Klement HTTPAPI。试试吧,你不会后悔的。
我会看看。 – sloaniebaloney 2014-09-24 20:01:18
您是否调试过iSeries的一面,看看它认为它是作为请求接收的?听起来像问题在那里,而不是在你的要求。 – bvstone 2014-09-22 17:05:55
是的。在iSeries上工作的人已经调试了她的身边,并且她正在返回一个联系人,我可以使用SoapUI看到,但是当我从.Net使用它时不会看到。 – sloaniebaloney 2014-09-22 17:30:45
在iSeries上他们可以看到返回的数据是你期望的,但是实际返回的数据是不同的。 iSeries或者返回一个联系人。我会和他们一起坐下来仔细检查,而不是在任何一方“假设”。 – bvstone 2014-09-22 19:54:38