从WCF SOAP响应中删除名称空间前缀

时间:2017-01-05 11:50:05

标签: c# web-services wcf soap

我正在实现一个WCF服务来替换现有的SOAP服务。访问此服务的客户端无法更改(除配置指向新服务器外)。

当响应名为Ping的方法时,原始服务器响应:

enter image description here

使用WCF重新创建方法,我已设法尽可能接近:

enter image description here

当我从C#控制台应用程序调用原始服务时,会正确填充PingResult。只需将端点的地址更改为我的新服务并重新运行,服务就会返回新的响应,但PingResult为空。我唯一可以看到原始和我的不同之处是PingResult节点上的“ns1”前缀。我猜这是在客户端绊倒反序列化。

所以我的问题是,如何从PingResult中删除ns1前缀?

感谢。

1 个答案:

答案 0 :(得分:1)

你可以试试这个,我从来没有改变过消息,所以我不确定它是否完全像这样,但我已经这样做来记录消息。

实现消息监听器。您有机会处理ExitRequestedHandler方法,您可以访问该消息并更改消息。

然后使用属性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参数在回复中的重要程度,但您可以阅读有关如何构建其值的信息:

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.

  

更新

我在Action config:

中也有这些项目
system.serviceModel

...