- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
我正在处理与 SOAP 服务的接口(interface),该服务似乎不处理默认 namespace ,但可以很好地处理在 SOAP 信封级别声明的全局 namespace 和 namespace 前缀。
问题是 WCF 不会在根目录下创建这些全局命名空间,而是使用显式的无前缀默认命名空间,而服务显然会阻塞这些默认命名空间。现在我知道这并不是 WCF 的错——我相信 WCF 生成的消息是有效的 XML,但服务仍然会阻塞它。
使用 WCF 生成的输出如下所示:
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header>
<h:Security xmlns:h="http://docs.oasis-open.org/wss/2004/01/oasis-
...
</h:Security>
</s:Header>
<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<cancelShipmentRequest xmlns="http://www.royalmailgroup.com/api/ship/V2">
<integrationHeader>
<dateTime xmlns="http://www.royalmailgroup.com/integration/core/V1">2016-03-26T01:44:37.0493801Z</dateTime>
<version xmlns="http://www.royalmailgroup.com/integration/core/V1">2</version>
<identification xmlns="http://www.royalmailgroup.com/integration/core/V1">
<applicationId>RMG-API-G-01</applicationId>
<transactionId>ozhckwej6sxg</transactionId>
</identification>
</integrationHeader>
<cancelShipments>
<shipmentNumber>TTT001908905GB</shipmentNumber>
</cancelShipments>
</cancelShipmentRequest>
</s:Body>
</s:Envelope>
这是行不通的。
使用以下 SOAP 信封(在 SoapUI 中手动)确实有效:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:oas="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
xmlns:v2="http://www.royalmailgroup.com/api/ship/V2"
xmlns:v1="http://www.royalmailgroup.com/integration/core/V1">
<soapenv:Header>
<h:Security xmlns:h="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
...
</h:Security>
</soapenv:Header>
<soapenv:Body>
<v2:cancelShipmentRequest>
<v2:integrationHeader>
<v1:dateTime>2016-03-02T14:55:00Z</v1:dateTime>
<v1:version>2</v1:version>
<v1:identification>
<v1:applicationId>RMG-API-G-01</v1:applicationId>
<v1:transactionId>wftdaife96gv</v1:transactionId>
</v1:identification>
</v2:integrationHeader>
<v2:cancelShipments>
<v2:shipmentNumber>TTT001908905GB</v2:shipmentNumber>
</v2:cancelShipments>
</v2:cancelShipmentRequest>
</soapenv:Body>
</soapenv:Envelope>
两者的区别在于 v1 和 v2 命名空间是在文档顶部全局声明的,而第二个文档中没有局部命名空间声明。
也许我遗漏了什么,但对我来说,WCF 生成的 XML 看起来是有效的,并且在命名空间方面代表相同的文档状态。
我能说的唯一区别是命名空间的声明方式。尽管 WCF 版本似乎有效并生成相同的命名空间,但服务会提示命名空间引用无效。
Failed Schema Validation: Message failed schema validation: Schemas validity error : Element 'xmlns': This element is not expected. Expected is ( {http://www.royalmailgroup.com/api/ship/V2}integrationHeader ).
问题是,强制 WCF 在顶部而不是内联添加命名空间引用的最佳方法是什么?到目前为止,我发现的唯一方法是使用消息检查器并显式重写消息,但如果我完成所有这些,我还不如手动创建消息。
我有什么想法可以尝试强制 WCF 使用显式 namespace 前缀而无需手动重写消息?
最佳答案
所以这个问题的答案是创建一个自定义的 IClientMessageFormatter
和 Message
然后覆盖 Message.OnWriteStartEnvelope()
以显式写出Soap 文档根目录下的所有命名空间。呈现的文档然后重用这些命名空间,而不是在子元素上显式分配命名空间。
为此需要创建 3 个类:
OnWriteStartEnvelope()
这是所有三个的代码:
public class RoyalMailCustomMessage : Message
{
private readonly Message message;
public RoyalMailCustomMessage(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("soapenv", "Envelope", "http://schemas.xmlsoap.org/soap/envelope/");
writer.WriteAttributeString("xmlns", "oas", null, "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd");
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");
}
}
public class RoyalMailMessageFormatter : IClientMessageFormatter
{
private readonly IClientMessageFormatter formatter;
public RoyalMailMessageFormatter(IClientMessageFormatter formatter)
{
this.formatter = formatter;
}
public Message SerializeRequest(MessageVersion messageVersion, object[] parameters)
{
var message = this.formatter.SerializeRequest(messageVersion, parameters);
return new RoyalMailCustomMessage(message);
}
public object DeserializeReply(Message message, object[] parameters)
{
return this.formatter.DeserializeReply(message, parameters);
}
}
[AttributeUsage(AttributeTargets.Method)]
public class RoyalMailFormatMessageAttribute : Attribute, IOperationBehavior
{
public void AddBindingParameters(OperationDescription operationDescription,
BindingParameterCollection bindingParameters)
{ }
public void ApplyClientBehavior(OperationDescription operationDescription, ClientOperation clientOperation)
{
var serializerBehavior = operationDescription.Behaviors.Find<XmlSerializerOperationBehavior>();
if (clientOperation.Formatter == null)
((IOperationBehavior)serializerBehavior).ApplyClientBehavior(operationDescription, clientOperation);
IClientMessageFormatter innerClientFormatter = clientOperation.Formatter;
clientOperation.Formatter = new RoyalMailMessageFormatter(innerClientFormatter);
}
public void ApplyDispatchBehavior(OperationDescription operationDescription, DispatchOperation dispatchOperation)
{ }
public void Validate(OperationDescription operationDescription) { }
}
其中大部分是仪式和样板代码。关键代码片段是连接实际命名空间的 OnWriteStartEnvelope
、格式化程序连接到 WCF 管道的 SerializeRequest
和消息的 ApplyClientBehavior
formatter是附在实际操作上的。
为了连接起来,我将属性添加到服务接口(interface)上的客户端方法 - 在本例中是在 Reference.cs
中生成的 WCF 客户端中。
// CODEGEN: Generating message contract since the operation cancelShipment is neither RPC nor document wrapped.
[System.ServiceModel.OperationContractAttribute(Action="cancelShipment", ReplyAction="*")]
[System.ServiceModel.FaultContractAttribute(typeof(MarvelPress.Workflow.Business.RoyalShippingApi.exceptionDetails), Action="cancelShipment", Name="exceptionDetails")]
[System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults=true)]
[System.ServiceModel.ServiceKnownTypeAttribute(typeof(contactMechanism))]
[System.ServiceModel.ServiceKnownTypeAttribute(typeof(baseRequest))]
[RoyalMailFormatMessage()]
MarvelPress.Workflow.Business.RoyalShippingApi.cancelShipmentResponse1 cancelShipment(MarvelPress.Workflow.Business.RoyalShippingApi.cancelShipmentRequest1 request);
从 WCF 生成的消息现在看起来与预期的一样,所有命名空间都在文档顶部定义:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:oas="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" 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 xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<h:Security>...</h:Security>
</s:Header>
<soapenv:Body>
<v2:cancelShipmentRequest>
<v2:integrationHeader>
<v1:dateTime>2016-04-02T01:04:50.4122473Z</v1:dateTime>
<v1:version>2</v1:version>
<v1:identification>
<v1:applicationId>RMG-API-G-01</v1:applicationId>
<v1:transactionId>fshrxevdnc7n</v1:transactionId>
</v1:identification>
</v2:integrationHeader>
<v2:cancelShipments>
<v2:shipmentNumber>TTT001908905GB</v2:shipmentNumber>
</v2:cancelShipments>
</v2:cancelShipmentRequest>
</soapenv:Body>
</soapenv:Envelope>
有关更多信息和添加格式化程序的通用命名空间,请在此处查看我的相关博客文章:http://weblog.west-wind.com/posts/2016/Apr/02/Custom-Message-Formatting-in-WCF-to-add-all-Namespaces-to-the-SOAP-Envelope
关于c# - WCF 客户端 : Forcing Global Namespaces,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36230835/
我已经在我的电脑上安装了 node.js,当我运行这个命令时它给了我这个错误,我该怎么办??? npm WARN config global `--global`, `--local` are dep
在 PHP 中,我想知道 GLOBAL 和 GLOBALS 之间的区别。 一些例子: print_r($GLOBALS); 最佳答案 这是与同一事物相关的两个不同事物:全局变量。 $GLOBALS -
在某些 SCSS 文件中,我看到以下内容: :global { /* ... */ } 不知道是SCSS特性还是CSS特性。我尝试搜索它,但第一眼找不到任何好的结果。 最佳答案 此运算符用于 CS
我正在考虑向 JSON 添加注释并找到 this script在处理使 JSON 有效之前将它们去除。我只是想了解如何使 JSON.minify() 函数可用? 开始于 (function(globa
在我的 React 应用程序中,我尝试使用 react-widgets package 中包含的 DateTimePicker 组件.我还通过 reactstrap 使用 Bootstrap 4 组件
全局变量的作用域是所有文件,而静态全局变量的作用域只是它所在的文件被宣布。为什么这样? 全局或静态全局变量存储在内存中的什么位置? 最佳答案 有一些混淆,因为 C 中的 static 可能意味着两种不
我尝试从 Marko 组件访问全局变量,但收到 Uncaught ReferenceError: out is not Defined。 class { onClick(event) {
这个 fiddle 在 IE 和 FF 中返回正确的值“5,5”,但在 Chrome 中它返回“5.5” fiddle :http://jsfiddle.net/4tvSH/ Globalize.cu
我对 python 很陌生,我尝试制作一个简单的 GUI 程序。但是,我遇到了一个“问题”,确切地说是一个警告,上面写着:“m”未在全局范围内定义(Python(变量未定义全局))。 我知道如果你想在
将变量初始化为 global var 或调用 globals().update(var) 有什么区别。 谢谢 最佳答案 当你说 global var 您是在告诉 Python var 与在全局上下文中
我正在开发 ASP.NET Web 应用程序,对于未处理的异常,我正在使用Global.asax 文件 我在其中编写了将错误日志写为 的逻辑 Sub Application_Error(ByVal s
这是我的第一篇 StackOverflow 帖子。提前致谢!我在这里找到了很多答案,但在网络上的任何地方都找不到有关我当前问题的任何信息。 =( 我有一个 C# 服务,我已经使用 Visual Stu
问题: 我正在尝试将对我的 MongoDB 数据库的查询结果有效地分配给全局数组。我基本上尝试将对全局数组的引用存储在一个数组中,以便我可以将 for 循环中的查询结果分配给所有这些引用。 这似乎是不
我想看看 Node.js 中 global.process 的构造函数是否存储在任何地方。 例如,在网络中,构造函数很容易获得。例如,window 的构造函数是window.Window。所有构造函数
Tell me about the difference between global.asax and global.asax.cs ? 和 If i click the both file in
全局对象作为顶级词法环境(如果你愿意的话,在作用域链的顶部)。这意味着可以通过直接引用(如变量)访问全局属性: // global code this.foo = 1; // creat
如何修复 Depricated 警告消息 (node:6136) DeprecationWarning: 'GLOBAL' is deprecated, use 'global' 在我的代码中,我使用
在我的本地发布文件夹中,我有 Global.asax 和 Global.asax.cs,其中 Global.asax 未更新(日期为一个月前)和 Global.asax .cs 已更新。 我检查了 G
我有下面的代码,自动生成: $ react-native init RepeatAloud 应用程序.tsx /** * Sample React Native App * https://git
在 Node-red 仪表板上,我想以不同的流量显示相机流。背后的想法是在每个流上显示相机。 为了显示相机流,我使用了 iFrame。一切正常,但我必须为每个单独的 iFrame 提供流的 URL。
我是一名优秀的程序员,十分优秀!