WCF服务未反序列化枚举值 [英] Enum Value Is Not Deserialized By WCF Service

查看:52
本文介绍了WCF服务未反序列化枚举值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我构建了WCF服务,其中有一个部分如下所示:

  [ServiceContract]公共类服务{[运营合同]public SomethingElse []方法(代码a,参数Something [] b){...}}[数据合同]公共课某事{[DataMember]公共字符串Stuff {get; set;}[DataMember]公共状态MyStatus {get; set;}公共字符串ServerSideField {get; set;}}[数据合同]公共课程SomethingElse {[DataMember]公共状态MyStatus {get; set;}}[数据合同]公共枚举状态{[EnumMember] WorksFine,[EnumMember]不起作用}[数据合同]公共枚举代码{[EnumMember] TypeA,[EnumMember] TypeB} 

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

出于尽职调查的目的,其他有关将枚举传递给WCF服务的主题的文章,请参见 DataContract EnumMember(Value ="TypeA") ServiceKnownType ,所以我给了所有这些机会.但是,即使使用 ServiceKnownType (如下所示),我仍然会遇到相同的问题.

  [ServiceContract][ServiceKnownType(typeof(Something)][ServiceKnownType(typeof(Status))]公共类服务{[运营合同]public SomethingElse []方法(代码a,参数Something [] b){...}} 

对于如此基本的问题,此问题似乎难以理解.我还测试了从服务中传回 Status.NotWorking 的过程,客户端能够看到它,因此这似乎是一个单向的问题.有什么建议吗?

类似的问题: WCF不会反序列化值类型.神秘行为

从缺乏即时响应的角度出发,我将提供更多信息,以防其中某些问题停留.

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

枚举:

 ///<备注/>[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml","4.0.30319.18408")][System.SerializableAttribute()][System.Xml.Serialization.XmlTypeAttribute(Namespace ="http://schemas.datacontract.org/2004/07/Service")]公共枚举状态{TypeA,TypeB} 

方法:

 //CODEGEN:参数'MethodResult'需要其他模式信息,这些信息无法使用参数模式捕获.特定属性是"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方法(MyClientProject.Service.MethodRequest请求); 

我构建了另一个仅由上面的代码组成的Web服务,但是它没有重现我所看到的行为.我的猜测是,或者其他一些代码正在压缩DataContractSerializer,或者存在一些相关的IIS/WCF设置,或者是一些未解决的数据协定问题.

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

编辑4

拦截了Fiddler的请求,它看起来像这样:

 < s:信封xmlns:s ="http://schemas.xmlsoap.org/soap/envelope/">< s:正文xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd ="http://www.w3.org/2001/XMLSchema"><方法xmlns ="http://tempuri.org/">< a> TypeA</a>< b><某事xmlns ="http://schemas.datacontract.org/2004/07/TestService.Something">< Stuff> mystuffvalue</Stuff></某事>/b</方法></s:Body></s:信封> 

因此,枚举毕竟永远不会被传递!我该如何解决合同不匹配的问题?

编辑5

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

解决方案

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

我通过省略请求正文所需的参数来解决此问题.这是修复它的代码:

  [DataContract]公共课某事{[DataMember]公共字符串Stuff {get; set;}[DataMember(IsRequired = true)]//仅是这1个简单的更改!公共状态MyStatus {get; set;}公共字符串ServerSideField {get; set;}} 

I built a WCF service and there's a section that looks like this:

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

Now I am using it as a service reference for a C# client. For some reason, whenever I call Method, the MyStatus property inside the b parameter is always set to WorksFine, even if I set it to NotWorking. On the other hand, whenever I pass Code.TypeA or Code.TypeB for the a argument, the service always deserializes it correctly.

For the sake of due diligence, other posts on the subject of passing enums to WCF services refer to DataContract, EnumMember(Value="TypeA"), and ServiceKnownType so I gave all of those a shot. However, even when I use ServiceKnownType (like below), I am still encountering the same problem.

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

This issue seems unusually obscure for something so basic. I tested passing back Status.NotWorking from the service as well and the client is able to see it, so this appears to be a one-way issue. Any suggestions?

EDIT 1:

Similar issue: WCF not deserializing value types. Mysterious behaviour

EDIT 2:

Judging from the lack of immediate response, I am going to include some more information in case some of it sticks.

  • I'm experiencing this problem on both .NET 4.5 and 4.0.
  • The service is hosted on IIS, has SSL, and custom authentication scheme.
  • There is also a FaultContract attribute on Method but I excluded it to make the example simpler.
  • Event Viewer says zilch. So does IIS logs.
  • Auto-generated service reference code in Reference.cs looks like this:

The enum:

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

The method:

// 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);

EDIT 3:

I built another web service consisting of just the code above, but it does NOT reproduce the behavior that I am seeing. My conjecture is that either some other code is zilching the DataContractSerializer, OR there is some relevant IIS/WCF setting, OR some unresolved data contract issues.

I also built another web client that connects to both webservices, and it is receiving the same results as the first.

EDIT 4

Intercepted request with Fiddler and it looked like this:

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

So the enum is never being passed after all! How do I fix this contract mismatch?

EDIT 5

Forgot to mention that the web service had a reference to an ASMX service and was itself using XML serializer to communicate with that external service.

解决方案

For some unknown reason, the SOAP request made by the client was omitting the enum values that I needed, and consequently the server serialized those enums to their default values (the first enum definition on the list).

I fixed this issue by making omitted parameters required for the request body. This is the code that fixed it:

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

这篇关于WCF服务未反序列化枚举值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆