首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何访问SOAP响应?

如何访问SOAP响应?
EN

Stack Overflow用户
提问于 2008-11-01 23:17:15
回答 5查看 50.2K关注 0票数 13

(如果这里有什么需要澄清/更详细的话,请告诉我。)

我有一个应用程序(C#,2.*框架),它使用SOAP与第三方with服务进行接口。我使用thinktecture的WSCF外接程序对提供的WSDL创建客户端实现。出于我无法控制的原因,SOAP消息交换使用WSE2.0作为安全性(为了包含WSE2.0引用,必须修改thinctecture实现)。除了“正常”数据包之外,我还附加了一个存储的X509证书和一个来自以前调用的二进制安全令牌到另一个web服务。我们正在使用某种类型的SSL加密--我不知道具体细节。

所有必要的序列化/反序列化都包含在web服务客户端中--这意味着当控件在调用客户端后返回给我时,SOAP响应中包含的整个XML字符串对我来说是不可用的--只是反序列化的组件。别误会我的意思--我觉得这很好,因为这意味着我不需要自己去做。

但是,为了让我有一些值得存储/存档的东西,我必须在根元素中重新序列化数据。这似乎是浪费资源,因为我的结果是在SOAP响应。

现在问我的问题:我如何才能访问SOAP响应的“清除”版本,这样我就不必重新序列化存储/归档的所有内容了?

编辑--我的应用程序是一个运行为网络服务的“无格式”windows应用程序--由WebsphereMQ客户端触发器监视器触发。我不认为ASP.NET解决方案适用。

编辑--因为到目前为止的共识是,我的应用程序是否是ASP.NET并不重要,所以我会给CodeMelt(以及克里斯的)解决方案一个机会。

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2008-11-01 23:49:17

您可以利用现有WSE2.0框架中的SoapExtension来拦截来自服务器的响应。

代码语言:javascript
复制
public class MyClientSOAPExtension : SoapExtension
{

     Stream oldStream;
     Stream newStream;

     // Save the Stream representing the SOAP request or SOAP response into
     // a local memory buffer.
     public override Stream ChainStream( Stream stream )
     {
            oldStream = stream;
            newStream = new MemoryStream();
            return newStream;
     }

    public override void ProcessMessage(SoapMessage message)
    {
       switch (message.Stage)
        {
            case SoapMessageStage.BeforeDeserialize:
                // before the XML deserialized into object.
                break;
            case SoapMessageStage.AfterDeserialize:
                break;        
            case SoapMessageStage.BeforeSerialize:
                break;
            case SoapMessageStage.AfterSerialize:
                break;            
            default:
                throw new Exception("Invalid stage...");
        }       
    }
}

在SoapMessageStage.BeforeDeserialize的阶段,您可以从旧流读取所需的预期数据(例如,使用XmlReader)。然后将预期的数据存储在某个地方供自己使用,还需要将旧的流数据转发到newstream for web服务稍后阶段才能使用这些数据,例如将XML反序列化为对象。

从MSDN记录web服务的所有流量的示例。

票数 9
EN

Stack Overflow用户

发布于 2011-03-03 12:54:11

下面是一个示例,您可以使用Visual引用来设置http://footballpool.dataaccess.eu/data/info.wso?WSDL

基本上,您必须在webservice调用链中插入一个XmlReader spyer,它将重建原始的XML。

我相信这种方式在某种程度上比使用SoapExtensions更简单。

解决方案是受http://orbinary.com/blog/2010/01/getting-the-raw-soap-xml-sent-via-soaphttpclientprotocol/启发的

代码语言:javascript
复制
using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.IO;
using System.Reflection;
using System.Xml;


namespace ConsoleApplication1 {

    public class XmlReaderSpy : XmlReader {
        XmlReader _me;
        public XmlReaderSpy(XmlReader parent) {
            _me = parent;
        }

        /// <summary>
        /// Extracted XML.
        /// </summary>
        public string Xml;

        #region Abstract method that must be implemented
        public override XmlNodeType NodeType {
            get {

                return _me.NodeType;
            }
        }

        public override string LocalName {
            get {
                return _me.LocalName;
            }
        }

        public override string NamespaceURI {
            get {
                return _me.NamespaceURI;
            }
        }

        public override string Prefix {
            get {
                return _me.Prefix;
            }
        }

        public override bool HasValue {
            get { return _me.HasValue; }
        }

        public override string Value {
            get { return _me.Value; }
        }

        public override int Depth {
            get { return _me.Depth; }
        }

        public override string BaseURI {
            get { return _me.BaseURI; }
        }

        public override bool IsEmptyElement {
            get { return _me.IsEmptyElement; }
        }

        public override int AttributeCount {
            get { return _me.AttributeCount; }
        }

        public override string GetAttribute(int i) {
            return _me.GetAttribute(i);
        }

        public override string GetAttribute(string name) {
            return _me.GetAttribute(name);
        }

        public override string GetAttribute(string name, string namespaceURI) {
            return _me.GetAttribute(name, namespaceURI);
        }

        public override void MoveToAttribute(int i) {
            _me.MoveToAttribute(i);
        }

        public override bool MoveToAttribute(string name) {
            return _me.MoveToAttribute(name);
        }

        public override bool MoveToAttribute(string name, string ns) {
            return _me.MoveToAttribute(name, ns);
        }

        public override bool MoveToFirstAttribute() {
            return _me.MoveToFirstAttribute();
        }

        public override bool MoveToNextAttribute() {
            return _me.MoveToNextAttribute();
        }

        public override bool MoveToElement() {
            return _me.MoveToElement();
        }

        public override bool ReadAttributeValue() {
            return _me.ReadAttributeValue();
        }

        public override bool Read() {
            bool res = _me.Read();

            Xml += StringView();


            return res;
        }

        public override bool EOF {
            get { return _me.EOF; }
        }

        public override void Close() {
            _me.Close();
        }

        public override ReadState ReadState {
            get { return _me.ReadState; }
        }

        public override XmlNameTable NameTable {
            get { return _me.NameTable; }
        }

        public override string LookupNamespace(string prefix) {
            return _me.LookupNamespace(prefix);
        }

        public override void ResolveEntity() {
            _me.ResolveEntity();
        }

        #endregion


        protected string StringView() {
            string result = "";

            if (_me.NodeType == XmlNodeType.Element) {
                result = "<" + _me.Name;

                if (_me.HasAttributes) {
                    _me.MoveToFirstAttribute();
                    do {
                        result += " " + _me.Name + "=\"" + _me.Value + "\"";
                    } while (_me.MoveToNextAttribute());

                    //Let's put cursor back to Element to avoid messing up reader state.
                    _me.MoveToElement();
                }

                if (_me.IsEmptyElement) {
                    result += "/";
                }

                result += ">";
            }

            if (_me.NodeType == XmlNodeType.EndElement) {
                result = "</" + _me.Name + ">";
            }

            if (_me.NodeType == XmlNodeType.Text || _me.NodeType == XmlNodeType.Whitespace) {
                result = _me.Value;
            }



            if (_me.NodeType == XmlNodeType.XmlDeclaration) {
                result = "<?"  + _me.Name + " " +   _me.Value + "?>";
            }

            return result;

        }
    }

    public class MyInfo : ConsoleApplication1.eu.dataaccess.footballpool.Info {             

        protected XmlReaderSpy _xmlReaderSpy;

        public string Xml {
            get {
                if (_xmlReaderSpy != null) {
                    return _xmlReaderSpy.Xml;
                }
                else {
                    return "";
                }
            }
        }


        protected override XmlReader GetReaderForMessage(System.Web.Services.Protocols.SoapClientMessage message, int bufferSize) {          
            XmlReader rdr = base.GetReaderForMessage(message, bufferSize);
            _xmlReaderSpy = new XmlReaderSpy((XmlReader)rdr);
            return _xmlReaderSpy;
        }

    }

    class Program {
        static void Main(string[] args) {

            MyInfo info = new MyInfo();
            string[] rest = info.Cities();

            System.Console.WriteLine("RAW Soap XML response :\n"+info.Xml);
            System.Console.ReadLine();
        }
    }
}
票数 6
EN

Stack Overflow用户

发布于 2020-08-20 02:28:22

旧的线程,但如果其他人希望今天这样做:这些想法利用SoapExtension或创建‘间谍’类是很好的,但不工作在.NET核心。

@mting923关于使用IClientMessageInspector方法的建议在.NET Core3.1中有效;参见此处:在将SOAP消息发送到WebService ( .NET )之前获取它

生成的SOAP代理类仍然只是幕后的WCF客户端,因此IClientMessageInspector方法可以工作,即使对于调用旧的SOAP服务的.NET核心Azure函数也是如此。在.NET Core3.1Azure函数中,以下内容适用于我:

代码语言:javascript
复制
public class SoapMessageInspector : IClientMessageInspector
{
    public string LastRequestXml { get; private set; }
    public string LastResponseXml { get; private set; }

    public object BeforeSendRequest(ref Message request, IClientChannel channel)
    {
        LastRequestXml = request.ToString();
        return request;
    }

    public void AfterReceiveReply(ref Message reply, object correlationState)
    {
        LastResponseXml = reply.ToString();
    }
}

public class SoapInspectorBehavior : IEndpointBehavior
{
    private readonly SoapMessageInspector inspector_ = new SoapMessageInspector();

    public string LastRequestXml => inspector_.LastRequestXml;
    public string LastResponseXml => inspector_.LastResponseXml;

    public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
    {
    }

    public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
    {
    }

    public void Validate(ServiceEndpoint endpoint)
    {
    }

    public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
    {
        clientRuntime.ClientMessageInspectors.Add(inspector_);
    }
}

然后它可以像这样设置:

代码语言:javascript
复制
    var client = new ServiceClient();
    var soapInspector = new SoapInspectorBehavior();
    client.Endpoint.EndpointBehaviors.Add(soapInspector);

在调用客户机代理上的web服务调用之后,soapInspector.LastRequestXmlsoapInspector.LastResponseXml将包含原始SOAP请求和响应(作为字符串)。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/256234

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档