使用服务引用/ WCF在.NET中使用SOAP API。消息格式不正确

时间:2016-04-23 00:51:53

标签: asp.net wcf soap wsdl service-reference

我正在尝试使用我们的某个供应商提供的WSDL来使用SOAP 1.2 API。我尽可能简化了WSDL,只做了一个动作。我遇到的问题是WCF为SOAP请求消息生成的格式与供应商期望的格式或SoapUI生成的格式不匹配。具体而言,信封不包含xmlns:ser="http://some.random.api.here.com/"getDeviceList操作不包含ser:

我收到的错误是:

  

System.ServiceModel.FaultException:Unmarshalling Error:   cvc-complex-type.2.4.a:找到无效的内容   元素'userName'。 '{userName,password,clientId,   locationId}'是预期的。

据我所知,根据一些研究,这个错误只是意味着肥皂体没有正确格式化,或者服务器需要。

SoapUI生成的请求按预期工作,但.NET不会。我尝试使用Web服务,但我得到了相同的结果。我正在考虑按照here手动更改消息,但似乎WCF应该能够处理这个问题。 WSDL似乎有效,除了不导入安全策略部分外,Svcutil不会抛出任何错误。

我遇到的另一个更小的问题是,即使WSDL将属性username,password,clientid和locationid指定为minoccurs = 0,它们仍然是生成的代理类所要求的。我想找到解决这个问题的方法,但是在我至少得到一些工作之后我可以继续努力。

我已经尝试了多种类型的绑定,如here所述:basicHttpBinding,因为它们也有Soap 1.1服务,WsHttpBinding,以及使用多种设置组合的自定义绑定,但似乎没有任何区别消息的格式。

如果有人对如何设置SOAP消息的格式有任何想法或告诉.NET包含正确的命名空间,我将永远感激,因为我只是出于想法。

SoapUI请求:

POST https://a.randomapi.com/api/ApiService12 HTTP/1.1
Accept-Encoding: gzip,deflate
Content-Type: application/soap+xml;charset=UTF-8
Content-Length: 386
Host: a.randomapi.com
Connection: Keep-Alive
User-Agent: Apache-HttpClient/4.5.1 (Java/1.8.0_74)

<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:ser="http://some.random.api.here.com/">
   <soap:Header/>
   <soap:Body>
      <ser:getDeviceList>
         <!--Optional:-->
         <userName>username</userName>
         <!--Optional:-->
         <password>password</password>
      </ser:getDeviceList>
   </soap:Body>
</soap:Envelope>

.NET请求(使用Fiddler捕获):

POST https://a.randomapi.com/api/ApiService12 HTTP/1.1
Content-Type: application/soap+xml; charset=utf-8; action=""
Host: a.randomapi.com
Content-Length: 645
Expect: 100-continue
Accept-Encoding: gzip, deflate

<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope">
<s:Header>
</s:Header>
<s:Body xmlns:xsi=http://www.w3.org/2001/XMLSchema-instance xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<getDeviceList xmlns="http://some.random.api.here.com/">
<userName xmlns="">username</userName>
<password xmlns="">password</password>
<clientId xmlns="">0</clientId>
<locationId xmlns="">0</locationId>
</getDeviceList>
</s:Body>
</s:Envelope>

WSDL:

<?xml version='1.0' encoding='UTF-8'?><wsdl:definitions xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:tns="http://some.random.api.here.com/" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:ns1="http://schemas.xmlsoap.org/soap/http" name="ApiServiceImplService" targetNamespace="http://some.random.api.here.com/">
  <wsdl:types>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xmime="http://www.w3.org/2005/05/xmlmime" xmlns:tns="http://some.random.api.here.com/" attributeFormDefault="unqualified" elementFormDefault="unqualified" targetNamespace="http://some.random.api.here.com/">
  <xs:import namespace="http://www.w3.org/2005/05/xmlmime"/>

  <xs:element name="faultInfo">
    <xs:complexType>
      <xs:sequence>
        <xs:element minOccurs="0" name="faultCode" type="xs:string"/>
        <xs:element minOccurs="0" name="reason" type="xs:string"/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
  <xs:element name="getDeviceList" type="tns:getDeviceList"/>
  <xs:element name="getDeviceListResponse" type="tns:getDeviceListResponse"/>
  <xs:complexType name="getDeviceList">
    <xs:sequence>
      <xs:element minOccurs="0" name="userName" type="xs:string"/>
      <xs:element minOccurs="0" name="password" type="xs:string"/>
      <xs:element minOccurs="0" name="clientId" type="xs:long"/>
      <xs:element minOccurs="0" name="locationId" type="xs:long"/>
    </xs:sequence>
  </xs:complexType>
  <xs:complexType name="getDeviceListResponse">
    <xs:sequence>
      <xs:element maxOccurs="unbounded" minOccurs="0" name="device" type="tns:deviceInfo"/>
    </xs:sequence>
  </xs:complexType>
  <xs:complexType name="deviceInfo">
    <xs:sequence>
      <xs:element minOccurs="0" name="client" type="tns:provInfo"/>
      <xs:element minOccurs="0" name="deviceAlias" type="xs:string"/>
      <xs:element minOccurs="0" name="deviceId" type="xs:long"/>
      <xs:element minOccurs="0" name="deviceIp" type="xs:string"/>
      <xs:element minOccurs="0" name="deviceName" type="xs:string"/>
      <xs:element minOccurs="0" name="location" type="tns:provInfo"/>
    </xs:sequence>
  </xs:complexType>
  <xs:complexType name="provInfo">
<xs:sequence>
<xs:element name="id" type="xs:long"/>
<xs:element minOccurs="0" name="name" type="xs:string"/>
</xs:sequence>
</xs:complexType>
  <xs:element name="ApiWebFaultException" nillable="true"/> 
</xs:schema>
  </wsdl:types>
  <wsdl:message name="ApiWebFaultException">
  <wsdl:part element="tns:ApiWebFaultException" name="ApiWebFaultException"></wsdl:part>
    </wsdl:message>
  <wsdl:message name="getDeviceList">
    <wsdl:part element="tns:getDeviceList" name="parameters">
    </wsdl:part>
  </wsdl:message>
  <wsdl:message name="getDeviceListResponse">
    <wsdl:part element="tns:getDeviceListResponse" name="parameters">
    </wsdl:part>
  </wsdl:message>
  <wsdl:portType name="ApiService">
    <wsdl:operation name="getDeviceList">
      <wsdl:input message="tns:getDeviceList" name="getDeviceList">
    </wsdl:input>
      <wsdl:output message="tns:getDeviceListResponse" name="getDeviceListResponse">
    </wsdl:output>
      <wsdl:fault message="tns:ApiWebFaultException" name="ApiWebFaultException">
    </wsdl:fault>
    </wsdl:operation>
  </wsdl:portType>
  <wsdl:binding name="ApiServiceImplServiceSoapBinding" type="tns:ApiService">
    <soap12:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
    <wsp:PolicyReference URI="#UsernameTokenPolicy"/>
    <wsdl:operation name="getDeviceList">
      <soap12:operation soapAction="" style="document"/>
      <wsdl:input name="getDeviceList">
        <soap12:body use="literal"/>
      </wsdl:input>
      <wsdl:output name="getDeviceListResponse">
        <soap12:body use="literal"/>
      </wsdl:output>
      <wsdl:fault name="ApiWebFaultException">
        <soap12:fault name="ApiWebFaultException" use="literal"/>
      </wsdl:fault>
    </wsdl:operation>
  </wsdl:binding>
  <wsdl:service name="ApiServiceImplService">
    <wsdl:port binding="tns:ApiServiceImplServiceSoapBinding" name="ApiServiceImplPort">
      <soap12:address location="https://a.randomapi.com/api/ApiService12"/>
    </wsdl:port>
  </wsdl:service>
    <wsp:Policy xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy" wsu:Id="UsernameTokenPolicy">
    <wsp:ExactlyOne>
        <wsp:All>
            <sp:TransportBinding xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702">
                <wsp:Policy>
                    <sp:TransportToken>
                        <wsp:Policy>
                            <sp:HttpsToken/>
                        </wsp:Policy>
                    </sp:TransportToken>
                    <sp:AlgorithmSuite>
                        <wsp:Policy>
                            <sp:Basic256/>
                        </wsp:Policy>
                    </sp:AlgorithmSuite>
                </wsp:Policy>
            </sp:TransportBinding>
            <sp:SupportingTokens xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702">
                <wsp:Policy>
                    <sp:UsernameToken sp:IncludeToken="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702/IncludeToken/AlwaysToRecipient">
                        <wsp:Policy>
                            <sp:WssUsernameToken11/>
                        </wsp:Policy>
                    </sp:UsernameToken>
                </wsp:Policy>
            </sp:SupportingTokens>
        </wsp:All>
    </wsp:ExactlyOne>
</wsp:Policy>
</wsdl:definitions>

生成的代码:

[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "4.6.1067.0")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(Namespace="http://some.random.api.here.com/")]
public partial class getDeviceList : object, System.ComponentModel.INotifyPropertyChanged {

    private string userNameField;

    private string passwordField;

    private long clientIdField;

    private bool clientIdFieldSpecified;

    private long locationIdField;

    private bool locationIdFieldSpecified;

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=0)]
    public string userName {
        get {
            return this.userNameField;
        }
        set {
            this.userNameField = value;
            this.RaisePropertyChanged("userName");
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=1)]
    public string password {
        get {
            return this.passwordField;
        }
        set {
            this.passwordField = value;
            this.RaisePropertyChanged("password");
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=2)]
    public long clientId {
        get {
            return this.clientIdField;
        }
        set {
            this.clientIdField = value;
            this.RaisePropertyChanged("clientId");
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlIgnoreAttribute()]
    public bool clientIdSpecified {
        get {
            return this.clientIdFieldSpecified;
        }
        set {
            this.clientIdFieldSpecified = value;
            this.RaisePropertyChanged("clientIdSpecified");
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=3)]
    public long locationId {
        get {
            return this.locationIdField;
        }
        set {
            this.locationIdField = value;
            this.RaisePropertyChanged("locationId");
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlIgnoreAttribute()]
    public bool locationIdSpecified {
        get {
            return this.locationIdFieldSpecified;
        }
        set {
            this.locationIdFieldSpecified = value;
            this.RaisePropertyChanged("locationIdSpecified");
        }
    }

    public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;

    protected void RaisePropertyChanged(string propertyName) {
        System.ComponentModel.PropertyChangedEventHandler propertyChanged = this.PropertyChanged;
        if ((propertyChanged != null)) {
            propertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName));
        }
    }
}

/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "4.6.1067.0")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(Namespace="http://some.random.api.here.com/")]
public partial class provInfo : object, System.ComponentModel.INotifyPropertyChanged {

    private long idField;

    private string nameField;

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=0)]
    public long id {
        get {
            return this.idField;
        }
        set {
            this.idField = value;
            this.RaisePropertyChanged("id");
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=1)]
    public string name {
        get {
            return this.nameField;
        }
        set {
            this.nameField = value;
            this.RaisePropertyChanged("name");
        }
    }

    public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;

    protected void RaisePropertyChanged(string propertyName) {
        System.ComponentModel.PropertyChangedEventHandler propertyChanged = this.PropertyChanged;
        if ((propertyChanged != null)) {
            propertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName));
        }
    }
}

/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "4.6.1067.0")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(Namespace="http://some.random.api.here.com/")]
public partial class deviceInfo : object, System.ComponentModel.INotifyPropertyChanged {

    private provInfo clientField;

    private string deviceAliasField;

    private long deviceIdField;

    private bool deviceIdFieldSpecified;

    private string deviceIpField;

    private string deviceNameField;

    private provInfo locationField;

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=0)]
    public provInfo client {
        get {
            return this.clientField;
        }
        set {
            this.clientField = value;
            this.RaisePropertyChanged("client");
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=1)]
    public string deviceAlias {
        get {
            return this.deviceAliasField;
        }
        set {
            this.deviceAliasField = value;
            this.RaisePropertyChanged("deviceAlias");
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=2)]
    public long deviceId {
        get {
            return this.deviceIdField;
        }
        set {
            this.deviceIdField = value;
            this.RaisePropertyChanged("deviceId");
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlIgnoreAttribute()]
    public bool deviceIdSpecified {
        get {
            return this.deviceIdFieldSpecified;
        }
        set {
            this.deviceIdFieldSpecified = value;
            this.RaisePropertyChanged("deviceIdSpecified");
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=3)]
    public string deviceIp {
        get {
            return this.deviceIpField;
        }
        set {
            this.deviceIpField = value;
            this.RaisePropertyChanged("deviceIp");
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=4)]
    public string deviceName {
        get {
            return this.deviceNameField;
        }
        set {
            this.deviceNameField = value;
            this.RaisePropertyChanged("deviceName");
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=5)]
    public provInfo location {
        get {
            return this.locationField;
        }
        set {
            this.locationField = value;
            this.RaisePropertyChanged("location");
        }
    }

    public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;

    protected void RaisePropertyChanged(string propertyName) {
        System.ComponentModel.PropertyChangedEventHandler propertyChanged = this.PropertyChanged;
        if ((propertyChanged != null)) {
            propertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName));
        }
    }
}

[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
[System.ServiceModel.ServiceContractAttribute(Namespace="http://some.random.api.here.com/", ConfigurationName="ServiceReference5.ApiService")]
public interface ApiService {

    [System.ServiceModel.OperationContractAttribute(Action="", ReplyAction="*")]
    [System.ServiceModel.FaultContractAttribute(typeof(object), Action="", Name="ApiWebFaultException")]
    [System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults=true)]
    [System.ServiceModel.ServiceKnownTypeAttribute(typeof(getDeviceList))]
    WebApplication1.ServiceReference5.getDeviceListResponse getDeviceList(WebApplication1.ServiceReference5.getDeviceList1 request);

    [System.ServiceModel.OperationContractAttribute(Action="", ReplyAction="*")]
    System.Threading.Tasks.Task<WebApplication1.ServiceReference5.getDeviceListResponse> getDeviceListAsync(WebApplication1.ServiceReference5.getDeviceList1 request);
}

[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
[System.ServiceModel.MessageContractAttribute(WrapperName="getDeviceList", WrapperNamespace="http://some.random.api.here.com/", IsWrapped=true)]
public partial class getDeviceList1 {

    [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://some.random.api.here.com/", Order=0)]
    [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
    public string userName;

    [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://some.random.api.here.com/", Order=1)]
    [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
    public string password;

    [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://some.random.api.here.com/", Order=2)]
    [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
    public long clientId;

    [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://some.random.api.here.com/", Order=3)]
    [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
    public long locationId;

    public getDeviceList1() {
    }

    public getDeviceList1(string userName, string password, long clientId, long locationId) {
        this.userName = userName;
        this.password = password;
        this.clientId = clientId;
        this.locationId = locationId;
    }
}

[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
[System.ServiceModel.MessageContractAttribute(WrapperName="getDeviceListResponse", WrapperNamespace="http://some.random.api.here.com/", IsWrapped=true)]
public partial class getDeviceListResponse {

    [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://some.random.api.here.com/", Order=0)]
    [System.Xml.Serialization.XmlElementAttribute("device", Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
    public WebApplication1.ServiceReference5.deviceInfo[] device;

    public getDeviceListResponse() {
    }

    public getDeviceListResponse(WebApplication1.ServiceReference5.deviceInfo[] device) {
        this.device = device;
    }
}

[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
public interface ApiServiceChannel : WebApplication1.ServiceReference5.ApiService, System.ServiceModel.IClientChannel {
}

[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
public partial class ApiServiceClient : System.ServiceModel.ClientBase<WebApplication1.ServiceReference5.ApiService>, WebApplication1.ServiceReference5.ApiService {

    public ApiServiceClient() {
    }

    public ApiServiceClient(string endpointConfigurationName) : 
            base(endpointConfigurationName) {
    }

    public ApiServiceClient(string endpointConfigurationName, string remoteAddress) : 
            base(endpointConfigurationName, remoteAddress) {
    }

    public ApiServiceClient(string endpointConfigurationName, System.ServiceModel.EndpointAddress remoteAddress) : 
            base(endpointConfigurationName, remoteAddress) {
    }

    public ApiServiceClient(System.ServiceModel.Channels.Binding binding, System.ServiceModel.EndpointAddress remoteAddress) : 
            base(binding, remoteAddress) {
    }

    public WebApplication1.ServiceReference5.getDeviceListResponse getDeviceList(WebApplication1.ServiceReference5.getDeviceList1 request) {
        return base.Channel.getDeviceList(request);
    }

    public System.Threading.Tasks.Task<WebApplication1.ServiceReference5.getDeviceListResponse> getDeviceListAsync(WebApplication1.ServiceReference5.getDeviceList1 request) {
        return base.Channel.getDeviceListAsync(request);
    }
}

调用API的代码:             var client = new ServiceReference5.ApiServiceClient();

        var request = new ServiceReference5.getDeviceList1();

        request.userName = "username";
        request.password = "password";

        var response = client.getDeviceList(request);

结合/终点:

<endpoint address="https://a.randomapi.com/api/ApiService12"
        binding="customBinding" bindingConfiguration="ApiServiceImplServiceSoapBinding1"
        contract="ServiceReference5.ApiService" name="ApiServiceImplPort1" />

<customBinding>
                <binding name="ApiServiceImplServiceSoapBinding1">
          <!--    WsdlImporter encountered unrecognized policy assertions in ServiceDescription 'http://some.random.api.here.com/':    -->
          <!--    <wsdl:binding name='ApiServiceImplServiceSoapBinding'>    -->
          <!--        <sp:SupportingTokens xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702">..</sp:SupportingTokens>    -->
          <textMessageEncoding messageVersion="Soap12" />
          <httpsTransport />
        </binding>
</customBinding>

0 个答案:

没有答案