. net WCF序列化问题

本文关键字:问题 序列化 WCF net | 更新日期: 2023-09-27 17:50:35

情况:系统A应该公开SOAP 1.2 web服务供系统B调用。为了让A知道消息是什么样子,B向A发送了一个描述消息内容的XSD。使用。net xsd.exe工具生成存根,围绕它创建简单的webservice,工作就完成了。

然而

;当B调用此web服务时,A拒绝将SOAP/XML内容序列化到生成的代理类实例。我意识到这一定是由于在系统A的web服务端定义序列化的方式,但一直无法准确地定位出什么问题。

来自B的消息是什么样子的(匿名)- FAILS:

<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>

来自测试客户端的测试消息(基于WSDL)是什么样子的- WORKS:

<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>

当由A构建的webservice从B接收消息时,它根本不序列化消息。代理(以Context为例)的对象为null。当它从测试客户端接收消息时,一切都正确生成了。

代理上的序列化属性:

[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;

我觉得奇怪的事情:

  1. 当为该服务生成WSDL时,WSDL将其自己的名称空间添加到WSDL定义中(例如,上面示例中的xmlns:b)。
  2. WSDL不尊重代理中定义的unqualified注释,并且使所有内容都是合格的。

我尝试了各种注释组合,但似乎没有什么帮助;来自B的消息没有正确地反序列化到a生成的代理,任何想法/指针/帮助将非常感激!

. net WCF序列化问题

在一个典型的"问问题,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发生了显著变化(适当的名称空间),消息被正确序列化。

让我走上正轨的论坛帖子:http://social.msdn.microsoft.com/Forums/en-US/wcf/thread/c7fede29-56c2-4ff3-bd02-48e3e0b2cec1/

(这实际上是一个注释,但它不适合)

尝试添加系统。诊断到您的网络。配置以查找有关错误的更多信息:

    <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 SDKs'Windows'v6.0A'bin'SvcTraceViewer.exe(或类似的)查看svclog。将此添加到两个服务中(当然是不同的日志文件名),看看哪个失败了,以及确切的原因。

我怀疑序列化是可以的,但是服务的某些绑定/设置导致调用失败。