【问题标题】:Problem serializing SOAP xml nodes within a WCF service在 WCF 服务中序列化 SOAP xml 节点时出现问题
【发布时间】:2019-08-12 22:39:18
【问题描述】:

有人可以帮助我理解为什么当我收到一个肥皂信封时,当接收对象序列化肥皂体时,我没有收到父节点中的所有后代节点?

合约接口类

    namespace AssemblyMDEPort
    {
        [ServiceContract(Name = "AssemblyMDEPort", Namespace = "urn:oasis:names:tc:legalxml:wsdl:WebServicesProfile-Definitions-4.0")]
        [XmlSerializerFormat]
        public interface IAssemblyMDEPort
        {
            [OperationContract(ReplyAction = "*", Action = "urn:oasis:names:tc:legalxml:wsdl:WebServicesProfile-Definitions-4.0/AssemblyMDEPort/NotifyCompleteRequest")]
            [XmlSerializerFormat(SupportFaults = true)]
            NotifyCompleteResponse NotifyReviewComplete(NotifyCompleteRequest request);
        }
    }

这是当soap信封到达我们的服务端点时执行的客户端soap接口方法。

 public NotifyCompleteResponse NotifyReviewComplete(NotifyCompleteRequest request)

这是我们的 SOAP 对象,它处理传入的 SOAP 信封的序列化。

[System.ServiceModel.MessageContractAttribute(IsWrapped = false)]
public partial class NotifyCompleteRequest  
{
    [System.ServiceModel.MessageBodyMemberAttribute(Namespace = "urn:oasis:names:tc:legalxml:wsdl:WebServicesProfile-Definitions-4.0", Order = 0)]
    public XElement NotifyCompleteRequestMessage;

    public NotifyFilingReviewCompleteRequest()
    {
    }
}

这是发送到服务的示例 SOAP 信封

    <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:urn="urn:oasis:names:tc:legalxml:wsdl:WebServicesProfile-Definitions-4.0">
       <soapenv:Header/>
       <soapenv:Body>
            <NotifyCompleteRequestMessage xmlns="urn:oasis:names:tc:legalxml:wsdl:WebServicesProfile-Definitions-4.0">
    <SendingMDELocationID xmlns="urn:oasis:names:tc:legalxml:schema:xsd:CommonTypes-4.0">
        <IdentificationID xmlns="http://niem.gov/niem/niem-core/2.0"></IdentificationID>
    </SendingMDELocationID>
                <SendingMDEProfileCode xmlns="urn:oasis:names:tc:legalxml:schema:xsd:CommonTypes-4.0">urn:oasis:names:tc:legalxml:schema:xsd:WebServicesMessaging-2.0</SendingMDEProfileCode>
                <ReviewCallbackMessage xmlns="urn:oasis:names:tc:legalxml-courtfiling:schema:xsd:ReviewFilingCallbackMessage-4.0" xmlns:nc="http://niem.gov/niem/niem-core/2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
                    <nc:DocumentFiledDate>
                        <nc:DateTime>2018-06-07T13:55:56.0Z</nc:DateTime>
                    </nc:DocumentFiledDate>
                </ReviewCallbackMessage>
            </NotifyCompleteRequestMessage>         
       </soapenv:Body>
    </soapenv:Envelope>

NotifyCompleteRequestMessage XElement 属性仅与第一个节点一起加载,而不是像下面这样的所有后代,我们需要在 NotifyCompleteRequestMessage 属性中加载信封正文中的所有元素节点。必须有办法做到这一点。

<SendingMDELocationID xmlns="urn:oasis:names:tc:legalxml:schema:xsd:CommonTypes-4.0">
    <IdentificationID xmlns="http://niem.gov/niem/niem-core/2.0"></IdentificationID>
</SendingMDELocationID>

【问题讨论】:

  • 节点上没有soapenv之类的命名空间。所以对象上方方括号中的属性必须有一个命名空间“”(空字符串)。
  • 感谢您的帮助。您是在谈论此语句 [System.ServiceModel.MessageBodyMemberAttribute(Namespace = "urn:oasis:names:tc:legalxml-courtfiling:wsdl:WebServicesProfile-Definitions-4.0", Order = 0)] 并将命名空间设置为“”。我试过了,现在 NotifyCompleteRequestMessage = null,所以什么都没有加载。
  • 我指出了一个需要更改的标签。更多元素也需要更改(或添加括号)。您可能还需要添加 [XmlRoot(ElementName = "ABC", Namespace = "") ] 在类定义之上。 XmlRoot 可用于任何类(不仅仅是第一个节点)。有两种不同类型的命名空间。一个名称类似于 xmlns:soapenv= 和默认命名空间 xmlns=。有时默认命名空间在括号只需要一个空字符串。其他时候,像您这样的默认命名空间确实具有属性。使用示例数据调试创建类并进行序列化。
  • 好的,谢谢。我试图避免创建一堆类来序列化。我要做的就是将完整的 xml 正文加载到一个 XElement 中,我可以使用 Linq 搜索我需要的信息。我不需要将每个节点序列化为它自己的属性。这可能吗。最终,我想要的是 ReviewCallbackMessage 中的数据元素,但它有超过 1 个命名空间。 MessageBodyMemberAttribute 是否支持使用超过 1 个命名空间,或者可能只需要 1 个来进行序列化。这个也不确定。
  • 然后避免序列化。当我不需要 xml 中的所有信息时,我通常只使用 XML Linq (XDOCUMENT) 来解析我需要的内容。

标签: c# .net wcf


【解决方案1】:

该错误可能是由于未定义命名空间 nc。用于测试更正错误。尝试以下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;

namespace ConsoleApplication1
{
    class Program
    {
        const string FILENAME = @"c:\temp\test.xml";
        static void Main(string[] args)
        {
            XDocument doc = XDocument.Load(FILENAME);
            XElement notifyCompleteRequestMessage = doc.Descendants().Where(x => x.Name.LocalName == "NotifyCompleteRequestMessage").FirstOrDefault();
            XNamespace ns = notifyCompleteRequestMessage.GetDefaultNamespace();
            DateTime date = (DateTime)notifyCompleteRequestMessage.Descendants().Where(x => x.Name.LocalName == "DateTime").FirstOrDefault();
        }
    }
}

【讨论】:

  • 嗨 jdweng,谢谢,实际上我只是忘记将命名空间 nc 添加到节点,因为我在发布问题时必须删除一些机密信息。我在上面的问题中更改了它,但在我的原始代码中它是正确的。无论如何,我使用 .net fiddle 运行了您的 xml 示例,它可以工作,您可以在此处看到 dotnetfiddle.net/VcHlaw#,但是我将如何将 XDocument 解析集成到我的 NotifyCompleteRequest 序列化方法中,该方法从入站 SOAP 消息合同接收 XElement。目前,我只得到 SendingMDELocationID 节点。
  • 是否需要序列化,还是直接用XDocument解析
  • 不,我认为我不需要序列化。该服务使用 Mtom 编码,因此公共的 NotifyReviewComplete(NotifyCompleteRequest request) 方法需要返回特定的响应。但是我认为我可以以某种方式将 NotifyReviewComplete 方法更改为除 XElement 之外的方法,但我相信这样做时会出现 500 个错误,因此我认为接口类也需要更改。如果我可以在不序列化的情况下完成这项工作,那就太好了。我发布了合同方法的实际合同界面。非常感谢您的帮助!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-12-19
  • 1970-01-01
  • 2016-12-28
  • 2020-04-11
  • 2013-07-03
  • 1970-01-01
  • 2010-12-11
相关资源
最近更新 更多