枚举和WCF - 有意义的错误?

时间:2009-09-12 14:29:51

标签: .net wcf enums

我正在尝试克服WCF和枚举的问题,我正在尝试将对象从服务器传递到包含枚举的客户端(或其他服务器)。枚举以1开头,故意。枚举初始化时以及在其中定义值时,一切都很顺利,但是当它未在枚举中定义时,我得到了这个非常好的(并且描述性很强的(...))错误消息:

“底层连接已关闭:连接意外关闭。”

我尝试实现的是当我得到这个场景时,要么是数据库中的数据损坏(无论是对于枚举,还是完全非常奇怪),或者开发人员在启动时忘记设置枚举值对象,为了获得有意义的消息,例如“枚举值无效,键入:{0},值:{1}”。

我试图在类的枚举和getter中使用“Enum.IsDefined”,并将有意义的异常抛给客户端(或其他服务器),但仍然得到“连接关闭”错误(当允许调试服务器时,我得到了有意义的消息,但仅在服务器端)。

这是enum setter& amp;吸气剂:

    private TestEnum m_TestEnum;

    [DataMember]
    public TestEnum TestEnum 
    {
        get
        {
            if (Enum.IsDefined(typeof(TestEnum), m_TestEnum))
            {
                return m_TestEnum;
            }
            else
            {
                throw new ApplicationException("Enum value is not valid: " + m_TestEnum);
            }
        }
        set
        {
            if (Enum.IsDefined(typeof(TestEnum), value))
            {
                m_TestEnum = value;
            }
            else
            {
                throw new ApplicationException("Enum value is not valid: " + value);
            }
        }
    }

从0开始枚举(带有“未知”值)不够好,因为我仍然可以获得枚举中不存在的值。我可以结合两种解决方案,我检查“IsDefined”并将枚举设置为“未知”值,但仍然 - 这不是理想的解决方案,因为我们想知道这些情况,以便在开发周期中解决它们

你怎么说? 谢谢, 尼尔。

2 个答案:

答案 0 :(得分:5)

通过WCF发送枚举时,将发送枚举值的字符串表示形式,而不是数字值。这允许双方将相同的枚举标签映射到不同的数字。

如果发送的标签未被收件人理解,则该频道将被关闭。我相信这会延伸到未定义的枚举值(它看起来像你正在迎合它。)

因此,仅仅因为枚举标签在发件人方面有效并不意味着客户端必然会理解它。

您是否在发件人和收件人之间共享相同的类定义?

要进一步调试此问题,您应该在客户端和服务器中启用服务跟踪(对于许多令人沮丧的WCF问题,这是正确的。)它将帮助您确定问题的根源,否则您没有任何指示。

将以下XML添加到App.config中(在客户端和服务器上):

<configuration>
   <system.diagnostics>
      <sources>
            <source name="System.ServiceModel" 
                    switchValue="Information, ActivityTracing"
                    propagateActivity="true">
            <listeners>
               <add name="traceListener" 
                   type="System.Diagnostics.XmlWriterTraceListener" 
                   initializeData= "WcfTrace.svclog" />
            </listeners>
         </source>
      </sources>
   </system.diagnostics>
</configuration>

several options for this configuration

添加此配置后,您将创建一个.svclog文件,可以使用Service Trace Viewer Tool进行查看。此日志包含大量有关所发生事件的信息,包括警告和错误。

请注意,生成的日志文件可能会非常大,因此请务必在完成调试后删除或注释掉此配置部分。


请注意,您可以为要在线路上使用的枚举成员指定不同的字符串值。

例如,以下两个枚举在WCF上是等效的:

public enum CarCondition
{
    New,
    Used,
    Rental,
    [NonSerialized]
    Lost
}    

[DataContract(Name = "CarCondition")]
public enum CarConditionWithDifferentNames
{
    [EnumMember(Value = "New")]
    BrandNew,
    [EnumMember(Value = "Used")]
    PreviouslyOwned,
    [EnumMember]
    Rental
} 

您可以阅读more information about using enums over WCF here

答案 1 :(得分:1)

好吧,问题是序列化无法序列化枚举中未定义的值,这包括(默认)0值。

例如:

enum E
{
    New = 1,
    Used
}


[OperationContract]
public E Method()
{
    E e;
    return e;
}

对Method的调用将失败,因为“e”被初始化为“e =(E)0”。当序列化尝试完成它的工作时,它在E中找不到匹配0的字段,因此它失败(或生成与wsdl不匹配的xml,这会将值限制为枚举成员)。

因此,我们必须确保我们的服务方法始终返回有效值(根据枚举定义)。

我在MSDN中没有看到任何关于这一点的讨论,所以在我的测试之后这是我自己的结论。

希望它有所帮助, 何