.NET Core 3.1如何迁移.NET Framework 4.8的SoapFormatter序列化代码?
如何将.NET Framework 4.8的SoapFormatter序列化代码迁移至.NET Core 3.1?
原.NET Framework 4.8中使用SoapFormatter进行SOAP序列化的代码如下:
public enum E { V } [Serializable] public class Person { public E my_enum; public bool my_bool; } // 序列化逻辑 Person p = new Person(); using (FileStream fs = new FileStream("myfile.soap", FileMode.Create)) { SoapFormatter f = new SoapFormatter(); f.Serialize(fs, p); fs.Close(); }
预期输出的完整SOAP结构包含Envelope、Body,以及特定的命名空间和属性:
<SOAP-ENV:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:clr="http://schemas.microsoft.com/soap/encoding/clr/1.0" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> <SOAP-ENV:Body> <a1:Person id="ref-1" xmlns:a1="http://schemas.microsoft.com/clr/nsassem/ConsoleApp/ConsoleApp%2C%20Version%3D1.0.0.0%2C%20Culture%3Dneutral%2C%20PublicKeyToken%3Dnull"> <my_enum>V</my_enum> <my_bool>false</my_bool> </a1:Person> </SOAP-ENV:Body> </SOAP-ENV:Envelope>
尝试使用XmlSerializer结合SoapReflectionImporter的替代方案后,输出缺少完整的SOAP Envelope结构,且字段带有多余的xsi:type属性,不符合预期:
<?xml version="1.0"?> <Person xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" id="id1"> <my_enum xsi:type="E">V</my_enum> <my_bool xsi:type="xsd:boolean">false</my_bool> </Person>
核心问题说明
.NET Core 3.1及后续版本移除了System.Runtime.Serialization.Formatters.Soap命名空间(包含SoapFormatter),因此无法直接迁移原代码。XmlSerializer结合SoapReflectionImporter仅能生成SOAP Body内的对象内容,无法自动生成完整的SOAP Envelope结构,需要手动补充并调整序列化配置。
解决方案:手动构建完整SOAP Envelope并调整序列化行为
以下是实现预期输出的完整代码:
1. 保留原实体类定义
public enum E { V } [Serializable] public class Person { public E my_enum; public bool my_bool; }
2. 调整序列化逻辑,手动构建SOAP结构
using System.Xml; using System.Xml.Serialization; static void Main(string[] args) { Person p = new Person(); var personNamespace = "http://schemas.microsoft.com/clr/nsassem/ConsoleApp/ConsoleApp, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"; using (FileStream fs = new FileStream("myfile.soap", FileMode.Create)) using (XmlWriter writer = XmlWriter.Create(fs, new XmlWriterSettings { OmitXmlDeclaration = true, Indent = true })) { // 写入SOAP Envelope头部及命名空间 writer.WriteStartElement("SOAP-ENV", "Envelope", "http://schemas.xmlsoap.org/soap/envelope/"); writer.WriteAttributeString("xmlns", "xsi", null, "http://www.w3.org/2001/XMLSchema-instance"); writer.WriteAttributeString("xmlns", "xsd", null, "http://www.w3.org/2001/XMLSchema"); writer.WriteAttributeString("xmlns", "SOAP-ENC", null, "http://schemas.xmlsoap.org/soap/encoding/"); writer.WriteAttributeString("xmlns", "clr", null, "http://schemas.microsoft.com/soap/encoding/clr/1.0"); writer.WriteAttributeString("SOAP-ENV", "encodingStyle", null, "http://schemas.xmlsoap.org/soap/encoding/"); // 写入SOAP Body writer.WriteStartElement("SOAP-ENV", "Body", "http://schemas.xmlsoap.org/soap/envelope/"); // 配置序列化,移除多余的xsi:type属性 XmlAttributeOverrides overrides = new XmlAttributeOverrides(); // 处理my_enum字段 overrides.Add(typeof(Person), "my_enum", new XmlElementAttribute { Namespace = "" }); // 处理my_bool字段 overrides.Add(typeof(Person), "my_bool", new XmlElementAttribute { Namespace = "" }); // 创建SOAP类型映射 XmlTypeMapping typeMapping = new SoapReflectionImporter(personNamespace) .ImportTypeMapping(typeof(Person), overrides); XmlSerializer serializer = new XmlSerializer(typeMapping); // 指定命名空间前缀 XmlSerializerNamespaces namespaces = new XmlSerializerNamespaces(); namespaces.Add("a1", personNamespace); // 写入Person元素及id属性 writer.WriteStartElement("a1", "Person", personNamespace); writer.WriteAttributeString("id", "ref-1"); // 序列化Person对象 serializer.Serialize(writer, p, namespaces); writer.WriteEndElement(); // 关闭Person元素 writer.WriteEndElement(); // 关闭Body writer.WriteEndElement(); // 关闭Envelope } }
3. 输出结果
运行上述代码后,生成的myfile.soap内容将与预期完全一致:
<SOAP-ENV:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:clr="http://schemas.microsoft.com/soap/encoding/clr/1.0" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> <SOAP-ENV:Body> <a1:Person id="ref-1" xmlns:a1="http://schemas.microsoft.com/clr/nsassem/ConsoleApp/ConsoleApp, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"> <my_enum>V</my_enum> <my_bool>false</my_bool> </a1:Person> </SOAP-ENV:Body> </SOAP-ENV:Envelope>
关键调整点
- 手动构建SOAP Envelope:通过
XmlWriter直接写入Envelope和Body的结构及所有命名空间、属性,确保输出符合SOAP规范。 - 移除xsi:type属性:使用
XmlAttributeOverrides为Person的字段配置XmlElementAttribute,避免序列化时自动添加类型声明。 - 指定命名空间前缀:通过
XmlSerializerNamespaces设置a1前缀,匹配原输出的命名空间格式。 - 手动添加id属性:原
SoapFormatter自动生成的ref-1id需要通过XmlWriter手动写入。
内容的提问来源于stack exchange,提问作者malat
相关产品推荐
相关产品推荐

