XmlDictionaryReader修改xml命名空间别名

本文关键字:别名 命名空间 xml 修改 XmlDictionaryReader | 更新日期: 2023-09-27 18:05:52

我为WCF服务设置了以下XML输入。我使用XmlReader验证消息,并用新消息替换它。在此过程中,xml命名空间别名从xmlns:soapenv更改为xmlns:s

为了在重新创建消息时保持名称空间别名,需要在下面的c#代码中做哪些更改?

参考WCF消息正文显示…流……& lt;/s: Body>修改后查看正确的已替换消息内容。

来自WCF可扩展性-消息检查器

WCF消息对象只能被"消费"一次——"消费"意味着读取、写入或复制。消息体本质上是一个只读一次的流,因此一旦它被消耗,就不能再次使用。因此,如果在检查器代码中读取消息,WCF运行时将无法在其管道的其余部分中重用该消息(即,将其编码为作为回复发送或将其解析为操作参数)。因此,如果检查器代码需要读取消息,则检查器有责任重新创建消息。

输入

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tem="http://tempuri.org/">
<soapenv:Header>
<To soapenv:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">http://local:54956/Service1.svc</To>
<Action soapenv:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">http://tempuri.org/IService1/GetData</Action>
</soapenv:Header>
<soapenv:Body>
  <tem:GetData>
     <!--Optional:-->
     <tem:value>4</tem:value>
  </tem:GetData>
</soapenv:Body>
</soapenv:Envelope>

 private void MyInspectorsValidateMessageBody(ref System.ServiceModel.Channels.Message message, bool isARequest)
    {
        string originalMessageText = message.ToString();
        if (!message.IsFault)
        {
            XmlDictionaryReaderQuotas quotas = new XmlDictionaryReaderQuotas();
            XmlReader bodyReader = message.GetReaderAtBodyContents().ReadSubtree();
            //Settings
            XmlReaderSettings wrapperSettings = new XmlReaderSettings();
            wrapperSettings.CloseInput = true;
            wrapperSettings.ValidationFlags = XmlSchemaValidationFlags.None;
            wrapperSettings.ValidationType = ValidationType.Schema;
            //Add a event handler for ValidationEventHandler of XmlReaderSettings
            //Validation happens while read of xml instance
            //wrapperSettings.ValidationEventHandler += new ValidationEventHandler(MyHandlerForXMLInspectionErrors);
            XmlReader wrappedReader = XmlReader.Create(bodyReader, wrapperSettings);
            this.isRequest = isARequest;
            MemoryStream memStream = new MemoryStream();
            XmlDictionaryWriter xdw = XmlDictionaryWriter.CreateBinaryWriter(memStream);
            xdw.WriteNode(wrappedReader, false);
            xdw.Flush(); memStream.Position = 0;
            XmlDictionaryReader xdr = XmlDictionaryReader.CreateBinaryReader(memStream, quotas);
            //Reconstruct the message with the validated body
            Message replacedMessage = Message.CreateMessage(message.Version, null, xdr);
            replacedMessage.Headers.CopyHeadersFrom(message.Headers);
            replacedMessage.Properties.CopyProperties(message.Properties);
            message = replacedMessage;
            string replacedMessageText = replacedMessage.ToString();
        }
    }

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header>
<To s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">http://local:54956/Service1.svc</To>
<Action s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">http://tempuri.org/IService1/GetData</Action>
</s:Header>
<s:Body>... stream ...</s:Body>
</s:Envelope>

XmlDictionaryReader修改xml命名空间别名

不,它没有改变名称空间。它改变了用于引用到名称空间的前缀,但在这两种情况下,名称空间本身都是"http://schemas.xmlsoap.org/soap/envelope/"

从原始文档:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" 
                  xmlns:tem="http://tempuri.org/">

输出:

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">

不应该关心使用的前缀是什么-重要的是实际命名空间的URI