使用XmlSerializerFormat

时间:2017-05-11 19:49:13

标签: c# wcf soap xml-serialization

我正在使用旧的soap服务基于WSDL编写WCF服务。我使用svcutil生成服务合同并进行了一些更改以匹配我托管它的网站,但是当我从测试客户端调用服务时,请求对象将以null形式出现。

服务返回的响应也被错误地序列化,我确信这是相关的。但我无法弄清楚为什么它没有正确序列化和反序列化。

这是服务合同:

[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
[System.ServiceModel.ServiceContractAttribute(Namespace = ApuConstants.Namespace)]
public interface IApuService
{
    [System.ServiceModel.OperationContractAttribute(Action = "*", ReplyAction = "*")]
    [System.ServiceModel.XmlSerializerFormatAttribute(Style = System.ServiceModel.OperationFormatStyle.Rpc, Use = System.ServiceModel.OperationFormatUse.Encoded)]
    [System.ServiceModel.ServiceKnownTypeAttribute(typeof(Part))]
    [return: System.ServiceModel.MessageParameterAttribute(Name = "return")]
    Brock.Web.Apu.Response check(Brock.Web.Apu.Request request);
}

/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("svcutil", "4.0.30319.33440")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.SoapTypeAttribute(Namespace = ApuConstants.Namespace)]
public partial class Request
{

    private RequestHeader headerField;

    private Lookup lookupField;

    /// <remarks/>
    public RequestHeader header
    {
        get
        {
            return this.headerField;
        }
        set
        {
            this.headerField = value;
        }
    }

    /// <remarks/>
    public Lookup lookup
    {
        get
        {
            return this.lookupField;
        }
        set
        {
            this.lookupField = value;
        }
    }
}

/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("svcutil", "4.0.30319.33440")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.SoapTypeAttribute(Namespace = ApuConstants.Namespace)]
public partial class RequestHeader
{

    private string accountField;

    private string idField;

    /// <remarks/>
    public string account
    {
        get
        {
            return this.accountField;
        }
        set
        {
            this.accountField = value;
        }
    }

    /// <remarks/>
    public string id
    {
        get
        {
            return this.idField;
        }
        set
        {
            this.idField = value;
        }
    }
}

/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("svcutil", "4.0.30319.33440")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.SoapTypeAttribute(Namespace = ApuConstants.Namespace)]
public partial class Part
{

    private string oemField;

    private string hicField;

    private string skuField;

    private string descField;

    private int daysField;

    private string availField;

    private string branchField;

    private float listField;

    private float netField;

    private string typeField;

    private string certField;

    private string statusField;

    /// <remarks/>
    public string oem
    {
        get
        {
            return this.oemField;
        }
        set
        {
            this.oemField = value;
        }
    }

    /// <remarks/>
    public string hic
    {
        get
        {
            return this.hicField;
        }
        set
        {
            this.hicField = value;
        }
    }

    /// <remarks/>
    public string sku
    {
        get
        {
            return this.skuField;
        }
        set
        {
            this.skuField = value;
        }
    }

    /// <remarks/>
    public string desc
    {
        get
        {
            return this.descField;
        }
        set
        {
            this.descField = value;
        }
    }

    /// <remarks/>
    public int days
    {
        get
        {
            return this.daysField;
        }
        set
        {
            this.daysField = value;
        }
    }

    /// <remarks/>
    public string avail
    {
        get
        {
            return this.availField;
        }
        set
        {
            this.availField = value;
        }
    }

    /// <remarks/>
    public string branch
    {
        get
        {
            return this.branchField;
        }
        set
        {
            this.branchField = value;
        }
    }

    /// <remarks/>
    public float list
    {
        get
        {
            return this.listField;
        }
        set
        {
            this.listField = value;
        }
    }

    /// <remarks/>
    public float net
    {
        get
        {
            return this.netField;
        }
        set
        {
            this.netField = value;
        }
    }

    /// <remarks/>
    public string type
    {
        get
        {
            return this.typeField;
        }
        set
        {
            this.typeField = value;
        }
    }

    /// <remarks/>
    public string cert
    {
        get
        {
            return this.certField;
        }
        set
        {
            this.certField = value;
        }
    }

    /// <remarks/>
    public string status
    {
        get
        {
            return this.statusField;
        }
        set
        {
            this.statusField = value;
        }
    }
}

/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("svcutil", "4.0.30319.33440")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.SoapTypeAttribute(Namespace = ApuConstants.Namespace)]
public partial class ResponseHeader
{

    private string statusField;

    private string reasonField;

    private string accountField;

    private string idField;

    /// <remarks/>
    public string status
    {
        get
        {
            return this.statusField;
        }
        set
        {
            this.statusField = value;
        }
    }

    /// <remarks/>
    public string reason
    {
        get
        {
            return this.reasonField;
        }
        set
        {
            this.reasonField = value;
        }
    }

    /// <remarks/>
    public string account
    {
        get
        {
            return this.accountField;
        }
        set
        {
            this.accountField = value;
        }
    }

    /// <remarks/>
    public string id
    {
        get
        {
            return this.idField;
        }
        set
        {
            this.idField = value;
        }
    }
}

/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("svcutil", "4.0.30319.33440")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.SoapTypeAttribute(Namespace = ApuConstants.Namespace)]
public partial class Response
{

    private ResponseHeader headerField;

    private Part[] itemsField;

    /// <remarks/>
    public ResponseHeader header
    {
        get
        {
            return this.headerField;
        }
        set
        {
            this.headerField = value;
        }
    }

    /// <remarks/>
    public Part[] items
    {
        get
        {
            return this.itemsField;
        }
        set
        {
            this.itemsField = value;
        }
    }
}

/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("svcutil", "4.0.30319.33440")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.SoapTypeAttribute(Namespace = ApuConstants.Namespace)]
public partial class Lookup
{

    private string oemField;

    private string hicField;

    private int qtyField;

    private string zipField;

    /// <remarks/>
    public string oem
    {
        get
        {
            return this.oemField;
        }
        set
        {
            this.oemField = value;
        }
    }

    /// <remarks/>
    public string hic
    {
        get
        {
            return this.hicField;
        }
        set
        {
            this.hicField = value;
        }
    }

    /// <remarks/>
    public int qty
    {
        get
        {
            return this.qtyField;
        }
        set
        {
            this.qtyField = value;
        }
    }

    /// <remarks/>
    public string zip
    {
        get
        {
            return this.zipField;
        }
        set
        {
            this.zipField = value;
        }
    }
}

实施:

[ServiceBehavior(Namespace = ApuConstants.Namespace)]
public class ApuService : IApuService
{
    private readonly IApuServiceHandler _handler;
    private readonly ISettingService _settingService;

    public ApuService()
    {
        _handler = EngineContext.Current.Resolve<IApuServiceHandler>();
        _settingService = EngineContext.Current.Resolve<ISettingService>();
    }

    public Response check(Request request)
    {
        if (Authorized(request))
            return _handler.ProcessRequest(request);
        return _handler.ErrorResponse("Invalid credentials");
    }

    protected bool Authorized(Request request)
    {
        if (request == null || request.header == null)
            return false;

        var settings = _settingService.LoadSetting<ApuSettings>(0);

        if (!string.Equals(request.header.account, settings.Username, StringComparison.InvariantCultureIgnoreCase))
            return false;

        if (!string.Equals(request.header.id, settings.Password))
            return false;

        return true;
    }
}

配置:

<configuration>
  <system.web>
    <compilation targetFramework="4.5.1" />
  </system.web>

  <system.serviceModel>
    <behaviors>
      <serviceBehaviors>
        <behavior name="ApuBehavior">
          <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
          <serviceDebug includeExceptionDetailInFaults="true"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <bindings>
    </bindings>
    <services>
      <service name="Apu.WebService.ApuService" behaviorConfiguration="ApuBehavior">
        <endpoint address="" binding="basicHttpBinding" contract="Web.Apu.IApuService" bindingNamespace="http://www.testurl.com/apu" />
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
      </service>
    </services>
  </system.serviceModel>
</configuration>

服务收到的请求(来自OperationContext.Current.RequestContext.RequestMessage):

<Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Header xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
    <To s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">http://localhost:15555/Plugins/Brock.Apu/Remote/ApuService.svc</To>
  </s:Header>
  <Body>
        <check xmlns="http://www.testurl.com/apu">
            <request>
                <header>
                    <account>apu</account>
                    <id>apu001!</id>
                </header>
                <lookup>
                    <hic>323-01327</hic>
                    <oem>5014351AB</oem>
                    <qty>2</qty>
                    <zip>85304</zip>
                </lookup>
            </request>
        </check>
    </Body>
</Envelope>

服务发送的响应(序列化不正确):

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
    <s:Body s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
        <q1:checkResponse xmlns:q1="http://www.testurl.com/apu">
            <return href="#id1"/>
        </q1:checkResponse>
        <q2:Response id="id1" xsi:type="q2:Response" xmlns:q2="http://www.testurl.com/apu">
            <header href="#id2"/>
        </q2:Response>
        <q3:ResponseHeader id="id2" xsi:type="q3:ResponseHeader" xmlns:q3="http://www.testurl.com/apu">
            <status xsi:type="xsd:string">no</status>
            <reason xsi:type="xsd:string">Invalid credentials</reason>
            <account xsi:type="xsd:string"/>
            <id xsi:type="xsd:string"/>
        </q3:ResponseHeader>
    </s:Body>
</s:Envelope>

3 个答案:

答案 0 :(得分:1)

看起来Response是一个部分类。还有另一件,也许在另一个文件中吗?那是另一件可序列化的吗? ResponseHeaderPart的相同问题?

我通常使用[Serializable]装饰器。

public float list课程Part上的关键字列表可能存在问题。

答案 1 :(得分:0)

跟进:事实证明我最初发布的服务合同很好。这是错误的请求格式。解串器不是一个简单的内联xml结构,而是期待这个:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <soapenv:Body>
        <ns1:check xmlns:ns1="http://www.testurl.com/apu" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
            <request href="#id0"/>
        </ns1:check>
        <multiRef xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns2="http://www.testurl.com/apu" id="id0" soapenc:root="0" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="ns2:Request">
            <header href="#id1"/>
            <lookup href="#id2"/>
        </multiRef>
        <multiRef xmlns:ns3="http://www.testurl.com/apu" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" id="id1" soapenc:root="0" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="ns3:RequestHeader">
            <account xsi:type="xsd:string"></account>
            <id xsi:type="xsd:string"></id>
        </multiRef>
        <multiRef xmlns:ns4="http://www.testurl.com/apu" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" id="id2" soapenc:root="0" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="ns4:Lookup">
            <oem xsi:type="xsd:string">6C3Z13008BB</oem>
            <hic xsi:type="xsd:string"/>
            <qty href="#id3"/>
            <zip xsi:type="xsd:string">70764</zip>
        </multiRef>
        <multiRef xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" id="id3" soapenc:root="0" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="xsd:int">1</multiRef>
    </soapenv:Body>
</soapenv:Envelope>

在我们的客户记录客户发送的原始请求后,我想出了这一点。

答案 2 :(得分:0)

改变这个:

 [System.ServiceModel.XmlSerializerFormatAttribute(Style = System.ServiceModel.OperationFormatStyle.Rpc, Use = System.ServiceModel.OperationFormatUse.Encoded)]

作者:

 [System.ServiceModel.XmlSerializerFormatAttribute(Style = System.ServiceModel.OperationFormatStyle.Document, Use = System.ServiceModel.OperationFormatUse.Literal)]