Инспектор сообщений WCF - измените неверный XML SOAP ответ - PullRequest
0 голосов
/ 20 апреля 2020

Я звоню в службу SOAP с использованием клиента WCF. NET. Иногда случается, что служба SOAP отправляет ответ, который не может быть сериализован объектам. NET. Основным виновником здесь является поле даты и времени, в котором они отправляют обратно «24:00:00» вместо «00:00:00».

В этом случае мы получаем следующую ошибку: «The DateTime, представленный строкой, не поддерживается в календаре System.Globalization.GregorianCalendar. "

Чтобы решить эту проблему, я реализовал инспектор сообщений WCF, в котором я хочу изменить сообщение в методе" AfterReceiveReply ". Здесь я хотел бы найти неправильную дату и исправить ее, прежде чем отправить ее обратно клиенту.

Я бы сделал замену путем манипулирования строками (find + replace).

Однако я Я не могу получить содержимое ответного сообщения в виде строки , поскольку он читает его как XML объект (и он содержит недопустимую дату).

exception details

Я также попытался выполнить следующее, но там у меня есть такая же проблема (поскольку мы не можем записать недопустимые значения XML в объект XmlWrite), он выдает ту же ошибку, что и выше.

MemoryStream ms = new MemoryStream();
XmlWriter xw = XmlWriter.Create(ms);
reply.WriteMessage(xw);
xw.Flush();
string body = Encoding.UTF8.GetString(ms.ToArray());
xw.Close();

Объект сообщения принимает только «XmlWriter» или « XmlDictionaryWriter "для записи в другой поток: code snippet

Любые идеи, как получить необработанное содержимое тела ответного сообщения в виде строкового объекта, не анализируя его как XML Документ?

* 102 5 * Заранее спасибо!

С уважением

1 Ответ

1 голос
/ 21 апреля 2020

Если мы предположим, что XmlDictionary, полученный вами от GetReaderAtBodyContents, не проверяет сам по себе, возможно, этого осторожного XmlReader, игнорирующего FormatExceptions, может быть достаточно для перезаписи вашего dateTime.

Вот реализация:

void AfterReceiveReply(ref System.ServiceModel.Channels.Message reply, object state) 
{
    // settings to ignore errors ...
    XmlReaderSettings settings = new XmlReaderSettings();
    settings.ValidationType = ValidationType.Schema;
    settings.ValidationEventHandler += (o,e) => { 
        if (e.Exception != null && !(e.Exception.InnerException is FormatException))
        {
          throw e.Exception;
        }
    }; // ignore formatexception errors

    var xmlrdr = XmlReader.Create(reply.GetReaderAtBodyContents(),settings);
    var ms = new MemoryStream();
    using(var wr = XmlWriter.Create(ms))
    while(xmlrdr.Read())
    {
        // very simple and naive xml copy
         switch(xmlrdr.NodeType) 
         {
             case XmlNodeType.Element:
                 wr.WriteStartElement(xmlrdr.Name);
             break;
             case XmlNodeType.Text:
                 var text = xmlrdr.ReadContentAsString();
                 // names of nodes that are a date
                 if (xmlrdr.Name == "date") 
                 {
                     DateTime dtm;
                     if (!DateTime.TryParse(text, out dtm)) 
                     {
                         // let's assume this is the only thing that can go wrong
                         text = text.Replace("24:00:00", "23:59:59");
                     }
                     wr.WriteString(text);
                     wr.WriteEndElement(); // yeah, well, let's gamble
                 } 
                 else
                 {
                     wr.WriteString(text);
                 }
             break;
             case XmlNodeType.EndElement:
                 wr.WriteEndElement();
             break;
             default:
               // Debug.Assert
             break;
         }
    }
    ms.Position=0;
    // create a new message for the next handler
    reply = System.ServiceModel.Channels.Message.CreateMessage(
       reply.Version, 
       reply.Headers.Action, 
       XmlReader.Create(ms));

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...