WCF服务不对反释的值进行反序列化

时间:2015-01-28 22:23:26

标签: c# wcf

我构建了一个WCF服务,并且有一个看起来像这样的部分:

[ServiceContract]
public class Service {
    [OperationContract]
    public SomethingElse[] Method(Code a, params Something[] b) { ... }
}

[DataContract]
public class Something {
    [DataMember]
    public string Stuff {get;set;}
    [DataMember]
    public Status MyStatus {get;set;}
    public string ServerSideField {get;set;}
}

[DataContract]
public class SomethingElse {
    [DataMember]
    public Status MyStatus {get;set;}
}

[DataContract]
public enum Status {
    [EnumMember] WorksFine,
    [EnumMember] NotWorking
}

[DataContract]
public enum Code {
    [EnumMember] TypeA,
    [EnumMember] TypeB
}

现在我将它用作C#客户端的服务参考。出于某种原因,每当我致电Method时,MyStatus参数中的b属性始终设置为WorksFine,即使我将其设置为NotWorking。另一方面,每当我为Code.TypeA参数传递Code.TypeBa时,服务始终会正确地反序列化。

为了尽职调查,关于将枚举传递给WCF服务的其他帖子引用DataContractEnumMember(Value="TypeA")ServiceKnownType,所以我给了所有这些帖子。但是,即使我使用ServiceKnownType(如下所示),我仍然遇到同样的问题。

[ServiceContract]
[ServiceKnownType(typeof(Something)]
[ServiceKnownType(typeof(Status)]
public class Service {
    [OperationContract]
    public SomethingElse[] Method(Code a, params Something[] b) { ... }
}

对于这么基本的事情,这个问题似乎异常模糊。我测试了从服务中传回Status.NotWorking并且客户端能够看到它,因此这似乎是一个单向问题。有什么建议吗?

编辑1:

类似问题:WCF not deserializing value types. Mysterious behaviour

编辑2:

从缺乏即时回应的角度来看,我会在其中一些内容中包含更多信息。

  • 我在.NET 4.5和4.0上都遇到了这个问题。
  • 该服务托管在IIS上,具有SSL和自定义身份验证方案。
  • Method上还有一个FaultContract属性,但我将其排除在外以使示例更简单。
  • 事件查看器说zilch。 IIS日志也是如此。
  • Reference.cs中自动生成的服务引用代码如下所示:

枚举:

/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "4.0.30319.18408")]
[System.SerializableAttribute()]
[System.Xml.Serialization.XmlTypeAttribute(Namespace="http://schemas.datacontract.org/2004/07/Service")]
public enum Status{ TypeA, TypeB }

方法:

// CODEGEN: Parameter 'MethodResult' requires additional schema information that cannot be captured using the parameter mode. The specific attribute is 'System.Xml.Serialization.XmlArrayAttribute'.
    [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/Service/Method", ReplyAction="http://tempuri.org/Service/MethodResponse")]
    [System.ServiceModel.FaultContractAttribute(typeof(MyClientProject.Service.MyFault), Action="http://tempuri.org/Service/MethodMyFaultFault", Name="MyFault", Namespace="http://schemas.datacontract.org/2004/07/Service.MyFault")]
    [System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults=true)]
    MyClientProject.Service.Method Method(MyClientProject.Service.MethodRequest request);

编辑3:

我构建了另一个仅包含上述代码的Web服务,但它不会重现我所看到的行为。我的猜想是,其他一些代码都是Zilching DataContractSerializer,或者有一些相关的IIS / WCF设置,或者一些未解决的数据合同问题。

我还构建了另一个连接到两个Web服务的Web客户端,它收到的结果与第一个相同。

编辑4

与Fiddler截获的请求看起来像这样:

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Method xmlns="http://tempuri.org/">
<a>TypeA</a>
<b><Something xmlns="http://schemas.datacontract.org/2004/07/TestService.Something">
   <Stuff>mystuffvalue</Stuff>
</Something></b>
</Method>
</s:Body>
</s:Envelope>

所以枚举永远不会被传递!如何解决合同不匹配问题?

编辑5

忘记提及Web服务引用了ASMX服务,并且本身使用XML序列化程序与该外部服务进行通信。

2 个答案:

答案 0 :(得分:2)

关键在于:

[System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults=true)]

XML Serializer用于生成代理而不是DataContractSerializer。你是否意外指定了XmlSerializer?您是否尝试使用.asmx服务?

一旦你弄清楚是什么导致使用XmlSerializer生成代码,你就会得到答案,但是你发布的内容并不是很明显。

答案 1 :(得分:2)

由于某些未知原因,客户端发出的SOAP请求省略了我需要的枚举值,因此服务器将这些枚举序列化为其默认值(列表中的第一个枚举定义)。

我通过省略请求体所需的参数来修复此问题。这是修复它的代码:

[DataContract]
public class Something {
    [DataMember]
    public string Stuff {get;set;}
    [DataMember(IsRequired=true)] // just this 1 simple change!
    public Status MyStatus {get;set;}
    public string ServerSideField {get;set;}
}