【问题标题】:How to get raw XML sections from a serialized response message in .NET如何从 .NET 中的序列化响应消息中获取原始 XML 部分
【发布时间】:2020-06-20 16:10:55
【问题描述】:

我有一个从 .NET Web 服务返回的 XML 响应。用于返回响应的 API 是一个序列化响应,它去掉了 XML 的补充部分,因为它不是我无法在 API 中更改的序列化类堆栈的一部分。有没有办法获取原始 XML 响应,以便我可以返回我的响应消息的补充:补充数据部分,或者以某种方式自行获取补充:补充数据 XML 部分?

服务 API 调用是 TestPort.TestPortType response = service.GetTestPortList() 并且返回的响应不包含补充部分,因为它不是 TestPort.TestResponse 堆栈的一部分。

这是通过 Fiddle Analyzer 返回的原始 XML 消息:

    <TestResponse xmlns="urn:oasis:names:tc:legalxml-filing:schema:xsd:TestResponse-4.0" xmlns:org="urn:org:ecf:extensions:Common" xmlns:j="http://niem.tech/niem/domains/jxdm/4.0" xmlns:s="http://niem.tech/niem/structures/2.0" xmlns:nc="http://niem.tech/niem/niem-core/2.0" xmlns:ecf="urn:oasis:names:tc:legalxml-filing:schema:xsd:CommonTypes-4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
          <ecf:Error>
            <ecf:ErrorCode>0</ecf:ErrorCode>
            <ecf:ErrorText>No Error</ecf:ErrorText>
          </ecf:Error>
          <supplemental:supplementalData xmlns:supplemental="urn:oasis:names:tc:legalxml-filing:schema:xsd:supplementalData-4.0">
            <nc:TestID>DATest159647</nc:TestID>
          </supplemental:supplementalData>
    </TestResponse>

这是从 API 返回的 XML 消息,它是一个序列化响应,因此由于补充:supplementalData 部分不是序列化响应的一部分,因此将被忽略。

    <TestResponse xmlns="urn:oasis:names:tc:legalxml-filing:schema:xsd:TestResponse-4.0" xmlns:org="urn:org:ecf:extensions:Common" xmlns:j="http://niem.tech/niem/domains/jxdm/4.0" xmlns:s="http://niem.tech/niem/structures/2.0" xmlns:nc="http://niem.tech/niem/niem-core/2.0" xmlns:ecf="urn:oasis:names:tc:legalxml-filing:schema:xsd:CommonTypes-4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
          <ecf:Error>
            <ecf:ErrorCode>0</ecf:ErrorCode>
            <ecf:ErrorText>No Error</ecf:ErrorText>
          </ecf:Error>
    </TestResponse>

这是我在返回响应后尝试从我的 .Net 托管应用程序中访问的 XML 部分,但它正在从返回的序列化响应中删除。

    <supplemental:supplementalData xmlns:supplemental="urn:oasis:names:tc:legalxml-filing:schema:xsd:supplementalData-4.0">
            <nc:TestID>DATest159647</nc:TestID>
    </supplemental:supplementalData>

【问题讨论】:

  • Web 服务是 WCF 吗?如果是WCF,可以通过IDispatchMessageInspector截取消息,得到原始的XML部分。关于IDispatchMessageInspector的更多信息,请参考以下链接:docs.microsoft.com/en-us/dotnet/api/…
  • 是的,Web 服务是 WCF 服务,我正在托管 WCF 服务。在我这边,服务主机部分是一个调用 API 方法。我可以在服务的托管控制台部分使用 IDispatchMessageInspector,还是只能在应用程序本身的服务端使用。 IDispatchMessageInspector 是否易于实现以仅获取原始 xml 响应?
  • 如何将 IDispatchMessageInspector 包裹在 API 调用方法周围以获取 xml 响应?

标签: c# .net wcf


【解决方案1】:

使用 Xml Linq。我从文件中读取了一个字符串。您可以使用类似的代码来获取响应字符串并创建一个 xdocument。

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

namespace ConsoleApplication1
{
    class Program
    {
        const string FILENAME = @"c:\temp\test.xml";
        static void Main(string[] args)
        {
            string xml = File.ReadAllText(FILENAME);
            XDocument doc = XDocument.Parse(xml);

            XElement supplementalData = doc.Descendants().Where(x => x.Name.LocalName == "supplementalData").FirstOrDefault();
            XNamespace supplemental = supplementalData.GetNamespaceOfPrefix("supplemental");
            XNamespace nc = supplementalData.GetNamespaceOfPrefix("nc");

            string TestID = (string)supplementalData.Element(nc + "TestID");

        }
    }
}

【讨论】:

  • 感谢您的回复。但是,我的 .Net 应用程序正在调用这样的 API 方法 TestPort.TestPortType response = service.GetTestPortList()。 TestPort.TestPortType 是一个序列化类,它剥离了 XML 响应的补充:补充数据部分,因为它不是序列化 TestPort.TestPortType 类的一部分。不知何故,我需要访问supplemental:supplementalData 部分。
  • 类是如何生成的? XML 序列化仅在类中的反序列化器属性。所以你的课程有问题。通常有一个用于构建类的模式。您的类可能是使用较旧版本的模式构建的,您的类需要更新。或者你得到的 xml 很糟糕,不符合架构要求。 xml 的补充部分可能需要不同的模式,并且您的类是根据补充模式构建的。
  • 是的,问题是提供给我们的 API WSDL 具有 TestResponse 消息的序列化类,但不幸的是,它不包括嵌入在消息中的补充:supplementalData 部分的序列化我需要并且当返回序列化响应时它不会被加载。所以我需要以某种方式访问​​原始 XML 部分。
  • 你有网址吗?你需要 API 吗?可以直接连接到 c# 中的 URL。
【解决方案2】:

如果服务器端截获SOAP消息,需要实现IDispatchMessageInspector接口。

public class ServerMessageLogger : IDispatchMessageInspector
    {
        public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
        {

            Console.WriteLine(request);
            return null;
        }

        public void BeforeSendReply(ref Message reply, object correlationState)
        {
            Console.WriteLine(reply);
        }
    }

Request 是服务器端从客户端接收到的 SOAP 消息。 如果客户端截获SOAP消息,需要实现IClientMessageInspector接口。

 public class ClientMessageLogger : IClientMessageInspector
    {
        public void AfterReceiveReply(ref Message reply, object correlationState)
        {
            Console.WriteLine(reply);
        }

        public object BeforeSendRequest(ref Message request, IClientChannel channel)
        {
            Console.WriteLine(request);
            return null;
        }
    }

我们需要将实现IDispatchMessageInspector或IClientMessageInspector的类添加到服务端或客户端的行为中。

 [AttributeUsage(AttributeTargets.Interface | AttributeTargets.Class, AllowMultiple = false)]
    public class CustContractBehaviorAttribute : Attribute, IContractBehavior, IContractBehaviorAttribute,IOperationBehavior
    {
        public Type TargetContract => throw new NotImplementedException();

        public void AddBindingParameters(ContractDescription contractDescription, ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
        {
            return;
        }

        public void AddBindingParameters(OperationDescription operationDescription, BindingParameterCollection bindingParameters)
        {
            throw new NotImplementedException();
        }

        public void ApplyClientBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, ClientRuntime clientRuntime)
        {
            clientRuntime.ClientMessageInspectors.Add(new ClientMessageLogger());
        }

        public void ApplyClientBehavior(OperationDescription operationDescription, ClientOperation clientOperation)
        {
            throw new NotImplementedException();
        }

        public void ApplyDispatchBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, DispatchRuntime dispatchRuntime)
        {
            dispatchRuntime.MessageInspectors.Add(new ServerMessageLogger());
        }

        public void ApplyDispatchBehavior(OperationDescription operationDescription, DispatchOperation dispatchOperation)
        {
            
        }

        public void Validate(ContractDescription contractDescription, ServiceEndpoint endpoint)
        {
            return;
        }

        public void Validate(OperationDescription operationDescription)
        {
            throw new NotImplementedException();
        }
    }

最后,我们需要将此行为应用于服务。

    [CustContractBehavior]
    public interface IService1
    {...

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-07-05
    • 1970-01-01
    • 1970-01-01
    • 2021-10-31
    • 2023-04-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多