ServiceContract 对命名空间的定义如何(为啥)影响功能
Posted
技术标签:
【中文标题】ServiceContract 对命名空间的定义如何(为啥)影响功能【英文标题】:How (why) definition of Namespace by ServiceContract affects functionalityServiceContract 对命名空间的定义如何(为什么)影响功能 【发布时间】:2019-05-01 11:03:56 【问题描述】:我有一个这样的 ServiceContract:
[ServiceContract]
public interface IHttpsServer
[OperationContract]
[XmlSerializerFormat]
void Post(SomeEvent e);
事件定义如下:
[Serializable]
[XmlType(Namespace = "")]
public class SomeEvent
[XmlAttribute("flag")]
public bool m_bFlag;
[XmlElement("Name")]
public string m_strName;
...
此服务由 ServiceHost
托管,带有“BasicHttpBinding”。
我在做什么:
-
启动网络服务
添加对客户端应用上正在运行的 Web 服务的引用
启动客户端并向服务器发送 SomeEvent。
此时我有一个问题 - 将调用 Post-function,但 SomeEvent 为空(所有可为空的字段都是 null
)。
但是,如果我是 ServiceContrat ([ServiceContract(Namespace = "")]
) 的空命名空间,那么它可以正常工作。
为什么会这样?
更新:
我已经执行了几次检查,结果都很奇怪:
-
当由 ServiceContract 和 SomeEvent(
[ServiceContract(Namespace = "http://anynamespace")]
和 [XmlType(Namespace = "http://othernamespace")]
)定义命名空间时,它工作正常。
如果命名空间仅由 ServiceContract([ServiceContract(Namespace = "http://anynamespace")]
和 [XmlType(Namespace = "")]
)定义,那么它不起作用。
如果两个([ServiceContract(Namespace = "")]
和 [XmlType(Namespace = "")]
)都定义了一个空的命名空间,那么它工作正常。
如果 ServiceContract 有一个空的命名空间,但为 SomeEvent 定义了一个命名空间([ServiceContract(Namespace = "")]
和 [XmlType(Namespace = "http://othernamespace")]
),那么它工作正常。
【问题讨论】:
【参考方案1】:嗯,我想,我已经找到了这种行为的原因。
首先我实现了IDispatchMessageInspector
。这使我有可能跟踪来自客户的请求。
来自客户端的请求如下所示:
+ request <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header>
<To s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">https://localhost/</To>
<Action s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">http://tempuri.org/IHttpsServer/Post</Action>
</s:Header>
<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Post xmlns="http://tempuri.org/">
<xml flag="true">
<Name>John</Name>
</xml>
</Post>
</s:Body>
</s:Envelope> System.ServiceModel.Channels.Message System.ServiceModel.Channels.BufferedMessage
过了一会儿我注意到,有一个为Post
节点定义的默认命名空间,而没有为“xml”节点定义的命名空间。所以,我们所拥有的是,此示例中的 xml
是 xmlns="http://tempuri.org/"
的一部分,而不是它定义的空命名空间。
为了检查我的建议,我生成了客户端代码并手动将XmlType
属性添加到SomeEvent
的声明中:
[System.Xml.Serialization.XmlType(Namespace = "")]
在此更改之后,我收到了以下请求:
+ request <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header>
<To s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">https://localhost/</To>
<Action s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">http://tempuri.org/IHttpsServer/Post</Action>
</s:Header>
<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Post xmlns="http://tempuri.org/">
<xml flag="true">
<Name xmlns="">John</Name>
</xml>
</Post>
</s:Body>
</s:Envelope> System.ServiceModel.Channels.Message System.ServiceModel.Channels.BufferedMessage
(有Name
节点定义的默认命名空间)。
之后我的服务就正常了。
我对问题原因的建议:
如果我为事件[XmlType(Namespace = "")]public class SomeEvent ...
定义了空命名空间,则在生成客户端代码时将跳过属性XmlType
。这会在发送请求时将描述事件的 xml 放入ServiceContract
的命名空间中。之后,WCF 无法反序列化事件。
所以问题有两种解决方案:
-
避免使用具有空命名空间的事件(参见用例 2)。
为事件
[XmlType(Namespace = "")]public partial class SomeEvent
添加部分类
【讨论】:
以上是关于ServiceContract 对命名空间的定义如何(为啥)影响功能的主要内容,如果未能解决你的问题,请参考以下文章