【问题标题】:XmlDictionaryReader changes the xml namespace aliasXmlDictionaryReader 更改 xml 命名空间别名
【发布时间】:2013-03-25 16:37:33
【问题描述】:

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

为了在重新创建消息时维护命名空间别名,需要在以下 C# 代码中进行哪些更改?

请参阅WCF message body showing <s:Body>... stream ...</s:Body> after modification 以查看正确替换的消息内容。

来自WCF Extensibility – Message Inspectors

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>

【问题讨论】:

    标签: c# .net wcf


    【解决方案1】:

    不,它没有改变命名空间。它正在更改用于引用命名空间的前缀,但在这两种情况下命名空间本身都是"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。

    【讨论】:

    • 是的,你是对的。但我需要维护alias。我已经更新了问题。
    • @Lijo:为什么 - 有什么关系?不管是什么,IMO 都坏了。
    • @Lijo:别再那样做了。相反,使用适当的 URI 验证元素的存在。当文档实际上是有效的,但碰巧使用了不同的前缀时,你为什么要声称它们是无效的?如果您的验证被破坏,您应该修复验证而不是更改其他内容以符合破坏的要求。
    • 我会考虑修正逻辑。但是我想知道为什么它会改变。我有一个不同版本的检查器(用于其他项目),它维护命名空间别名。知道如何强制别名相同吗?
    • @Lijo:不,我不知道你怎么能强迫他们一样——但我个人不会在这上面浪费任何精力。前缀是偶然的,所以基本上要确保它在使用它的代码中。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-14
    相关资源
    最近更新 更多