2008-11-01 29 views
9

(Nếu bất cứ điều gì ở đây cần làm rõ/chi tiết xin vui lòng cho tôi biết.)Làm thế nào để có được quyền truy cập vào phản ứng SOAP

Tôi có một ứng dụng (C#, 2. * framework) có giao diện với một webservice của bên thứ ba sử dụng SOAP. Tôi đã sử dụng bổ trợ WSCF của kiến ​​trúc đối với WSDL được cung cấp để tạo ra việc triển khai phía máy khách. Vì những lý do ngoài tầm kiểm soát của tôi, trao đổi thông điệp SOAP sử dụng WSE2.0 để bảo mật (việc triển khai thực hiện kiến ​​thức phải được sửa đổi để bao gồm tham chiếu WSE2.0). Ngoài gói dữ liệu 'bình thường', tôi đính kèm chứng chỉ X509 được lưu trữ và mã thông báo bảo mật nhị phân từ cuộc gọi trước đó đến một dịch vụ web khác. Chúng tôi đang sử dụng mã hóa SSL của một số loại - tôi không biết chi tiết.

Mọi serialization/deserialization cần thiết được chứa trong máy khách dịch vụ web - nghĩa là khi điều khiển được trả lại cho tôi sau khi gọi cho khách hàng toàn bộ chuỗi XML có trong phản hồi SOAP không có sẵn cho tôi - chỉ là các thành phần được deserialized. Đừng hiểu lầm tôi - tôi nghĩ điều đó tốt vì điều đó có nghĩa là tôi không phải tự làm.

Tuy nhiên, để tôi có thứ gì đó đáng lưu trữ/lưu trữ, tôi phải sắp xếp lại dữ liệu ở phần tử gốc. Điều này có vẻ như một sự lãng phí tài nguyên vì kết quả của tôi là trong phản ứng SOAP.

Bây giờ cho câu hỏi của tôi: Làm cách nào để truy cập vào phiên bản 'rõ ràng' của phản hồi SOAP để tôi không phải sắp xếp lại mọi thứ để lưu trữ/lưu trữ?

Chỉnh sửa- Ứng dụng của tôi là ứng dụng cửa sổ 'vô hình' chạy dưới dạng dịch vụ mạng - được kích hoạt bởi trình theo dõi trình kích hoạt máy khách WebsphereMQ. Tôi không nghĩ rằng các giải pháp ASP.NET sẽ được áp dụng.

Chỉnh sửa - Vì sự nhất trí từ trước đến nay là không quan trọng liệu ứng dụng của tôi có phải là ASP.NET hay không thì tôi sẽ cung cấp giải pháp của CodeMelt (và bằng cách mở rộng của Chris).

Trả lời

8

Bạn có thể sử dụng SoapExtension từ khung công tác WSE2.0 hiện có để chặn các phản hồi từ máy chủ.

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..."); 
     }  
    } 
} 

Ở giai đoạn của SoapMessageStage.BeforeDeserialize, Bạn có thể đọc dữ liệu dự kiến ​​mà bạn muốn từ oldstream (ví dụ sử dụng XmlReader). Sau đó, lưu trữ dữ liệu dự kiến ​​ở đâu đó để bạn sử dụng và bạn cũng cần chuyển tiếp dữ liệu luồng cũ sang luồng mới cho dịch vụ web ở giai đoạn sau để sử dụng dữ liệu, ví dụ: deserialize XML thành các đối tượng.

The sample of logging all the traffic for the web service from MSDN

+0

OK - đó là liên kết tương tự như Chris đã đăng ở trên. Đó là "ASP.NET" khiến tôi cảnh giác. Kể từ khi sự đồng thuận cho đến nay là nó không quan trọng cho dù ứng dụng của tôi là ASP.NET hay không thì tôi sẽ cho nó một shot. –

+0

Vâng, miễn là nó nằm trong chấm chấm để sử dụng dịch vụ. –

+2

@codemeit Tôi không biết liệu tôi có thiếu gì đó không, nhưng lớp này không nên biên dịch vì nó không thực hiện chữ ký 'SoapExtension' trừu tượng' GetInitializer (Loại serviceType) ',' GetInitializer (thuộc tính LogicalMethodInfo methodInfo, SoapExtensionAttribute)) ', và' Khởi tạo (bộ khởi tạo đối tượng) '. – Jez

0

MSDN Library bao gồm mã ví dụ để nhận XML của cả yêu cầu và phản hồi mà bạn có thể sử dụng để lưu trữ nó. Rõ ràng bạn sẽ phải thực hiện một số thay đổi vì ví dụ lưu trữ dữ liệu trong một tệp văn bản, nhưng nó không quá phức tạp.

+0

Xin lỗi - Tôi nên bao gồm rằng tôi không sử dụng ASP.NET - Đó là trong chỉnh sửa –

6

Dưới đây là một ví dụ bạn có thể thiết lập sử dụng Visual tham khảo web studio http://footballpool.dataaccess.eu/data/info.wso?WSDL

Về cơ bản, bạn phải chèn trong chuỗi cuộc gọi webservice một spyer XmlReader rằng sẽ tái tạo lại XML thô.

Tôi tin rằng cách này đơn giản hơn bằng cách sử dụng SoapExtensions.

giải pháp Giải pháp đã được lấy cảm hứng từ http://orbinary.com/blog/2010/01/getting-the-raw-soap-xml-sent-via-soaphttpclientprotocol/

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(); 
     } 
    } 
} 
3

Lấy cảm hứng từ jfburdet, tôi muốn để xem nếu nó đã có thể đánh chặn trực tiếp ở cấp dòng/byte chứ không phải là xây dựng lại XML. Và nó là! Xem mã bên dưới:

using System; 
using System.Collections.Generic; 
using System.IO; 
using System.Linq; 
using System.Text; 
using System.Web.Services.Protocols; 
using System.Xml; 

using Test.MyWebReference; 

namespace Test { 
    /// <summary> 
    /// Adds the ability to retrieve the SOAP request/response. 
    /// </summary> 
    public class ServiceSpy : OriginalService { 
     private StreamSpy writerStreamSpy; 
     private XmlTextWriter xmlWriter; 

     private StreamSpy readerStreamSpy; 
     private XmlTextReader xmlReader; 

     public MemoryStream WriterStream { 
      get { return writerStreamSpy == null ? null : writerStreamSpy.ClonedStream; } 
     } 

     public XmlTextWriter XmlWriter { 
      get { return xmlWriter; } 
     } 

     public MemoryStream ReaderStream { 
      get { return readerStreamSpy == null ? null : readerStreamSpy.ClonedStream; } 
     } 

     public XmlTextReader XmlReader { 
      get { return xmlReader; } 
     } 

     protected override void Dispose(bool disposing) { 
      base.Dispose(disposing); 
      DisposeWriterStreamSpy(); 
      DisposeReaderStreamSpy(); 
     } 

     protected override XmlWriter GetWriterForMessage(SoapClientMessage message, int bufferSize) { 
      // Dispose previous writer stream spy. 
      DisposeWriterStreamSpy(); 

      writerStreamSpy = new StreamSpy(message.Stream); 
      // XML should always support UTF8. 
      xmlWriter = new XmlTextWriter(writerStreamSpy, Encoding.UTF8); 

      return xmlWriter; 
     } 

     protected override XmlReader GetReaderForMessage(SoapClientMessage message, int bufferSize) { 
      // Dispose previous reader stream spy. 
      DisposeReaderStreamSpy(); 

      readerStreamSpy = new StreamSpy(message.Stream); 
      xmlReader = new XmlTextReader(readerStreamSpy); 

      return xmlReader; 
     } 

     private void DisposeWriterStreamSpy() { 
      if (writerStreamSpy != null) { 
       writerStreamSpy.Dispose(); 
       writerStreamSpy.ClonedStream.Dispose(); 
       writerStreamSpy = null; 
      } 
     } 

     private void DisposeReaderStreamSpy() { 
      if (readerStreamSpy != null) { 
       readerStreamSpy.Dispose(); 
       readerStreamSpy.ClonedStream.Dispose(); 
       readerStreamSpy = null; 
      } 
     } 

     /// <summary> 
     /// Wrapper class to clone read/write bytes. 
     /// </summary> 
     public class StreamSpy : Stream { 
      private Stream wrappedStream; 
      private long startPosition; 
      private MemoryStream clonedStream = new MemoryStream(); 

      public StreamSpy(Stream wrappedStream) { 
       this.wrappedStream = wrappedStream; 
       startPosition = wrappedStream.Position; 
      } 

      public MemoryStream ClonedStream { 
       get { return clonedStream; } 
      } 

      public override bool CanRead { 
       get { return wrappedStream.CanRead; } 
      } 

      public override bool CanSeek { 
       get { return wrappedStream.CanSeek; } 
      } 

      public override bool CanWrite { 
       get { return wrappedStream.CanWrite; } 
      } 

      public override void Flush() { 
       wrappedStream.Flush(); 
      } 

      public override long Length { 
       get { return wrappedStream.Length; } 
      } 

      public override long Position { 
       get { return wrappedStream.Position; } 
       set { wrappedStream.Position = value; } 
      } 

      public override int Read(byte[] buffer, int offset, int count) { 
       long relativeOffset = wrappedStream.Position - startPosition; 
       int result = wrappedStream.Read(buffer, offset, count); 
       if (clonedStream.Position != relativeOffset) { 
        clonedStream.Position = relativeOffset; 
       } 
       clonedStream.Write(buffer, offset, result); 
       return result; 
      } 

      public override long Seek(long offset, SeekOrigin origin) { 
       return wrappedStream.Seek(offset, origin); 
      } 

      public override void SetLength(long value) { 
       wrappedStream.SetLength(value); 
      } 

      public override void Write(byte[] buffer, int offset, int count) { 
       long relativeOffset = wrappedStream.Position - startPosition; 
       wrappedStream.Write(buffer, offset, count); 
       if (clonedStream.Position != relativeOffset) { 
        clonedStream.Position = relativeOffset; 
       } 
       clonedStream.Write(buffer, offset, count); 
      } 

      public override void Close() { 
       wrappedStream.Close(); 
       base.Close(); 
      } 

      protected override void Dispose(bool disposing) { 
       if (wrappedStream != null) { 
        wrappedStream.Dispose(); 
        wrappedStream = null; 
       } 
       base.Dispose(disposing); 
      } 
     } 
    } 
} 
Các vấn đề liên quan