C#中SOAP序列化忽略对象仅序列化其数据成员的实现方法
如何将SOAP服务的多参数封装为对象且保持WSDL/SOAP结构不变?
要解决这个问题,核心是利用WCF的**MessageContract特性**来精确控制SOAP消息的结构,这样既能在代码层面用一个对象封装所有参数,又能让生成的WSDL和SOAP信封和原来多参数的版本完全一致。
为什么直接用DataContract不行?
如果直接用DataContract封装参数,默认情况下SOAP消息会生成嵌套结构:<DoSomeAction>节点下会多一个<request>子节点,里面才是各个参数属性,这就破坏了你需要的原有结构。而MessageContract允许我们直接把属性映射到<DoSomeAction>的子节点层级,避免额外的嵌套。
具体实现代码
1. 定义请求消息对象(用MessageContract)
// WrapperName要和原方法名一致,Namespace要和服务契约的命名空间匹配 [MessageContract(WrapperName = "DoSomeAction", WrapperNamespace = "http://tempuri.org/")] public class RequestObject { // MessageBodyMember的Name要和原参数名完全一致,Namespace匹配服务命名空间 [MessageBodyMember(Name = "a", Namespace = "http://tempuri.org/")] public string a { get; set; } [MessageBodyMember(Name = "b", Namespace = "http://tempuri.org/")] public string b { get; set; } [MessageBodyMember(Name = "c", Namespace = "http://tempuri.org/")] public DateTime c { get; set; } [MessageBodyMember(Name = "d", Namespace = "http://tempuri.org/")] public OtherEnum d { get; set; } // 依次添加其他参数... }
2. 修改服务契约
[ServiceContract(Namespace = "http://tempuri.org/")] public interface IMyService { [OperationContract] ResultObject DoSomeAction(RequestObject request); }
关键配置说明
MessageContract的WrapperName必须和原方法名(DoSomeAction)完全一致,WrapperNamespace要和服务契约的命名空间(这里是http://tempuri.org/)匹配,这样生成的SOAP请求根节点还是<DoSomeAction>。- 每个
MessageBodyMember的Name要和原来的参数名一一对应(比如原参数a,这里Name设为"a"),Namespace保持和服务命名空间一致,确保每个属性直接作为<DoSomeAction>的子节点,和原有结构完全相同。
这样配置后,生成的WSDL和SOAP信封结构会和你原来多参数的版本毫无差别,客户端调用时不会感知到任何变化,但服务端代码已经实现了参数的封装,更易于维护和扩展。
内容的提问来源于stack exchange,提问作者Sam Burville
相关产品推荐
相关产品推荐

