错误验证邮件正文

时间:2011-05-02 14:37:30

标签: c# wcf

我正在尝试验证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消息(其中messageBody变量保存正文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"));

3 个答案:

答案 0 :(得分:0)

当您调用GetReaderAtBodyContents()时,它将完全执行以下操作:从Body内容开始,获取整个消息的Reader。当您到达身体内容的末尾时,xreader.Read()将继续阅读消息的其余部分并点击正文的关闭标记。您需要修改while循环以阻止读者点击此操作。试试这个:

int startDepth = xreader.Depth;

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

如果有更优雅的方式,请分享!

答案 1 :(得分: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);
}

答案 2 :(得分:0)

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

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