.net - 如何阻止 .net Xml 序列化插入非法字符

标签 .net xml soap invalid-characters

0x20 以下的任何内容(除了 0x09、0x0a、0x0d,即制表符、回车符和换行符)都不能包含在 XML 文档中。

我有一些数据来自数据库并作为对 Web 服务请求的响应传递。

Soap 格式化程序愉快地将 0x12 字符(Ascii 18,设备控制 2)编码为 但客户端响应失败,十六进制值为 0x12,是无效字符

<rant>我觉得非常令人沮丧的是,它们是同一枚硬币的两个方面,客户端和服务都是 .net 应用程序。如果没有人可以读取它,为什么 soap 格式化程序会写出错误的 xml? </rant>

我也愿意

  1. 让 Xml Serialiser 正确处理这些奇怪的字符或
  2. 让请求在 Web 服务中失败

除了 a) “清理您的输入”或 b) “更改您的文档结构”之外,我在 google 上搜索并没有找到太多相关信息。

a) 不是运行者,因为其中一些数据已有 20 多年历史了
b) 也不是什么好选择,因为除了我们自己的前端之外,我们还有直接针对 Web 服务编码的客户端。

有什么明显的我遗漏的东西吗?还是仅仅是围绕 AscII 控制代码的代码?

谢谢

更新
这实际上是 XmlSerialiser 的问题,下面的代码会将无效字符序列化到流中,但不会反序列化它

[Serializable]
public class MyData 
{
    public string Text { get; set; }

}
class Program
{
    public static void Main(string[] args)
    {
        var myData = new MyData {Text = "hello " 
                + ASCIIEncoding.ASCII.GetString(new byte[] { 0x12 }) 
                + " world"};

        var serializer = new XmlSerializer(typeof(MyData));

        var xmlWriter = new StringWriter();

        serializer.Serialize(xmlWriter, myData);

        var xmlReader = new StringReader(xmlWriter.ToString());

        var newData = (MyData)serializer.Deserialize(xmlReader); // Exception 
        // hexadecimal value 0x12, is an invalid character.

    }
}

我可以通过显式创建 XmlWriter 并将其传递给 Serialise 来阻止 编写 xml (我会很快将其发​​布为我自己的答案),但这仍然意味着我必须在发送数据之前对其进行清理。
由于这些字符很重要,我不能只删除它们,我需要在传输前对它们进行编码,并在读取时对其进行解码,我真的很惊讶似乎没有一个现有的执行此操作的框架方法。

最佳答案

第二:解决方案

使用 DataContractSerializer(WCF 服务默认使用)代替 XmlSerializer 效果不错

[Serializable]
public class MyData
{
    public string Text { get; set; }
}
class Program
{
    public static void Main(string[] args)
    {
        var myData = new MyData
        {
            Text = "hello "
                + ASCIIEncoding.ASCII.GetString(new byte[] { 0x12 })
                + " world"
        };

        var serializer = new DataContractSerializer(typeof(MyData));

        var mem = new MemoryStream();

        serializer.WriteObject(mem, myData);

        mem.Seek(0, SeekOrigin.Begin);
        MyData myData2 = (MyData)serializer.ReadObject(mem);

        Console.WriteLine("myData2 {0}", myData2.Text);
    }
}

Frist:解决方法

通过使用 XmlWriter,我可以在编写 Xml 时使其阻塞,这可以说比客户端阻塞要好。例如

但是它并没有解决发送无效字符的根本问题

[Serializable]
public class MyData 
{
    public string Text { get; set; }
}
class Program
{
    public static void Main(string[] args)
    {
        var myData = new MyData {Text = "hello " 
            + ASCIIEncoding.ASCII.GetString(new byte[] { 0x12 }) 
            + " world"};
        var serializer = new System.Xml.Serialization.XmlSerializer(typeof(MyData));

        var sw = new StringWriter();
        XmlWriterSettings settings = new XmlWriterSettings();

        using (var writer = XmlWriter.Create(sw))
        {
            serializer.Serialize(writer, myData); // Exception
            // hexadecimal value 0x12, is an invalid character
        }
        var xmlReader = new StringReader(sw.ToString());

        var newUser = (MyData)serializer.Deserialize(xmlReader);

        Console.WriteLine("User Name = {0}", newUser);

    }
}

关于.net - 如何阻止 .net Xml 序列化插入非法字符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8215657/

相关文章:

java - 使用 Maven 连接多个独立的 Spring 应用程序

javascript - 在 IIS 上显示来自 javascript 文件(SOAP 请求)的 XML 响应

c# - 即使正确发送了 SOAP 请求,Axis2 也总是收到空参数?

c# - 如何在 C# 泛型中指定可以从字符串构造的 T ? (通用类型约束)

.net - 如何从内存中的图像获取流?

xml - 如何比较两个 XML 节点结构 Delphi

java - 如何通过 Java 代码中的 SpEL 表达式选择 Tomcat context.xml 参数

c# - 在 C# 中获取 List<T> 中不同值的列表

c# - 如何使用 string.Join 将 Jagged 数组与分隔符连接起来?

c# - 在 WCF 的其他契约(Contract)中将 MessageContract 作为 MessageBodyMember