C# .NET WCF序列化问题
情况:系统A应该公开SOAP1.2Web服务,以便系统B调用。为了让A知道消息的外观,B向A发送了一个XSD,描述消息的内容。A使用.NET xsd.exe工具生成存根,围绕此创建简单的Web服务,并完成了工作 但是,;当B调用此webservice时,A拒绝将SOAP/XML内容序列化到生成的代理类实例。我意识到这一定是因为序列化是在系统A的webservice端定义的,但一直无法准确定位出哪里出了问题 来自B的消息看起来像什么(匿名)-失败:C# .NET WCF序列化问题,c#,.net,wcf,xml-serialization,C#,.net,Wcf,Xml Serialization,情况:系统A应该公开SOAP1.2Web服务,以便系统B调用。为了让A知道消息的外观,B向A发送了一个XSD,描述消息的内容。A使用.NET xsd.exe工具生成存根,围绕此创建简单的Web服务,并完成了工作 但是,;当B调用此webservice时,A拒绝将SOAP/XML内容序列化到生成的代理类实例。我意识到这一定是因为序列化是在系统A的webservice端定义的,但一直无法准确定位出哪里出了问题 来自B的消息看起来像什么(匿名)-失败: <ns2:Set_Out xmlns:ns
<ns2:Set_Out xmlns:ns2="http://a.a/1.0" xmlns:ns1="http://b.b/1.0" xmlns:ns0="http://c.c">
<Context xmlns="">
<Foo>test</Foo>
<Bar>test</Bar>
...
</Context>
<Set_Out xmlns="http://a.a/1.0">
<Context xmlns:b="http://schemas.datacontract.org/2004/07/x.x" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<b:Foo>TEST</b:Foo>
<b:Bar>test</b:Bar>
...
</Context>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.3038")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true, Namespace="http://a.a/1.0")]
[System.Xml.Serialization.XmlRootAttribute(Namespace="http://a.a/1.0", IsNullable=false)]
[System.ServiceModel.MessageContract]
public partial class Set_Out {
[System.Xml.Serialization.XmlElementAttribute(Namespace="http://a.a/1.0", Form=System.Xml.Schema.XmlSchemaForm.Unqualified)] [System.ServiceModel.MessageBodyMember(Order=0)]
public ContextType Context;
...
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.3038")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(Namespace="http://a.a/1.0")]
public partial class ContextType {
[System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
public string Foo;
我觉得奇怪的是:
xmlns:b
)非限定的注释,并使所有内容都限定
<system.diagnostics>
<trace autoflush="true" />
<sources>
<source name="System.ServiceModel"
switchValue="Information, ActivityTracing"
propagateActivity="true">
<listeners>
<add name="sdt"
type="System.Diagnostics.XmlWriterTraceListener"
initializeData= "C:\MyLog.svclog" />
</listeners>
</source>
</sources>
</system.diagnostics>
您可以使用C:\Program Files\Microsoft SDK\Windows\v6.0A\bin\SvcTraceViewer.exe
(或类似工具)查看svclog。将其添加到两个服务中(当然是不同的日志文件名),然后查看哪个服务失败,以及具体原因
我怀疑序列化是正常的,但服务的某些绑定/设置会导致调用失败。在典型的“提问,5分钟后自己解决”的情况下,我已经设法解决了我的问题
问题是,显然,在使用WCF.NET时,会对数据协定中涉及的类使用默认序列化程序。这个默认的序列化程序(我相信它是DataContractSerializer
)显然在配置方面不允许太多。我不得不告诉WCF使用XmlSerializer
来序列化消息。要做到这一点,我必须将[XmlSerializerFormat()]
注释添加到服务契约接口(显然它也用于操作)。例如:
[ServiceContract(Namespace = "http://a.a/1.0")]
[XmlSerializerFormat()]
public interface IMyWebService
{
[OperationContract()]
void DoStuff(Set_Out message);
}
添加[XmlSerializerFormat()]
注释后,WSDL发生了显著变化(正确的名称空间),消息被正确序列化
让我走上正轨的论坛帖子:注意:上面的XML示例是整个消息的摘录,显然这包含了更多与SOAP相关的内容,但为了简洁起见,我将其省略了。为什么要发送XSD?为什么不直接使用“添加服务参考”?我有同样的反应,但我在为一家公司咨询,而这家公司在我的故事中是系统B,所以我避免了冲突,并按照它去做。事实上,这是一种相反的工作方式;我没有让客户机遵守契约(WSDL),而是侵入契约使客户机工作。有人可能会说这很愚蠢,而且是“做错了”。@pHk:我会说这是无法维护的,不符合标准,而且违背了客户的长期利益。好吧,很典型,但我认为我找到了一个似乎可行的解决方案,需要做更多的测试,BRB:)