.Net使用iSeries Web服务

时间:2014-09-22 16:18:03

标签: .net wcf soapui fiddler ibm-midrange

我正在尝试使用.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服务的引用添加到服务引用时,我得到完全相同的结果:没有联系人。

任何帮助,推动,建议或指示都将不胜感激。我已经在这方面工作了两天,我仍然没有完全理解这里发生了什么。

非常感谢您的帮助。

感谢。

2 个答案:

答案 0 :(得分:1)

所以对bvstone大喊大叫。

事实证明,iSeries开发人员正在手动解析请求。因此,尽管SoapUI和.Net的请求生成功能相同,但结构却不同。在iSeries代码中无法正确处理。

我不是iSeries的专家,但我建议我们使用标准的xml库,如果它们存在,iSeries正确地解析xml请求。

谢谢,bvstone指出我正确的方向。

答案 1 :(得分:0)

我开发了许多在iSeries中公开和使用数据的服务,我认真推荐Scott Klement HTTPAPI来完成这项工作。试一试,你不会后悔。