Отсутствует значение перечисления 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, он действительно устарел.