WCF无法解析SOAP信封,仅获取默认值问题排查
WCF服务无法正确解析SOAP信封的问题排查与修复
问题背景
我创建了一个用于回调服务的WCF服务器,预期远程机器会按照指定信封格式调用该服务以完成任务。但服务无法正确解析SOAP信封:Delivery方法的起始断点能触发,但参数均为默认值(例如GUID全为0,items数组为空)。
待解析的SOAP信封
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"> <s:Header> <ActivityId CorrelationId="e801930b-bf31-4509-b98a-96d106b5513f" xmlns="http://schemas.microsoft.com/2004/09/ServiceModel/Diagnostics">00000000-0000-0000-0000-000000000000 </ActivityId> </s:Header> <s:Body> <Delivery xmlns="http://hsbdserver/calcula/v1"> <info xmlns:i="http://www.w3.org/2001/XMLSchema-instance"> <Guid>5869a5c5-243e-11ed-4a4c-b14560d0fb70</Guid> <Name>Name</Name> </info> <items xmlns:i="http://www.w3.org/2001/XMLSchema-instance"> <Item> <Guid>43207e16-906e-d94a-86f6-753ae31092ef</Guid> <Name>c37fb62f-2729-244b-a082-4be80d952c1e.txt</Name> <ExtDocId i:nil="true"/> <NewUserId i:nil="true" xmlns:a="http://schemas.microsoft.com/2003/10/Serialization/Arrays"/> <NewUserName i:nil="true" xmlns:a="http://schemas.microsoft.com/2003/10/Serialization/Arrays"/> <NewWorkflow>Done</NewWorkflow> <PreviousUserId xmlns:a="http://schemas.microsoft.com/2003/10/Serialization/Arrays"> <a:guid>0e67f61a-d1c6-c448-a11c-82ee8428028a</a:guid> </PreviousUserId> <PreviousUserName xmlns:a="http://schemas.microsoft.com/2003/10/Serialization/Arrays"> <a:string>Nick</a:string> </PreviousUserName> <PreviousWorkflow>Progress</PreviousWorkflow> <Code>xkde</Code> </Item> </items> </Delivery> </s:Body> </s:Envelope>
现有C#实现
[ServiceContract(Namespace = "http://hsbdserver/calcula/v1")] public interface IServerCallback { [OperationContract] void Delivery(Info info, Item[] items); } [DataContract] public class Info { Guid guid; string name; [DataMember] public Guid Guid { get { return guid; } set { guid = value; } } [DataMember] public string Name { get { return name; } set { name = value; } } } [DataContract] public class Item { Guid guid; string name; string extDocId; Guid[] newAssignedUserId; string[] newUserId; Workflow newWorkflow; Guid[] previousUserId; string[] previousUserName; Workflow previousWorkflow; string code; [DataMember] public Guid Guid { get { return guid; } set { guid = value; } } [DataMember] public string Name { get { return name; } set { name = value; } } [DataMember] public string ExtDocId { get { return extDocId; } set { extDocId = value; } } [DataMember] public Guid[] NewAssignedUserId { get { return newAssignedUserId; } set { newAssignedUserId = value; } } [DataMember] public string[] NewUserId { get { return newUserId; } set { newUserId = value; } } [DataMember] public Workflow NewWorkflow { get { return newWorkflow; } set { newWorkflow = value; } } [DataMember] public Guid[] PreviousUserId { get { return previousUserId; } set { previousUserId = value; } } [DataMember] public string[] PreviousUserName { get { return previousUserName; } set { previousUserName = value; } } [DataMember] public Workflow PreviousWorkflow { get { return previousWorkflow; } set { previousWorkflow = value; } } [DataMember] public string Code { get { return code; } set { code = value; } } } public enum Workflow { Progress, Done }
问题原因与修复方案
1. 数据契约命名空间不匹配
SOAP中的Delivery、info、Item等元素都属于http://hsbdserver/calcula/v1命名空间,但你的Info、Item类未指定对应命名空间,WCF无法将XML元素与类正确映射。
修复: 给Info和Item类的DataContract属性添加命名空间:
[DataContract(Namespace = "http://hsbdserver/calcula/v1")] public class Info { ... } [DataContract(Namespace = "http://hsbdserver/calcula/v1")] public class Item { ... }
2. 方法参数与XML元素大小写/名称不匹配
SOAP中的参数是<info>(小写开头)、<items>(小写开头),WCF默认对参数名称大小写敏感,需明确映射XML元素名。
修复: 给Delivery方法参数添加MessageParameter属性指定映射名称:
[OperationContract] void Delivery([MessageParameter(Name = "info")] Info info, [MessageParameter(Name = "items")] Item[] items);
3. Item类属性与XML元素名称不匹配
- SOAP中是
<NewUserId>,你的属性是NewAssignedUserId,名称完全不符; - SOAP中是
<NewUserName>,你的属性是NewUserId,名称错误。
修复: 修改属性名称,或用DataMember的Name属性指定映射:
[DataMember(Name = "NewUserId")] public Guid[] NewUserId { get; set; } [DataMember(Name = "NewUserName")] public string[] NewUserName { get; set; }
4. 枚举类未标记数据契约
SOAP中的<NewWorkflow>、<PreviousWorkflow>是字符串值,枚举类需标记DataContract以确保WCF正确解析。
修复: 给Workflow枚举添加DataContract和EnumMember属性:
[DataContract(Namespace = "http://hsbdserver/calcula/v1")] public enum Workflow { [EnumMember] Progress, [EnumMember] Done }
最终修改后的核心代码
[ServiceContract(Namespace = "http://hsbdserver/calcula/v1")] public interface IServerCallback { [OperationContract] void Delivery([MessageParameter(Name = "info")] Info info, [MessageParameter(Name = "items")] Item[] items); } [DataContract(Namespace = "http://hsbdserver/calcula/v1")] public class Info { [DataMember] public Guid Guid { get; set; } [DataMember] public string Name { get; set; } } [DataContract(Namespace = "http://hsbdserver/calcula/v1")] public class Item { [DataMember] public Guid Guid { get; set; } [DataMember] public string Name { get; set; } [DataMember] public string ExtDocId { get; set; } [DataMember(Name = "NewUserId")] public Guid[] NewUserId { get; set; } [DataMember(Name = "NewUserName")] public string[] NewUserName { get; set; } [DataMember] public Workflow NewWorkflow { get; set; } [DataMember] public Guid[] PreviousUserId { get; set; } [DataMember] public string[] PreviousUserName { get; set; } [DataMember] public Workflow PreviousWorkflow { get; set; } [DataMember] public string Code { get; set; } } [DataContract(Namespace = "http://hsbdserver/calcula/v1")] public enum Workflow { [EnumMember] Progress, [EnumMember] Done }
内容的提问来源于stack exchange,提问作者Isham Mohamed
相关产品推荐
相关产品推荐

