You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.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-1 id需要通过XmlWriter手动写入。

内容的提问来源于stack exchange,提问作者malat

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 19:10:32