ดูเหมือนว่าโซลูชันของ Tim Carter จะใช้ไม่ได้หากการเรียกไปยังการอ้างอิงเว็บทำให้เกิดข้อยกเว้น ฉันพยายามรับการตอบสนองเว็บดิบเพื่อที่ฉันจะได้ตรวจสอบ (ในรหัส) ในตัวจัดการข้อผิดพลาดเมื่อมีข้อยกเว้น อย่างไรก็ตามฉันพบว่าบันทึกการตอบกลับที่เขียนโดยวิธีของ Tim ว่างเปล่าเมื่อการโทรเกิดข้อยกเว้น ฉันไม่เข้าใจรหัสทั้งหมด แต่ดูเหมือนว่าวิธีการของ Tim จะเข้าสู่กระบวนการหลังจากจุดที่. Net ได้ยกเลิกการตอบกลับทางเว็บไปแล้ว
ฉันกำลังทำงานกับลูกค้าที่กำลังพัฒนาบริการเว็บด้วยตนเองด้วยการเข้ารหัสระดับต่ำ ณ จุดนี้พวกเขากำลังเพิ่มข้อความแสดงข้อผิดพลาดของกระบวนการภายในของตนเองเป็นข้อความที่จัดรูปแบบ HTML ลงในการตอบสนองก่อนการตอบสนองที่จัดรูปแบบ SOAP แน่นอนว่าการอ้างอิงเว็บ automagic .Net ทำให้เกิดปัญหานี้ขึ้น หากฉันสามารถรับการตอบกลับ HTTP ดิบหลังจากเกิดข้อยกเว้นฉันสามารถค้นหาและแยกวิเคราะห์การตอบสนอง SOAP ใด ๆ ภายในการตอบสนอง HTTP ที่ส่งคืนแบบผสมและรู้ว่าพวกเขาได้รับข้อมูลของฉันตกลงหรือไม่
ต่อมา ...
นี่เป็นวิธีแก้ปัญหาที่ใช้งานได้แม้หลังจากการดำเนินการแล้ว (โปรดทราบว่าหลังจากการตอบกลับเท่านั้น - สามารถรับคำขอได้เช่นกัน):
namespace ChuckBevitt
{
class GetRawResponseSoapExtension : SoapExtension
{
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)
{
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;
}
}
หากคุณค้นหา 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 )