gpt4 book ai didi

C# WCF 全局命名空间 - Royal Mail

转载 作者:太空狗 更新时间:2023-10-29 18:31:22 24 4
gpt4 key购买 nike

我有一个正在生成请求的 WCF SOAP 客户端。服务器将此作为无效请求拒绝。我已经使用 SOAPUI 将其追溯到 namespace ,但无法弄清楚如何让客户端产生所需的结果。

客户端是作为来自 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 信封中定义了 namespace ;

<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 方法中,您可以在信封中添加/定义所需的命名空间。

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 信封中,并且所有元素都使用正确的前缀,给我们类似的东西;

<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>

关于C# WCF 全局命名空间 - Royal Mail,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31595770/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com