[英]C# WCF Global Namespaces - Royal Mail
我有一個生成請求的WCF SOAP客戶端。 這被服務器拒絕為無效請求。 我已經使用SOAPUI將其追溯到命名空間,但無法弄清楚如何讓客戶端生成所需的結果。
客戶端是從wsdl生成的Web服務引用,並生成以下SOAP消息;
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header></s:Header>
<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<createShipmentRequest xmlns="http://www.royalmailgroup.com/api/ship/V2">
<integrationHeader>
<dateTime xmlns="http://www.royalmailgroup.com/integration/core/V1">2015-07-23</dateTime>
<version xmlns="http://www.royalmailgroup.com/integration/core/V1">2</version>
<identification xmlns="http://www.royalmailgroup.com/integration/core/V1">
<applicationId>some random number</applicationId>
<transactionId>some reference number</transactionId>
</identification>
</integrationHeader>
</createShipmentRequest>
</s:Body>
</s:Envelope>
正如您所看到的,名稱空間正在各個元素上輸出......
我的工作示例在SOAP Envelope中定義了名稱空間;
<s:Envelope xmlns:v2="http://www.royalmailgroup.com/api/ship/V2" xmlns:v1="http://www.royalmailgroup.com/integration/core/V1" xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<s:Header></s:Header>
<s:Body>
<v2:createShipmentRequest>
<v2:integrationHeader>
<v1:dateTime>2015-07-23</v1:dateTime>
<v1:version>2</v1:version>
<v1:identification>
<v1:applicationId>some random number</v1:applicationId>
<v1:transactionId>some reference number</v1:transactionId>
</v1:identification>
</v2:integrationHeader>
</v2:createShipmentRequest>
</s:Body>
</s:Envelope>
根據我的理解,這不應該有所作為,但服務器只是拒絕請求。 在SOAPUI中修改生成的請求之后,它肯定會導致問題,那么如何將兩個命名空間定義v1和v2移動到SOAP信封中,然后讓正確的元素使用正確的前綴?
我的客戶端使用以下功能啟動;
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;
}
所以事實證明我需要創建一個自定義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中,並且元素都使用正確的前綴給我們類似的東西;
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" xmlns:v2="http://www.royalmailgroup.com/api/ship/V2" xmlns:v1="http://www.royalmailgroup.com/integration/core/V1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<s:Header></s:Header>
<s:Body>
<v2:createShipmentRequest>
<v2:integrationHeader>
<v1:dateTime>2015-07-23T20:37:07.937+01:00</v1:dateTime>
<v1:version>2</v1:version>
<v1:identification>
<v1:applicationId>SOME RANDOM ID</v1:applicationId>
<v1:transactionId>SOME RANDOM ID</v1:transactionId>
</v1:identification>
</v2:integrationHeader>
</v2:createShipmentRequest>
</s:Body>
</s:Envelope>
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.