【问题标题】:Missing SecurityProtocolType.Ssl3 enum value during XML serializationXML 序列化期间缺少 SecurityProtocolType.Ssl3 枚举值
【发布时间】:2017-06-10 19:20:29
【问题描述】:

我有以下简单的 XML 可序列化类型:

[XmlType]
public class TestType
{
    public System.Net.SecurityProtocolType ProtocolType { get; set; }
}

var instanceToSerialize = new TestType { ProtocolType = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12 };

我可以在我的计算机和几台计算机上很好地序列化这个对象的一个​​实例。但在我测试过的其中一台计算机上,出现以下异常:

System.InvalidOperationException: There was an error generating the XML document. ---> System.InvalidOperationException: Instance validation error: '4080' is not a valid value for System.Net.SecurityProtocolType.
at System.Xml.Serialization.XmlCustomFormatter.FromEnum(Int64 val, String[] vals, Int64[] ids, String typeName)
at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationWriterTestType.Write1_SecurityProtocolType(SecurityProtocolType v)
at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationWriterTestType.Write3_TestType(String n, String ns, TestType o, Boolean isNullable, Boolean needType)
at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationWriterTestType.Write4_TestType(Object o)

我比较了sgen.exe 生成的工作和失败案例的代码。在工作案例中,我生成了以下代码:

string Write1_SecurityProtocolType(global::System.Net.SecurityProtocolType v) {
    string s = null;
    switch (v) {
        case global::System.Net.SecurityProtocolType.@Ssl3: s = @"Ssl3"; break;
        case global::System.Net.SecurityProtocolType.@Tls: s = @"Tls"; break;
        case global::System.Net.SecurityProtocolType.@Tls11: s = @"Tls11"; break;
        case global::System.Net.SecurityProtocolType.@Tls12: s = @"Tls12"; break;
        default: s = FromEnum(((System.Int64)v), new string[] {@"Ssl3", 
            @"Tls", 
            @"Tls11", 
            @"Tls12"}, new System.Int64[] {(long)global::System.Net.SecurityProtocolType.@Ssl3, 
            (long)global::System.Net.SecurityProtocolType.@Tls, 
            (long)global::System.Net.SecurityProtocolType.@Tls11, 
            (long)global::System.Net.SecurityProtocolType.@Tls12}, @"System.Net.SecurityProtocolType"); break;
    }
    return s;
}

而对于失败的代码,这是生成的代码:

string Write1_SecurityProtocolType(global::System.Net.SecurityProtocolType v) {
    string s = null;
    switch (v) {
        case global::System.Net.SecurityProtocolType.@Tls: s = @"Tls"; break;
        case global::System.Net.SecurityProtocolType.@Tls11: s = @"Tls11"; break;
        case global::System.Net.SecurityProtocolType.@Tls12: s = @"Tls12"; break;
        default: s = FromEnum(((System.Int64)v), new string[] {@"Tls", 
            @"Tls11", 
            @"Tls12"}, new System.Int64[] {(long)global::System.Net.SecurityProtocolType.@Tls, 
            (long)global::System.Net.SecurityProtocolType.@Tls11, 
            (long)global::System.Net.SecurityProtocolType.@Tls12}, @"System.Net.SecurityProtocolType"); break;
    }
    return s;
}

您会注意到,Ssl3 枚举成员的代码不会在失败的情况下生成。您知道为什么缺少该代码吗?

【问题讨论】:

  • 检查 PC 上安装的 .NET 版本。我相信最新版本 4.6 可能已经删除了该选项。
  • @Brianfromstatefarm 不,我安装了 4.6.1 和 4.6.2,而 4.6.x 仍然有 Ssl3 枚举成员。

标签: c# .net enums xml-serialization sgen


【解决方案1】:

简单的诊断是 SGen.exe 使用错误的参考程序集运行。 /reference 命令行选项很重要,如果不使用,它会退回到 c:\windows\microsoft.net 中的选项

鞋子合身,SecurityProtocolType 枚举一直很不稳定。它从 .NET 4.0 更改为 4.5,添加了 Tls11 和 Tls12 枚举成员。这里有很多关于它的 Q+A,即使在针对 4.0 的项目中也可以启用它们。 SSLv3 存在一个相当大的问题,它已被泄露beyond repair。因此,Microsoft 正试图阻止程序员使用它,您可以在 the .NETCore declaration 中看到这一点。 [Obsolete]属性是SGen.exe关注的一个属性。

对我来说,本来可以使用什么风格的参考汇编并不明显。虽然 SslProtocols.Ssl3 在 .NETCore 中具有 [Obsolete] 属性,但 SecurityProtocolType 枚举成员 does not。所以 SGen.exe 不小心使用了 .NETCore 参考程序集并没有解释它。 Mono 或 Xamarin 之类的东西不容易解释它。 Silverlight 或 PCL 参考程序集没有解释它,至少在我的机器上没有。不稳定的测试版总是有可能的。

除非您有已知的理由为 SGen.exe 使用不寻常的 /reference 参数,否则最好的建议是在该计算机上重新安装 .NET Framework。并且停止使用 Ssl3,它确实已经过时了。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-02
    • 2012-05-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多