开发者

error validating message body

开发者 https://www.devze.com 2023-03-02 10:47 出处:网络
I am trying to validate a wc message\'s body and getting exception \"The call to the \'ValidateEndElement\' method does not match a corresponding call to \'ValidateElement\' method.\"

I am trying to validate a wc message's body and getting exception

"The call to the 'ValidateEndElement' method does not match a corresponding call to 'ValidateElement' method."

using (MessageBuffer messageBuffer = message.CreateBufferedCopy(int.MaxValue))
{
      Message copiedMessage = messageBuffer.CreateMessage();
      using (var xreader = XmlReader.Create(
            copiedMessage.GetReaderAtBodyContents(), xmlReaderSettings))
      {
          while (xreader.Read()) ;
      }
            message = messageBuffer.CreateMessage();
}

XmlSchemaSet and reader settings are loaded in separate method

        xmlReaderSettings = new XmlReaderSettings
           {
               ValidationType = ValidationType.S开发者_开发知识库chema,
               Schemas = this.xmlSchemaSet,
               ConformanceLevel = ConformanceLevel.Auto
           };

        xmlReaderSettings.ValidationEventHandler += (o, e) =>
        {
            if (e.Severity == XmlSeverityType.Error)
                throw new ContractXmlSchemaValidationException(e.Message);
        };

To create a wcf message ( where messageBody variable holds the body xml)

Message  msg = null;
var reader = XmlReader.Create(new StringReader(messageBody));
msg = Message.CreateMessage(MessageVersion.Soap12, "http://mysoapAction", reader);
msg.Headers.Add(MessageHeader.CreateHeader("To", "http://schemas.microsoft.com/ws/2005/05/addressing/none", "http://localhost/Service/Service1.svc"));


When you call GetReaderAtBodyContents() it will do exactly that: get a Reader for the whole message, starting at the Body contents. When you reach the end of your body content, xreader.Read() is continuing to read the rest of the message and hitting the close tag for the body. You need to modify your while loop to stop the reader from hitting this. Try this:

int startDepth = xreader.Depth;

while (xreader.Read())
{
    if (xreader.Depth == startDepth && xreader.NodeType == XmlNodeType.EndElement)
    {
        break;
    }
}

If there's a more elegant way of doing this, please share!


simply use: GetReaderAtBodyContents().ReadSubtree() you will get a reader, which just reads the body.

EDIT:

I used it to validate my request. Because our awesome WebSphere sends just an "HTTP 500 Internal Server Error"-Error if the xml is invalid.

var settings = new XmlReaderSettings();

settings.Schemas.Add(_schemas);
settings.CloseInput = true;
settings.ValidationType = ValidationType.Schema;
settings.ValidationFlags = XmlSchemaValidationFlags.AllowXmlAttributes
                         | XmlSchemaValidationFlags.ProcessInlineSchema
                         | XmlSchemaValidationFlags.ReportValidationWarnings;
settings.ValidationEventHandler += ValidationEventHandler;


using (XmlDictionaryReader bodyReader = message.GetReaderAtBodyContents())
using (XmlReader documentReader = XmlReader.Create(bodyReader.ReadSubtree(), settings))
{
    documentReader.MoveToContent();

    using (var memory = new MemoryStream())
    //copy & validate in one step :)    
    using (XmlWriter writer = XmlWriter.Create(memory))
    {
        writer.WriteNode(documentReader, false);
        writer.Flush();
    }
#if DEBUG    
    memory.Seek(0, SeekOrigin.Begin);
    string xml = new StreamReader(memory).ReadToEnd();
#endif
    memory.Seek(0, SeekOrigin.Begin);

    message = Message.CreateMessage(message.Version, null, XmlReader.Create(memory));
    message.Headers.CopyHeadersFrom(message);
}


In their answer, @masty missed case with self-closing tags. It should be:

int startDepth = xreader.Depth;                    
while (xreader.Read())
{                       
  if (xreader.Depth == startDepth && (xreader.IsEmptyElement || xreader.NodeType == XmlNodeType.EndElement))
   {
      break;
   }
}
0

精彩评论

暂无评论...
验证码 换一张
取 消