Как остановить .net Xml сериализацию вставки недопустимых символов - PullRequest
4 голосов
/ 21 ноября 2011

Все, что меньше 0x20 (за исключением 0x09, 0x0a, 0x0d, т. Е. Табуляция, возврат каретки и перевод строки), не может быть включено в документ XML.

У меня есть некоторые данные, поступающие из базы данных и передаваемые в ответ на запрос веб-службы.

Средство форматирования Soap успешно кодирует символ 0x12 (Ascii 18, Device Control 2) как , но ответ на клиенте не получается с шестнадцатеричным значением 0x12, это недопустимый символ

<rant> То, что я нахожу весьма разочаровывающим, это то, что это две стороны одной медали, и клиент, и сервис являются приложениями .net. Почему средство форматирования мыла будет писать плохой xml, если ничто не может его прочитать? </rant>

Я бы тоже хотел

  1. Получите Сериализатор Xml для правильной обработки этих нечетных символов или
  2. Ошибка запроса в веб-сервисе

Я погуглил и не смог найти что-либо еще, кроме: а) «дезинфекции ваших входов» или б) «изменения структуры вашего документа».

а) Не является бегуном, поскольку некоторым из этих данных +20 лет
b) это тоже не лучший вариант, так как кроме нашего собственного внешнего интерфейса у нас есть клиенты, которые напрямую кодируют веб-службу.

Есть что-то очевидное, что я упускаю? Или это просто случай кода вокруг управляющих кодов 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.

    }
}

Я могу заставить его душить писать xml, явно создав XmlWriter и передав его в Serialise (я вскоре опубликую это как мой собственный ответ), но это все равно означает, что я очистить мои данные перед отправкой.
Поскольку эти символы имеют большое значение, я не могу просто удалить их, мне нужно кодировать их перед передачей и декодировать их при чтении, и я действительно очень удивлен, что, похоже, не существует существующей структуры способ сделать это.

Ответы [ 2 ]

1 голос
/ 22 ноября 2011

Секунда : решение

Использование 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 : Обходной путь

Я могу заставить его задохнуться при написании Xml, используя XmlWriter, что, возможно, лучше, чем клиент, подавленный им.например,

Однако это не решает основную проблему отправки недопустимых символов

[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);

    }
}
0 голосов
/ 14 сентября 2012

Комбинация сообщения Binary Worrier со вставленным фильтром специальных символов работает очень хорошо для фильтрации объекта перед его возвращением:

public List<MyData> MyWebServiceMethod()
{
    var mydata = GetMyData();
    return Helper.ScrubObjectOfSpecialCharacters<List<MyData>>(mydata);
}

Класс помощника:

public static T ScrubObjectOfSpecialCharacters<T>(T obj)
{
    var serializer = new XmlSerializer(obj.GetType());

    using (StringWriter writer = new StringWriter())
    {
        serializer.Serialize(writer, obj);

        string content = writer.ToString();

        content = FixSpecialCharacters(content);

        using (StringReader reader = new StringReader(content))
        {
            obj = (T)serializer.Deserialize(reader);
        }
    }
    return obj;
}
public static string FixSpecialCharacters(string input)
{
    if (string.IsNullOrEmpty(input)) return input;

    StringBuilder output = new StringBuilder();
    for (int i = 0; i < input.Length; i++)
    {
        int charCode = (int)input[i];
        switch (charCode)
        {
            case 8211:
            case 8212:
                {
                    // replaces short and long hyphen
                    output.Append('-');
                    break;
                }
            default:
                {
                    if ((31 < charCode && charCode < 127) || charCode == 9)
                    {
                        output.Append(input[i]);
                    }
                    break;
                }
        }
    }
    return output.ToString();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...