การรับข้อมูล RAW Soap จากไคลเอนต์อ้างอิงเว็บที่ทำงานใน ASP.net


95

ฉันกำลังประสบปัญหาในการถ่ายทำไคลเอนต์บริการเว็บในโครงการปัจจุบันของฉัน ฉันไม่แน่ใจเกี่ยวกับแพลตฟอร์มของเซิร์ฟเวอร์บริการ (LAMP) ฉันเชื่อว่ามีข้อผิดพลาดที่ด้านข้างของรั้วเนื่องจากฉันได้กำจัดปัญหาที่อาจเกิดขึ้นกับลูกค้าของฉัน ไคลเอนต์เป็นพร็อกซีอ้างอิงเว็บชนิด ASMX มาตรฐานที่สร้างขึ้นโดยอัตโนมัติจากบริการ WSDL

สิ่งที่ฉันต้องได้รับคือ RAW SOAP Messages (คำขอและการตอบกลับ)

วิธีที่ดีที่สุดในการดำเนินการคืออะไร?

คำตอบ:


135

ฉันทำการเปลี่ยนแปลงต่อไปนี้web.configเพื่อรับซองจดหมาย SOAP (คำขอ / การตอบกลับ) ออกจะนี้ข้อมูลทั้งหมด SOAP trace.logดิบไปยังแฟ้ม

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

2
สิ่งนี้ใช้ไม่ได้สำหรับฉันใน 02/2012 โดยใช้ VS 2010 ใครทราบวิธีแก้ไขที่ทันสมัยกว่า
qxotk

2
นี่เป็นประโยชน์ อย่างไรก็ตามในกรณีของฉันการตอบสนองเป็น Gzipped และการดึง ASCII หรือรหัสฐานสิบหกออกจากเอาต์พุตรวมเป็นความเจ็บปวด วิธีการส่งออกทางเลือกซึ่งเป็นแบบไบนารีหรือข้อความเท่านั้นหรือไม่

2
@Dediqated - คุณสามารถกำหนดเส้นทางไปยังไฟล์ trace.log โดยการปรับค่าของแอตทริบิวต์ initializeData ในตัวอย่างด้านบน
DougCouto

3
ไม่มีประโยชน์อีกต่อไปฉันใช้ Wirehark เพื่อดูข้อมูล SOAP ดิบ แต่ยังไงก็ขอบคุณ!
ลง

7
ดี. แต่ XML สำหรับฉันเป็นเหมือน: System.Net Verbose: 0: [14088] 00000000: 3C 3F 78 6D 6C 20 76 65-72 73 69 6F 6E 3D 22 31: <? xml version = "1 System.Net Verbose: 0: [14088] 00000010: 2E 30 22 20 65 6E 63 6F-64 69 6E 67 3D 22 75 74: .0 "encoding =" ut ....... มีความคิดว่าจะจัดรูปแบบอย่างไรหรือมีเฉพาะข้อมูล xml .?
Habeeb

35

คุณสามารถใช้ SoapExtension ที่บันทึกคำขอแบบเต็มและตอบกลับไปยังล็อกไฟล์ จากนั้นคุณสามารถเปิดใช้งาน SoapExtension ใน web.config ซึ่งทำให้ง่ายต่อการเปิด / ปิดเพื่อวัตถุประสงค์ในการดีบัก นี่คือตัวอย่างที่ฉันพบและแก้ไขสำหรับการใช้งานของฉันเองในกรณีของฉันการบันทึกทำโดย log4net แต่คุณสามารถแทนที่วิธีการบันทึกด้วยวิธีของคุณเองได้

public class SoapLoggerExtension : SoapExtension
{
    private static readonly ILog log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
    private Stream oldStream;
    private Stream newStream;

    public override object GetInitializer(LogicalMethodInfo methodInfo, SoapExtensionAttribute attribute)
    {
        return null;
    }

    public override object GetInitializer(Type serviceType)
    {
        return null;
    }

    public override void Initialize(object initializer)
    {

    }

    public override System.IO.Stream ChainStream(System.IO.Stream stream)
    {
        oldStream = stream;
        newStream = new MemoryStream();
        return newStream;
    }

    public override void ProcessMessage(SoapMessage message)
    {

        switch (message.Stage)
        {
            case SoapMessageStage.BeforeSerialize:
                break;
            case SoapMessageStage.AfterSerialize:
                Log(message, "AfterSerialize");
                    CopyStream(newStream, oldStream);
                    newStream.Position = 0;
                break;
                case SoapMessageStage.BeforeDeserialize:
                    CopyStream(oldStream, newStream);
                    Log(message, "BeforeDeserialize");
                break;
            case SoapMessageStage.AfterDeserialize:
                break;
        }
    }

    public void Log(SoapMessage message, string stage)
    {

        newStream.Position = 0;
        string contents = (message is SoapServerMessage) ? "SoapRequest " : "SoapResponse ";
        contents += stage + ";";

        StreamReader reader = new StreamReader(newStream);

        contents += reader.ReadToEnd();

        newStream.Position = 0;

        log.Debug(contents);
    }

    void ReturnStream()
    {
        CopyAndReverse(newStream, oldStream);
    }

    void ReceiveStream()
    {
        CopyAndReverse(newStream, oldStream);
    }

    public void ReverseIncomingStream()
    {
        ReverseStream(newStream);
    }

    public void ReverseOutgoingStream()
    {
        ReverseStream(newStream);
    }

    public void ReverseStream(Stream stream)
    {
        TextReader tr = new StreamReader(stream);
        string str = tr.ReadToEnd();
        char[] data = str.ToCharArray();
        Array.Reverse(data);
        string strReversed = new string(data);

        TextWriter tw = new StreamWriter(stream);
        stream.Position = 0;
        tw.Write(strReversed);
        tw.Flush();
    }
    void CopyAndReverse(Stream from, Stream to)
    {
        TextReader tr = new StreamReader(from);
        TextWriter tw = new StreamWriter(to);

        string str = tr.ReadToEnd();
        char[] data = str.ToCharArray();
        Array.Reverse(data);
        string strReversed = new string(data);
        tw.Write(strReversed);
        tw.Flush();
    }

    private void CopyStream(Stream fromStream, Stream toStream)
    {
        try
        {
            StreamReader sr = new StreamReader(fromStream);
            StreamWriter sw = new StreamWriter(toStream);
            sw.WriteLine(sr.ReadToEnd());
            sw.Flush();
        }
        catch (Exception ex)
        {
            string message = String.Format("CopyStream failed because: {0}", ex.Message);
            log.Error(message, ex);
        }
    }
}

[AttributeUsage(AttributeTargets.Method)]
public class SoapLoggerExtensionAttribute : SoapExtensionAttribute
{
    private int priority = 1; 

    public override int Priority
    {
        get { return priority; }
        set { priority = value; }
    }

    public override System.Type ExtensionType
    {
        get { return typeof (SoapLoggerExtension); }
    }
}

จากนั้นคุณเพิ่มส่วนต่อไปนี้ใน web.config ของคุณโดยที่ YourNamespace และ YourAssembly ชี้ไปที่คลาสและแอสเซมบลีของ SoapExtension ของคุณ:

<webServices>
  <soapExtensionTypes>
    <add type="YourNamespace.SoapLoggerExtension, YourAssembly" 
       priority="1" group="0" />
  </soapExtensionTypes>
</webServices>

ฉันจะให้มันไป ฉันได้ดูขอบเขตสบู่แล้ว แต่สำหรับฉันแล้วดูเหมือนว่ามันเป็นมากกว่าสำหรับการโฮสต์บริการ จะให้เห็บถ้ามันใช้งานได้ :)
Andrew Harry

ใช่วิธีนี้จะใช้บันทึกการโทรจากเว็บแอปพลิเคชันของคุณผ่านพร็อกซีที่สร้างขึ้น
John Lemp

นี่คือเส้นทางที่ฉันไปด้วยมันใช้งานได้ดีจริงๆและฉันสามารถใช้ xpath เพื่อปกปิดข้อมูลที่ละเอียดอ่อนก่อนที่จะบันทึก
Dave Baghdanov

ฉันต้องการเพิ่มส่วนหัวในคำขอสบู่ของลูกค้า สิ่งนี้ช่วยฉันได้ rhyous.com/2015/04/29/…
Rhyous

ฉันยังใหม่กับ c # และไม่แน่ใจว่าจะใส่ชื่อแอสเซมบลีอย่างไร ดูเหมือนว่าส่วนขยายจะไม่ทำงาน
Collin Anderson

28

ไม่แน่ใจว่าทำไมต้องยุ่งยากกับ web.config หรือคลาส serializer รหัสด้านล่างใช้ได้ผลสำหรับฉัน:

XmlSerializer xmlSerializer = new XmlSerializer(myEnvelope.GetType());

using (StringWriter textWriter = new StringWriter())
{
    xmlSerializer.Serialize(textWriter, myEnvelope);
    return textWriter.ToString();
}

19
ในกรณีที่ไม่myEnvelopeมาจากไหน?
ProfK

6
ฉันไม่เข้าใจว่าทำไมคำตอบนี้ไม่มีการโหวตเพิ่มขึ้นตรงประเด็น! ทำได้ดี!
Batista

1
myEnvalope จะเป็นวัตถุที่คุณส่งผ่านบริการเว็บ ฉันไม่สามารถทำให้สิ่งนี้ทำงานได้ตามที่อธิบายไว้ (โดยเฉพาะฟังก์ชัน textWriter.tostring) แต่มันทำงานได้ดีเพียงพอสำหรับวัตถุประสงค์ของฉันในโหมดดีบักซึ่งคุณสามารถเห็น xml ดิบหลังจากที่คุณเรียกซีเรียลไลซ์ ขอขอบคุณคำตอบนี้เป็นอย่างมากเนื่องจากบางส่วนได้ทำงานร่วมกับผลลัพธ์แบบผสม (การบันทึกโดยใช้ web.config จะส่งคืนเฉพาะบางส่วนของ xml เท่านั้นและไม่ใช่เรื่องง่ายที่จะแยกวิเคราะห์ด้วย)
user2366842

@Bimmerbound: สิ่งนี้จะใช้ได้กับข้อความสบู่ที่ปลอดภัยที่ส่งผ่าน VPN ที่เข้ารหัสหรือไม่?
Our Man in Bananas

7
คำตอบนี้ไม่ได้ผลิตซองสบู่ แต่เป็นอนุกรมกับ xml ขอซองสบู่ยังไง?
Ali Karaca

21

ลองFiddler2มันจะช่วยให้คุณตรวจสอบคำขอและการตอบสนอง อาจเป็นที่น่าสังเกตว่า Fiddler ใช้งานได้กับทั้งการรับส่งข้อมูล http และ https


เป็นบริการเข้ารหัส https
Andrew Harry

8
Fiddler สามารถยกเลิกการเข้ารหัสการรับส่งข้อมูล https
Aaron Fischer

1
ฉันพบว่าโซลูชันนี้ดีกว่าการเพิ่มการติดตามลงในเว็บ / app.config ขอบคุณ!
andyuk

1
แต่การใช้ system.diagnostics ในไฟล์ config ไม่จำเป็นต้องติดตั้งแอปของบุคคลที่สาม
Azat

1
@AaronFischer: Fiddler จะทำงานกับข้อความสบู่ที่ส่งผ่าน VPN ที่เข้ารหัสได้หรือไม่?
Our Man in Bananas

6

ดูเหมือนว่าโซลูชันของ Tim Carter จะใช้ไม่ได้หากการเรียกไปยังการอ้างอิงเว็บทำให้เกิดข้อยกเว้น ฉันพยายามรับการตอบสนองเว็บดิบเพื่อที่ฉันจะได้ตรวจสอบ (ในรหัส) ในตัวจัดการข้อผิดพลาดเมื่อมีข้อยกเว้น อย่างไรก็ตามฉันพบว่าบันทึกการตอบกลับที่เขียนโดยวิธีของ Tim ว่างเปล่าเมื่อการโทรเกิดข้อยกเว้น ฉันไม่เข้าใจรหัสทั้งหมด แต่ดูเหมือนว่าวิธีการของ Tim จะเข้าสู่กระบวนการหลังจากจุดที่. Net ได้ยกเลิกการตอบกลับทางเว็บไปแล้ว

ฉันกำลังทำงานกับลูกค้าที่กำลังพัฒนาบริการเว็บด้วยตนเองด้วยการเข้ารหัสระดับต่ำ ณ จุดนี้พวกเขากำลังเพิ่มข้อความแสดงข้อผิดพลาดของกระบวนการภายในของตนเองเป็นข้อความที่จัดรูปแบบ HTML ลงในการตอบสนองก่อนการตอบสนองที่จัดรูปแบบ SOAP แน่นอนว่าการอ้างอิงเว็บ automagic .Net ทำให้เกิดปัญหานี้ขึ้น หากฉันสามารถรับการตอบกลับ HTTP ดิบหลังจากเกิดข้อยกเว้นฉันสามารถค้นหาและแยกวิเคราะห์การตอบสนอง SOAP ใด ๆ ภายในการตอบสนอง HTTP ที่ส่งคืนแบบผสมและรู้ว่าพวกเขาได้รับข้อมูลของฉันตกลงหรือไม่

ต่อมา ...

นี่เป็นวิธีแก้ปัญหาที่ใช้งานได้แม้หลังจากการดำเนินการแล้ว (โปรดทราบว่าหลังจากการตอบกลับเท่านั้น - สามารถรับคำขอได้เช่นกัน):

namespace ChuckBevitt
{
    class GetRawResponseSoapExtension : SoapExtension
    {
        //must override these three methods
        public override object GetInitializer(LogicalMethodInfo methodInfo, SoapExtensionAttribute attribute)
        {
            return null;
        }
        public override object GetInitializer(Type serviceType)
        {
            return null;
        }
        public override void Initialize(object initializer)
        {
        }

        private bool IsResponse = false;

        public override void ProcessMessage(SoapMessage message)
        {
            //Note that ProcessMessage gets called AFTER ChainStream.
            //That's why I'm looking for AfterSerialize, rather than BeforeDeserialize
            if (message.Stage == SoapMessageStage.AfterSerialize)
                IsResponse = true;
            else
                IsResponse = false;
        }

        public override Stream ChainStream(Stream stream)
        {
            if (IsResponse)
            {
                StreamReader sr = new StreamReader(stream);
                string response = sr.ReadToEnd();
                sr.Close();
                sr.Dispose();

                File.WriteAllText(@"C:\test.txt", response);

                byte[] ResponseBytes = Encoding.ASCII.GetBytes(response);
                MemoryStream ms = new MemoryStream(ResponseBytes);
                return ms;

            }
            else
                return stream;
        }
    }
}

นี่คือวิธีที่คุณกำหนดค่าในไฟล์กำหนดค่า:

<configuration>
     ...
  <system.web>
    <webServices>
      <soapExtensionTypes>
        <add type="ChuckBevitt.GetRawResponseSoapExtension, TestCallWebService"
           priority="1" group="0" />
      </soapExtensionTypes>
    </webServices>
  </system.web>
</configuration>

"TestCallWebService" จะถูกแทนที่ด้วยชื่อของไลบรารี (ซึ่งเป็นชื่อของแอปคอนโซลทดสอบที่ฉันใช้งานอยู่)

คุณไม่ควรไปที่ ChainStream จริงๆ คุณควรจะทำได้ง่ายขึ้นจาก ProcessMessage เป็น:

public override void ProcessMessage(SoapMessage message)
{
    if (message.Stage == SoapMessageStage.BeforeDeserialize)
    {
        StreamReader sr = new StreamReader(message.Stream);
        File.WriteAllText(@"C:\test.txt", sr.ReadToEnd());
        message.Stream.Position = 0; //Will blow up 'cause type of stream ("ConnectStream") doesn't alow seek so can't reset position
    }
}

หากคุณค้นหา SoapMessage.Stream ควรเป็นสตรีมแบบอ่านอย่างเดียวที่คุณสามารถใช้ตรวจสอบข้อมูล ณ จุดนี้ได้ นี่เป็นสาเหตุที่ทำให้เกิดความเสียหายหากคุณอ่านสตรีมการประมวลผลระเบิดในภายหลังโดยไม่พบข้อผิดพลาด (สตรีมอยู่ในตอนท้าย) และคุณไม่สามารถรีเซ็ตตำแหน่งเป็นจุดเริ่มต้น

ที่น่าสนใจคือถ้าคุณทำทั้งสองวิธี ChainStream และ ProcessMessage วิธีการ ProcessMessage จะทำงานได้เนื่องจากคุณเปลี่ยนประเภทสตรีมจาก ConnectStream เป็น MemoryStream ใน ChainStream และ MemoryStream อนุญาตให้ดำเนินการค้นหา (ฉันพยายามแคสต์ ConnectStream ไปยัง MemoryStream - ไม่อนุญาต)

ดังนั้น ..... Microsoft ควรอนุญาตให้ดำเนินการค้นหาในประเภท ChainStream หรือทำให้ SoapMessage สตรีมเป็นสำเนาแบบอ่านอย่างเดียวตามที่ควรจะเป็น (เขียนสมาชิกรัฐสภาของคุณ ฯลฯ ... )

อีกหนึ่งประเด็น หลังจากสร้างวิธีเรียกคืนการตอบกลับ HTTP ดิบหลังจากเกิดข้อยกเว้นฉันยังไม่ได้รับการตอบสนองทั้งหมด (ตามที่กำหนดโดย HTTP sniffer) เนื่องจากเมื่อบริการเว็บการพัฒนาเพิ่มข้อความแสดงข้อผิดพลาด HTML ในตอนเริ่มต้นของการตอบสนองมันไม่ได้ปรับส่วนหัวของความยาวเนื้อหาดังนั้นค่าความยาวของเนื้อหาจึงน้อยกว่าขนาดของเนื้อหาการตอบสนองจริง สิ่งที่ฉันได้รับคือจำนวนอักขระค่าความยาวเนื้อหา - ส่วนที่เหลือหายไป เห็นได้ชัดว่าเมื่อ. Net อ่านสตรีมการตอบกลับมันจะอ่านจำนวนอักขระความยาวของเนื้อหาและไม่อนุญาตให้ค่าความยาวเนื้อหาอาจผิดพลาดได้ นี่คือสิ่งที่ควรจะเป็น แต่ถ้าค่าส่วนหัวความยาวของเนื้อหาไม่ถูกต้องวิธีเดียวที่คุณจะได้รับเนื้อหาการตอบสนองทั้งหมดคือการใช้ HTTP sniffer (ฉันใช้ HTTP Analyzer จากhttp://www.ieinspector.com )


2

ฉันต้องการให้เฟรมเวิร์กทำการบันทึกให้คุณโดยการเชื่อมต่อในสตรีมการบันทึกซึ่งจะบันทึกเมื่อเฟรมเวิร์กประมวลผลสตรีมที่เป็นพื้นฐาน ต่อไปนี้ไม่สะอาดเท่าที่ฉันต้องการเนื่องจากคุณไม่สามารถตัดสินใจระหว่างคำขอและการตอบกลับในวิธี ChainStream ต่อไปนี้เป็นวิธีจัดการ ด้วยความขอบคุณจอนฮันนาสำหรับการลบล้างไอเดียสตรีม

public class LoggerSoapExtension : SoapExtension
{
    private static readonly string LOG_DIRECTORY = ConfigurationManager.AppSettings["LOG_DIRECTORY"];
    private LogStream _logger;

    public override object GetInitializer(LogicalMethodInfo methodInfo, SoapExtensionAttribute attribute)
    {
        return null;
    }
    public override object GetInitializer(Type serviceType)
    {
        return null;
    }
    public override void Initialize(object initializer)
    {
    }
    public override System.IO.Stream ChainStream(System.IO.Stream stream)
    {
        _logger = new LogStream(stream);
        return _logger;
    }
    public override void ProcessMessage(SoapMessage message)
    {
        if (LOG_DIRECTORY != null)
        {
            switch (message.Stage)
            {
                case SoapMessageStage.BeforeSerialize:
                    _logger.Type = "request";
                    break;
                case SoapMessageStage.AfterSerialize:
                    break;
                case SoapMessageStage.BeforeDeserialize:
                    _logger.Type = "response";
                    break;
                case SoapMessageStage.AfterDeserialize:
                    break;
            }
        }
    }
    internal class LogStream : Stream
    {
        private Stream _source;
        private Stream _log;
        private bool _logSetup;
        private string _type;

        public LogStream(Stream source)
        {
            _source = source;
        }
        internal string Type
        {
            set { _type = value; }
        }
        private Stream Logger
        {
            get
            {
                if (!_logSetup)
                {
                    if (LOG_DIRECTORY != null)
                    {
                        try
                        {
                            DateTime now = DateTime.Now;
                            string folder = LOG_DIRECTORY + now.ToString("yyyyMMdd");
                            string subfolder = folder + "\\" + now.ToString("HH");
                            string client = System.Web.HttpContext.Current != null && System.Web.HttpContext.Current.Request != null && System.Web.HttpContext.Current.Request.UserHostAddress != null ? System.Web.HttpContext.Current.Request.UserHostAddress : string.Empty;
                            string ticks = now.ToString("yyyyMMdd'T'HHmmss.fffffff");
                            if (!Directory.Exists(folder))
                                Directory.CreateDirectory(folder);
                            if (!Directory.Exists(subfolder))
                                Directory.CreateDirectory(subfolder);
                            _log = new FileStream(new System.Text.StringBuilder(subfolder).Append('\\').Append(client).Append('_').Append(ticks).Append('_').Append(_type).Append(".xml").ToString(), FileMode.Create);
                        }
                        catch
                        {
                            _log = null;
                        }
                    }
                    _logSetup = true;
                }
                return _log;
            }
        }
        public override bool CanRead
        {
            get
            {
                return _source.CanRead;
            }
        }
        public override bool CanSeek
        {
            get
            {
                return _source.CanSeek;
            }
        }

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

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

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

        public override void Flush()
        {
            _source.Flush();
            if (Logger != null)
                Logger.Flush();
        }

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

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

        public override int Read(byte[] buffer, int offset, int count)
        {
            count = _source.Read(buffer, offset, count);
            if (Logger != null)
                Logger.Write(buffer, offset, count);
            return count;
        }

        public override void Write(byte[] buffer, int offset, int count)
        {
            _source.Write(buffer, offset, count);
            if (Logger != null)
                Logger.Write(buffer, offset, count);
        }
        public override int ReadByte()
        {
            int ret = _source.ReadByte();
            if (ret != -1 && Logger != null)
                Logger.WriteByte((byte)ret);
            return ret;
        }
        public override void Close()
        {
            _source.Close();
            if (Logger != null)
                Logger.Close();
            base.Close();
        }
        public override int ReadTimeout
        {
            get { return _source.ReadTimeout; }
            set { _source.ReadTimeout = value; }
        }
        public override int WriteTimeout
        {
            get { return _source.WriteTimeout; }
            set { _source.WriteTimeout = value; }
        }
    }
}
[AttributeUsage(AttributeTargets.Method)]
public class LoggerSoapExtensionAttribute : SoapExtensionAttribute
{
    private int priority = 1;
    public override int Priority
    {
        get
        {
            return priority;
        }
        set
        {
            priority = value;
        }
    }
    public override System.Type ExtensionType
    {
        get
        {
            return typeof(LoggerSoapExtension);
        }
    }
}

1
@TimCarter มันได้ผลกับฉันสิ่งเดียวที่ฉันลบคือส่วนไคลเอนต์ซึ่งทำให้ฉันมีชื่อด้วยเครื่องหมายจุดคู่ทำให้เกิดข้อยกเว้น ดังนั้นเมื่อฉันลบบรรทัดนี้มันใช้ได้ดีสำหรับผู้ที่ต้องการมีไฟล์เดียวสำหรับทุกคำขอ / การตอบกลับ สิ่งเดียวที่ต้องเพิ่มคือสิ่งที่ชัดเจนหากคุณอ่านคำตอบอื่น ๆ และคุณต้องเพิ่มโหนด web.config เพื่อระบุ soapExtension ขอบคุณ!
netadictos

1

นี่คือคำตอบยอดนิยมในเวอร์ชันที่เรียบง่าย เพิ่มสิ่งนี้ใน<configuration>องค์ประกอบweb.configหรือApp.configไฟล์ของคุณ มันจะสร้างtrace.logไฟล์ในbin/Debugโฟลเดอร์โครงการของคุณ หรือคุณสามารถระบุพา ธ สัมบูรณ์สำหรับล็อกไฟล์โดยใช้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>

เตือนว่าไม่อนุญาตแอตทริบิวต์maxdatasizeand tracemodeแต่จะเพิ่มจำนวนข้อมูลที่สามารถบันทึกได้และหลีกเลี่ยงการบันทึกทุกอย่างเป็นเลขฐานสิบหก


0

คุณไม่ได้ระบุภาษาที่คุณใช้ แต่สมมติว่า C # / .NET คุณสามารถใช้ส่วนขยาย SOAP ได้ได้

มิฉะนั้นให้ใช้เครื่องดมกลิ่นเช่นWireshark


1
ใช่ลอง Wirehark แล้วมันแสดงได้เฉพาะข้อมูลส่วนหัวเท่านั้นเนื้อหาสบู่ถูกเข้ารหัส
Andrew Harry

นั่นอาจเป็นเพราะคุณใช้ https ส่วนขยาย SOAP เท่าที่ฉันจำได้ว่าทำงานในระดับที่สูงขึ้นดังนั้นคุณควรจะสามารถดูข้อมูลได้หลังจากถอดรหัสแล้ว
rbrayb

2
ใช้ Fiddler แทน Wireshark ซึ่งจะถอดรหัส https ออกจากกล่อง
Rodrigo Strauss

-1

ฉันรู้ว่าฉันไปงานปาร์ตี้ค่อนข้างช้าและเนื่องจากไม่ได้ระบุภาษาจริงนี่คือโซลูชัน VB.NET ตามคำตอบของ Bimmerbound ในกรณีที่ใครก็ตามที่บังเอิญเจอสิ่งนี้และต้องการวิธีแก้ไข หมายเหตุ: คุณต้องมีการอ้างอิงถึงคลาส stringbuilder ในโปรเจ็กต์ของคุณหากคุณยังไม่มี

 Shared Function returnSerializedXML(ByVal obj As Object) As String
    Dim xmlSerializer As New System.Xml.Serialization.XmlSerializer(obj.GetType())
    Dim xmlSb As New StringBuilder
    Using textWriter As New IO.StringWriter(xmlSb)
        xmlSerializer.Serialize(textWriter, obj)
    End Using


    returnSerializedXML = xmlSb.ToString().Replace(vbCrLf, "")

End Function

เพียงแค่เรียกใช้ฟังก์ชันและจะส่งคืนสตริงที่มี xml ที่ทำให้เป็นอนุกรมของวัตถุที่คุณพยายามส่งผ่านไปยังบริการเว็บ (ตามความเป็นจริงสิ่งนี้ควรใช้ได้กับวัตถุใด ๆ ที่คุณต้องการโยนมันด้วย)

ตามหมายเหตุด้านข้างการเรียกแทนที่ในฟังก์ชันก่อนที่จะส่งคืน xml คือการตัดอักขระ vbCrLf ออกจากเอาต์พุต ของฉันมีอยู่มากมายภายใน xml ที่สร้างขึ้น แต่สิ่งนี้จะแตกต่างกันอย่างเห็นได้ชัดขึ้นอยู่กับสิ่งที่คุณพยายามทำให้เป็นอนุกรมและฉันคิดว่าพวกมันอาจถูกถอดออกในระหว่างที่วัตถุถูกส่งไปยังบริการเว็บ


ใครก็ตามที่ตบฉันด้วยการโหวตลดลงโปรดอย่าลังเลที่จะแจ้งให้เราทราบว่าฉันขาดอะไรไป / สิ่งที่สามารถปรับปรุงได้
user2366842
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.