2013-02-24 2 views
3

Я использовал функцию «Добавить ссылку на службу», чтобы создать прокси-сервер для внешней веб-службы.Заставить WCF создать псевдоним пространства имен xml в прокси-сервере клиента

По умолчанию клиент WCF производит SOAP сообщения, в которых тело сообщения имеет пространство имен украшения, которые выглядят следующим образом:

<s:Body> 
    <BankingTransaction xmlns="http://tempuri.org/"> 
     <amount>0</amount> 
    </BankingTransaction> 
    </s:Body> 

мне нужно тело сообщения, чтобы посмотреть, как это вместо того, чтобы

<s:Body> 
    <bb:BankingTransaction xmlns:bb="http://tempuri.org/"> 
     <amount>0</amount> 
    </bb:BankingTransaction> 
    </s:Body> 

Различие - псевдоним пространства имен «bb» xml. Веб-служба, которую я пытаюсь использовать, требует, чтобы пространство имен xml для полезной нагрузки сообщения было псевдонимом. И по умолчанию клиент WCF должен определить пространство имен как пространство имен DEFAULT. Я искал высоко и низко для решения конфигурации/декорирования этой проблемы и не нашел ее. Если вы не настроите конфигурационное решение, мне придется проверять и изменять каждое сообщение SOAP после его сериализации. #ламе.

Есть ли здесь простое решение?

+0

Это полезно: [Как я могу добавить префикс к WCF ServiceContract пространства имен] (http://stackoverflow.com/questions/2495195/ как-может-я-добавить-а-префикс-к-а-ФОС-ServiceContract-имен)? – publicgk

+0

Спасибо за ваш ответ. Кажется, это сработало. Для этого требуется, чтобы все контракты с сообщениями были изменены вручную. В этом API много. В итоге я нашел более простое решение. Еще раз спасибо. –

ответ

3

Решение этой проблемы заключается в создании пользовательского MessageInspector (через IClientMessageInspector) инспектировать и изменять сообщения SOAP, который производит клиент прокси WCF, перед отправкой их по проводам. Основа для этого решения сформулирована в сообщении Стивена Чэна, "[WCF] How to modify WCF message via custom MessageInspector", с дополнительным фоном от должности Кирка Эвана, "Modify Message Content with WCF".

Я использовал код из сообщения Стивена, чтобы подключить специальную инфраструктуру MessageInspector. Затем я изменил его метод Transformf2(), который работает только с частью сообщения SOAP <Body> в соответствии с моими конкретными потребностями. В моем случае, как описано в исходном вопросе, мне нужно было определить и использовать псевдоним для пространства имен XML целевой целевой службы, xmlns="http://tempuri.org", выше.

Для этого я

  1. должны получить ссылку на узел операции, <BankingTransaction>, который всегда будет первым (и только) ребенок <Body>
  2. удалить атрибут, который задает пространство имен по умолчанию к цели пространства имен
  3. набора префикс (псевдоним пространства имен) для узла

Модифицированный Transform2 (код), который делает это ниже:

private static Message Transform(Message oldMessage) 
    { 
     //load the old message into XML 
     var msgbuf = oldMessage.CreateBufferedCopy(int.MaxValue); 

     var tmpMessage = msgbuf.CreateMessage(); 
     var xdr = tmpMessage.GetReaderAtBodyContents(); 

     var xdoc = new XmlDocument(); 
     xdoc.Load(xdr); 
     xdr.Close(); 

     // We are making an assumption that the Operation element is the 
     // first child element of the Body element 
     var targetNodes = xdoc.SelectNodes("./*"); 

     // There should be only one Operation element 
     var node = (null != targetNodes) ? targetNodes[0] : null; 

     if (null != node) 
     { 
      if(null != node.Attributes) node.Attributes.RemoveNamedItem("xmlns"); 
      node.Prefix = "bb"; 
     } 

     var ms = new MemoryStream(); 
     var xw = XmlWriter.Create(ms); 
     xdoc.Save(xw); 
     xw.Flush(); 
     xw.Close(); 

     ms.Position = 0; 
     var xr = XmlReader.Create(ms); 

     //create new message from modified XML document 
     var newMessage = Message.CreateMessage(oldMessage.Version, null, xr); 
     newMessage.Headers.CopyHeadersFrom(oldMessage); 
     newMessage.Properties.CopyProperties(oldMessage.Properties); 

     return newMessage; 
    } 
}