Отсутствует значение перечисления SecurityProtocolType.Ssl3 во время сериализации XML

У меня есть следующий простой 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 Член enum не генерируется в случае ошибки. У вас есть идея, почему этот код отсутствует?

1 ответ

Простая диагностика в том, что SGen.exe был запущен с неправильными ссылочными сборками. /reference Значения параметров командной строки, если они не используются, то возвращаются к тем, которые находятся в c:\windows\microsoft.net

Обувь подходит, перечисление SecurityProtocolType было довольно непостоянным. Он был изменен с.NET 4.0 на 4.5, добавив элементы перечисления Tls11 и Tls12. Много Q+A здесь об этом, чтобы включить их даже в проекте, который нацелен на 4.0. И есть довольно большая проблема с SSLv3, он был скомпрометирован без возможности восстановления. Соответственно, Microsoft пытается помешать программистам использовать его, что вы можете увидеть в декларации.NETCore. Атрибут [Устаревший] - это тот, на который SGen.exe обращает внимание.

Для меня не очевидно, какой вариант эталонной сборки мог быть использован. В то время как SslProtocols.Ssl3 имеет атрибут [устарел] в.NETCore, член перечисления SecurityProtocolType не имеет. Поэтому SGen.exe, случайно использующий эталонную сборку.NETCore, не объясняет этого. Что-то вроде Моно или Ксамарина не может легко объяснить это. Silverlight или справочная сборка PCL этого не объясняют, по крайней мере, на моей машине. Выгодная бета-версия всегда возможна.

Если у вас нет известных причин использовать необычные /reference В качестве аргумента для SGen.exe, лучшая рекомендация - переустановить.NET Framework на этом компьютере. И прекратите использовать Ssl3, он действительно устарел.

Другие вопросы по тегам