C#WCF全球命名空间 – 皇家邮政

我有一个生成请求的WCF SOAP客户端。 这被服务器拒绝为无效请求。 我已经使用SOAPUI将其追溯到命名空间,但无法弄清楚如何让客户端生成所需的结果。

客户端是从wsdl生成的Web服务引用,并生成以下SOAP消息;

     2015-07-23 2  some random number some reference number      

正如您所看到的,名称空间正在各个元素上输出……

我的工作示例在SOAP Envelope中定义了名称空间;

      2015-07-23 2  some random number some reference number      

根据我的理解,这不应该有所作为,但服务器只是拒绝请求。 在SOAPUI中修改我生成的请求之后,它肯定会导致问题,那么如何将两个命名空间定义v1和v2移动到SOAP Envelope,然后让正确的元素使用正确的前缀?

我的客户端使用以下function启动;

 private shippingAPIPortTypeClient GetProxy() { BasicHttpBinding myBinding = new BasicHttpBinding(BasicHttpSecurityMode.Transport); myBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate; shippingClient = new shippingAPIPortTypeClient(myBinding, new EndpointAddress(new Uri(shippingClientSandboxEndpoint), EndpointIdentity.CreateDnsIdentity("api.royalmail.com"), new AddressHeaderCollection())); shippingClient.ClientCredentials.ClientCertificate.Certificate = certificate; return shippingClient; } 

所以事实certificate我需要创建一个自定义MessageFormatter并将其作为行为附加到客户端操作。

对于其他需要这样做的人,你需要3个文件;

首先,您创建一个实现Message的自定义消息类。 在OnWriteStartEnvelope方法中,您可以在Envelope中添加/定义所需的命名空间。

 class RoyalMailMessage: Message { private readonly Message message; public RoyalMailMessage(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("Body", "http://schemas.xmlsoap.org/soap/envelope/"); } protected override void OnWriteBodyContents(XmlDictionaryWriter writer) { this.message.WriteBodyContents(writer); } protected override void OnWriteStartEnvelope(XmlDictionaryWriter writer) { writer.WriteStartElement("s", "Envelope", "http://schemas.xmlsoap.org/soap/envelope/"); writer.WriteAttributeString("xmlns", "v2", null, "http://www.royalmailgroup.com/api/ship/V2"); writer.WriteAttributeString("xmlns", "v1", null, "http://www.royalmailgroup.com/integration/core/V1"); writer.WriteAttributeString("xmlns", "xsi", null, "http://www.w3.org/2001/XMLSchema-instance"); writer.WriteAttributeString("xmlns", "xsd", null, "http://www.w3.org/2001/XMLSchema"); } } 

然后创建一个实现IClientMessageFormatter的自定义类。 这使得我们在上面定义的Message类用于客户端发出的传出请求;

 public class RoyalMailMessageFormatter: IClientMessageFormatter { private readonly IClientMessageFormatter formatter; public RoyalMailMessageFormatter(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 RoyalMailMessage(message); } } 

然后,我们需要创建一个实现IOperationBehavior的自定义类。 这是必需的,因此我们可以将自定义消息格式化程序作为行为附加到服务操作中;

 class RoyalMailIEndpointBehavior: IOperationBehavior { public RoyalMailIEndpointBehavior() {} public void ApplyClientBehavior(OperationDescription description, ClientOperation proxy) { IClientMessageFormatter currentFormatter = proxy.Formatter; proxy.Formatter = new RoyalMailMessageFormatter(currentFormatter); } public void AddBindingParameters(OperationDescription operationDescription, BindingParameterCollection bindingParameters) { } public void ApplyDispatchBehavior(OperationDescription operationDescription, DispatchOperation dispatchOperation) { } public void Validate(OperationDescription operationDescription) { } } 

最后,我们需要将自定义IOperation行为添加到WCF生成的所有服务操作中;

 private shippingAPIPortTypeClient GetProxy() { BasicHttpBinding myBinding = new BasicHttpBinding(BasicHttpSecurityMode.Transport); myBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate; shippingClient = new shippingAPIPortTypeClient(myBinding, new EndpointAddress(new Uri(shippingClientSandboxEndpoint), EndpointIdentity.CreateDnsIdentity("api.royalmail.com"), new AddressHeaderCollection())); shippingClient.ClientCredentials.ClientCertificate.Certificate = certificate; foreach(OperationDescription od in shippingClient.Endpoint.Contract.Operations) { od.Behaviors.Add(new RoyalMailIEndpointBehavior()); } return shippingClient; } 

命名空间现在应该在SOAP Envelope中,并且元素都使用正确的前缀给我们类似的东西;

      2015-07-23T20:37:07.937+01:00 2  SOME RANDOM ID SOME RANDOM ID