2011-05-02 76 views
0

我试图验证WC消息的身体和越来越例外错误验证邮件正文

“到‘ValidateEndElement’方法的调用不匹配‘ValidateElement’方法的相应的呼叫。”

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中和读取器设置在分开的方法

 xmlReaderSettings = new XmlReaderSettings 
      { 
       ValidationType = ValidationType.Schema, 
       Schemas = this.xmlSchemaSet, 
       ConformanceLevel = ConformanceLevel.Auto 
      }; 

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

要创建WCF消息加载(其中消息体变量保持体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")); 
+0

您是否有示例消息? – 2011-05-02 15:04:28

+0

更新了创建消息的代码,基本上任何xmlelement都有一个有效的模式来验证 – 2011-05-02 15:11:01

回答

0

当调用GetReaderAtBodyContents()它会做到这一点:从Body内容开始,获取整个消息的Reader。当您到达正文内容的末尾时,xreader.Read()会继续读取该消息的其余部分并触击正文的close标签。你需要修改你的while循环来阻止读者触及它。试试这个:

int startDepth = xreader.Depth; 

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

如果有更优雅的方式做到这一点,请分享!

0

只需使用:GetReaderAtBodyContents().ReadSubtree() 您将获得一个只读取正文的阅读器。

编辑:

我用它来验证我的请求。 因为我们出色的WebSphere仅发送“HTTP 500内部服务器错误” - 错误(如果xml无效)。

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); 
} 
0

在他们的回答中,@masty错过了自闭标签的情况。它应该是:

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