2013-03-25 166 views
0

我有一個WCF服務的XML輸入。使用XmlReader我正在驗證消息並用新消息替換。在此過程中,xml名稱空間別名從xmlns:soapenv更改爲xmlns:sXmlDictionaryReader更改xml命名空間別名

爲了在重新創建消息時維護命名空間別名,以下C#代碼需要做哪些修改?

請參閱WCF message body showing <s:Body>... stream ...</s:Body> after modification查看正確的替換消息內容。

WCF Extensibility – Message Inspectors

WCF Message對象只能是「消費」一次 - 「消耗」可以指讀,寫或複製。消息體本質上是一次只讀的流,所以一旦消耗,它就不能再被使用。因此,如果在檢查器代碼中讀取消息,那麼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> 

CODE

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(); 

     } 
    } 

OUTPUT

<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> 

回答

2

不,它不改變命名空間。它將用於前綴的前綴更改爲名稱空間,但在兩種情況下,名稱空間本身都是"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。

+0

是的,你是對的。但我需要維護'alias'。我已經更新了這個問題。 – Lijo 2013-03-25 16:40:01

+0

@Lijo:*爲什麼* - 會在乎什麼?無論如何是破壞IMO。 – 2013-03-25 16:41:05

+0

我有一個自定義驗證檢查是否存在xmlns:soapenv。 – Lijo 2013-03-25 16:41:59