代码之家  ›  专栏  ›  技术社区  ›  Romias

在将SOAP消息发送到.NET中的Web服务之前获取该消息

  •  13
  • Romias  · 技术社区  · 17 年前

    我正在调用外部HTTPS Web服务。

    有没有办法在发送SOAP消息之前查看它?

    4 回复  |  直到 17 年前
        1
  •  14
  •   dizzy128    10 年前

    您只需在Submit之前序列化请求对象,如下所示:

    var sreq = new SomeSoapRequest();
    
    // ... fill in here ...
    
    var serxml = new System.Xml.Serialization.XmlSerializer(sreq.GetType());
    var ms = new MemoryStream();
    serxml.Serialize(ms, sreq);
    string xml = Encoding.UTF8.GetString(ms.ToArray());
    
    // in xml string you have SOAP request
    
        3
  •  9
  •   mting923    8 年前

    在同一项目中创建如下类:

    public class ClientMessageInspector : System.ServiceModel.Dispatcher.IClientMessageInspector
        {
            #region IClientMessageInspector Members
            public string LastRequestXml { get; private set; }
    
            public void AfterReceiveReply(ref System.ServiceModel.Channels.Message reply, object correlationState)
            {
    
            }
    
            public object BeforeSendRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel)
            {
                string requestHeaderName = request.Headers.Action.Replace("urn:#",string.Empty);
                LastRequestXml = request.ToString();
                string serializedRequestFile = string.Format(requestHeaderName + "_request_{0}.xml", DateTime.Now.ToString("yyyyMMddHHmmss"));
                string exportedFolder = ConfigurationManager.AppSettings["SubmittedRequestXmLocation"];
                printSoapRequest(request, exportedFolder, serializedRequestFile);
    
                return request;
            }
    
            public void printSoapRequest(System.ServiceModel.Channels.Message request, string exportedFolder, string fileName)
            {
                if (exportedFolder.Equals(string.Empty))
                    return;
    
                if (!Directory.Exists(exportedFolder))
                {
                    Directory.CreateDirectory(exportedFolder);
                }
                string exportedFile = string.Format("{0}\\{1}", exportedFolder, fileName);
                if (File.Exists(exportedFile))
                {
                    File.Delete(exportedFile);
                }
    
                string strRequestXML = request.ToString();
                XDocument xDoc = XDocument.Parse(strRequestXML);
                XmlWriter xw = XmlWriter.Create(exportedFile);
                xDoc.Save(xw);
                xw.Flush();
                xw.Close();
                LogOutput("Request file exported: " + exportedFile);
    
            }
    
        }
    
        public class CustomInspectorBehavior : IEndpointBehavior
        {
            private readonly ClientMessageInspector clientMessageInspector = new ClientMessageInspector();
    
            public string LastRequestXml
            {
                get { return clientMessageInspector.LastRequestXml; }
            }
    
            public string LastResponseXml
            {
                get { return clientMessageInspector.LastRequestXml; }
            }
    
            public void AddBindingParameters(
                ServiceEndpoint endpoint,
                System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
            {
            }
    
            public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
            {
            }
    
            public void Validate(ServiceEndpoint endpoint)
            {
            }
    
            public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
            {
                clientRuntime.MessageInspectors.Add(clientMessageInspector);
            }
        }
    

    然后你可以这样称呼它:

    ProxyClass _class = new ProxyClass();
    var requestInterceptor = new CustomInspectorBehavior();
               _client.Endpoint.Behaviors.Add(requestInterceptor);
    

    当您调用服务方法时,它将自动执行拦截器并打印输出。使用这种方式,您还可以在发送到服务器之前操作soap消息!

        4
  •  7
  •   Andy Gray    6 年前

    其他想法(例如利用SoapExtension,或创建“间谍”类) How do I get access to SOAP response )很有趣,但不能在.NET核心中使用。但生成的SOAP代理类仍然只是一个隐藏的WCF客户机,因此IClientMessageInspector方法非常有效,即使对于调用旧SOAP web服务的.NET核心Azure函数也是如此。

    在上面的示例中,暗示了响应wireup,但未完全显示。此外,在最新的.NET核心API中, MessageInspectors ClientMessageInspectors 和 Behaviors EndpointBehaviors

    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_);
        }
    }
    

    然后可以这样设置:

        var client = new ServiceClient();
        var soapInspector = new SoapInspectorBehavior();
        client.Endpoint.EndpointBehaviors.Add(soapInspector);
    

    在客户端代理上调用web服务调用后, soapInspector.LastRequestXml 和 soapInspector.LastResponseXml

        5
  •  1
  •   Collin Anderson    6 年前

    将其添加到web.config或App.config文件的元素中。它将在项目的bin/Debug文件夹中创建一个trace.log文件。或者,可以使用initializeData属性为日志文件指定绝对路径。

      <system.diagnostics>
        <trace autoflush="true"/>
        <sources>
          <source name="System.Net" maxdatasize="9999" tracemode="protocolonly">
            <listeners>
              <add name="TraceFile" type="System.Diagnostics.TextWriterTraceListener" initializeData="trace.log"/>
            </listeners>
          </source>
        </sources>
        <switches>
          <add name="System.Net" value="Verbose"/>
        </switches>
      </system.diagnostics>
    

    它警告不允许使用maxdatasize和tracemode属性,但它们会增加可记录的数据量,并避免以十六进制记录所有内容。

        6
  •  0
  •   Steven Hunt    12 年前

    1. 像往常一样生成您的web引用。
    2. 编写代码来执行您要调用的任何web方法。
    3. 创建处理程序或控制器/操作,并按如下方式提取请求流:

    using (var reader = new System.IO.StreamReader(Request.InputStream)) { result = reader.ReadToEnd(); }

    1. 在其上放置断点并在调试模式下运行。
    2. 在客户端上,将SOAP请求的Url设置为新的控制器/处理程序。
    3. 运行你的客户。您应该用SOAP消息捕获web应用程序上的断点。