我正在使用旧的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>
答案 0 :(得分:1)
看起来Response
是一个部分类。还有另一件,也许在另一个文件中吗?那是另一件可序列化的吗? ResponseHeader
和Part
的相同问题?
我通常使用[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)]