扩展原因
有一WebService,在工程中添加Web Service引用后调用不成功,但是用SoapUI测试正常
分析
用tctTrace跟踪报文后发现wcf生成的报文命名空间与SoapUI的不一样
解决办法
扩展WCF Message,具体如下:
第一步、自定义Message:
public class MyCustomMessage : Message { private readonly Message message; public MyCustomMessage(Message message) { this.message = message; } public override MessageHeaders Headers { get { return this.message.Headers; } } public override MessageProperties Properties { get { return this.message.Properties; } } public override MessageVersion Version { get { return this.message.Version; } } protected override void OnWriteStartBody(XmlDictionaryWriter writer) { writer.WriteStartElement("soapenv", "Body", null); } protected override void OnWriteBodyContents(XmlDictionaryWriter writer) { this.message.WriteBodyContents(writer); } protected override void OnWriteStartEnvelope(XmlDictionaryWriter writer) { writer.WriteStartElement("soapenv", "Envelope", @"http://schemas.xmlsoap.org/soap/envelope/"); writer.WriteAttributeString("xmlns", "ws", null, @"此处为自定义的命名空间"); } }
第二步、自定义IClientMessageFormatter,在其中应用MyCustomMessage类
public class MyCustomMessageFormatter : IClientMessageFormatter { IClientMessageFormatter formatter; public MyCustomMessageFormatter(IClientMessageFormatter formatter) { this.formatter = formatter; } public object DeserializeReply(Message message, object[] parameters) { return this.formatter.DeserializeReply(message, parameters); } public Message SerializeRequest(MessageVersion messageVersion, object[] parameters) { var message = this.formatter.SerializeRequest(messageVersion, parameters); return new MyCustomMessage(message); } }
第三步:实现IOperationBehavior
[AttributeUsage(AttributeTargets.Method)] public class MobilityProviderFormatMessageAttribute : Attribute, IOperationBehavior { public void AddBindingParameters(OperationDescription operationDescription, BindingParameterCollection bindingParameters) { } public void ApplyClientBehavior(OperationDescription operationDescription, ClientOperation clientOperation) { var serializerBehavior = operationDescription.Behaviors.Find<DataContractSerializerOperationBehavior>(); if (clientOperation.Formatter == null) { ((IOperationBehavior)serializerBehavior).ApplyClientBehavior(operationDescription, clientOperation); } IClientMessageFormatter innerDispatchFormatter = clientOperation.Formatter; clientOperation.Formatter = new MyCustomMessageFormatter(innerDispatchFormatter); } public void ApplyDispatchBehavior(OperationDescription operationDescription, DispatchOperation dispatchOperation) { } public void Validate(OperationDescription operationDescription) { } }
第四步:应用自定义Behaivor
static void Main(string[] args) { WMS.ERPWSService2Client client = new WMS.ERPWSService2Client(); foreach (var operation in client.ChannelFactory.Endpoint.Contract.Operations) { operation.Behaviors.Add(new MobilityProviderFormatMessageAttribute()); } }
参考资料:http://msdn.microsoft.com/en-us/magazine/cc163302.aspx