2017-01-05 5 views
0

Я использую службу WCF для замены существующей службы SOAP. Клиенты, которые обращаются к этой службе, не могут быть изменены (кроме конфигурации на новый сервер).Удалить префикс пространства имен из ответа WCAP SOAP

При ответе на метод, называемый Ping, исходный сервер отвечает:

enter image description here

Воссоздание метод с WCF, мне удалось получить так близко, как:

enter image description here

Когда я вызываю исходную службу из приложения консоли C#, PingResult заполняется правильно. Просто изменив адрес конечной точки на мою новую услугу и повторный запуск, служба возвращает новый ответ, но PingResult имеет значение null. Единственное, что я вижу, это отличие между оригиналом и моим - префикс «ns1» на узле PingResult. Я предполагаю, что это отключение десериализации на стороне клиента.

Так что мой вопрос в том, как я могу удалить префикс ns1 из PingResult?

Спасибо.

+0

Вы можете издеваться службой, вернуть буквальную строку XML без имен и посмотреть, может ли клиент десериализации его ? – Crowcoder

+0

@Crowcoder Это именно то, над чем я сейчас работаю, ура. – DavidGouge

+0

@Crowcoder Отправка строки xml с удаленным префиксом пространства имен полностью десериализируется клиентом. Если в рабочем процессе wcf есть точка, где я могу редактировать xml до его отправки, это было бы идеально. – DavidGouge

ответ

1

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

Внедрение слушателя сообщений. У вас есть возможность обрабатывать метод BeforeSendReply, где у вас есть доступ к сообщению и возможность его изменения.

Затем украсить свой контракт класс реализации с атрибутом [MessageListenerBehavior]

using System; 
using System.Collections.Generic; 
using System.Diagnostics; 
using System.IO; 
using System.Linq; 
using System.ServiceModel.Channels; 
using System.ServiceModel.Configuration; 
using System.ServiceModel.Description; 
using System.ServiceModel.Dispatcher; 
using System.Text; 
using System.Threading.Tasks; 
using System.Xml; 
using System.Xml.Linq; 

namespace YourNamespace 
{ 
    public class MessageListenerBehavior : Attribute, IDispatchMessageInspector, IServiceBehavior 
    { 
     public object AfterReceiveRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel, System.ServiceModel.InstanceContext instanceContext) 
     { 
      return null; 
     } 

     public void BeforeSendReply(ref System.ServiceModel.Channels.Message reply, object correlationState) 
     { 

      Message msg = reply.CreateBufferedCopy(int.MaxValue).CreateMessage(); 

      try 
      { 
       //Setup StringWriter to use as input for our StreamWriter 
       //This is needed in order to capture the body of the message, because the body is streamed. 
       using (StringWriter stringWriter = new StringWriter()) 
       using (XmlWriter xmlTextWriter = XmlWriter.Create(stringWriter)) 
       { 
        msg.WriteMessage(xmlTextWriter); 
        xmlTextWriter.Flush(); 
        xmlTextWriter.Close(); 

        string thexml = stringWriter.ToString(); 

        XDocument doc = XDocument.Parse(thexml); 
        // alter the doc here........... 
         Message newMsg = Message.CreateMessage(MessageVersion.Soap11, "http://..something", doc.ToString()); 

       reply = newMsg; 
      } 
      catch (Exception ex) { //handle it } 
     } 

     public void AddBindingParameters(ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase, System.Collections.ObjectModel.Collection<ServiceEndpoint> endpoints, System.ServiceModel.Channels.BindingParameterCollection bindingParameters) 
     { 

     } 

     public void ApplyDispatchBehavior(ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase) 
     { 
      foreach (ChannelDispatcher dispatcher in serviceHostBase.ChannelDispatchers) 
      { 
       foreach (var endpoint in dispatcher.Endpoints) 
       { 
        endpoint.DispatchRuntime.MessageInspectors.Add(new MessageListenerBehavior()); 
       } 
      } 
     } 

     public void Validate(ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase) 
     { 
      //throw new NotImplementedException(); 
     } 
    } 

    public class WcfMessgeLoggerExtension : BehaviorExtensionElement 
    { 
     public override Type BehaviorType 
     { 
      get 
      { 
       return typeof(MessageListenerBehavior); 
      } 
     } 

     protected override object CreateBehavior() 
     { 
      return new MessageListenerBehavior(); 
     } 
    } 
} 

Когда вы Message.CreateMessage я не знаю, сколько вопросы параметров Action в ответ, но вы можете прочитать о том, как построить это значение :

Use the Actionproperty to control the action of the method's input message. Because WCF uses this action to dispatch an incoming message to the appropriate method, messages used within a contract operation must have unique actions. The default action value is a combination of the contract namespace (the default value is "http://tempuri.org/"), the contract name (interface name or the class name, if no explicit service interface is used), the operation name, and an additional string ("Response") if the message is a correlated response. You can override this default with the Action property.

Update

У меня также есть эти пункты в system.serviceModel конфигурации:

<serviceBehaviors> 
    <behavior name="MessageListenerBehavior"> 
     <serviceDebug includeExceptionDetailInFaults="false" /> 
    </behavior> 
    </serviceBehaviors> 

    ... 

<services> 
    <service behaviorConfiguration="MessageListenerBehavior" name="... your service name..."> 

...

+0

Принимается как ответ, так как он отвечает на вопрос выше, но в конце концов мне не нужно было ничего делать, поскольку я восстановил сервер из wsdl клиента, который исправил все проблемы, которые я пытался воспроизвести. Благодаря! – DavidGouge