Có vẻ như giải pháp của Tim Carter không hoạt động nếu lệnh gọi đến tham chiếu web ném ra một ngoại lệ. Tôi đã cố gắng truy cập phản hồi web thô để tôi có thể kiểm tra nó (trong mã) trong trình xử lý lỗi khi ngoại lệ được ném ra. Tuy nhiên, tôi thấy rằng nhật ký phản hồi được viết bởi phương pháp của Tim bị trống khi cuộc gọi ném ra một ngoại lệ. Tôi không hoàn toàn hiểu mã, nhưng có vẻ như phương pháp của Tim cắt vào quy trình sau điểm mà .Net đã vô hiệu hóa và hủy phản hồi web.
Tôi đang làm việc với một khách hàng đang phát triển dịch vụ web theo cách thủ công với mã hóa cấp thấp. Tại thời điểm này, họ đang thêm thông báo lỗi quy trình nội bộ của riêng họ dưới dạng thông báo có định dạng HTML vào phản hồi TRƯỚC phản hồi được định dạng SOAP. Tất nhiên, tài liệu tham khảo trên web automagic .Net đã thổi bùng lên điều này. Nếu tôi có thể nhận được phản hồi HTTP thô sau khi một ngoại lệ được đưa ra, tôi có thể tìm kiếm và phân tích cú pháp bất kỳ phản hồi SOAP nào trong phản hồi HTTP trả về hỗn hợp và biết rằng họ đã nhận được dữ liệu của tôi đồng ý hay không.
Một lát sau ...
Đây là một giải pháp hoạt động, ngay cả sau khi thực thi (lưu ý rằng tôi chỉ sau khi phản hồi - cũng có thể nhận được yêu cầu):
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;
}
}
}
Đây là cách bạn định cấu hình nó trong tệp cấu hình:
<configuration>
...
<system.web>
<webServices>
<soapExtensionTypes>
<add type="ChuckBevitt.GetRawResponseSoapExtension, TestCallWebService"
priority="1" group="0" />
</soapExtensionTypes>
</webServices>
</system.web>
</configuration>
"TestCallWebService" sẽ được thay thế bằng tên của thư viện (đó tình cờ là tên của ứng dụng bảng điều khiển thử nghiệm mà tôi đang làm việc).
Bạn thực sự không cần phải truy cập ChainStream; bạn sẽ có thể làm điều đó đơn giản hơn từ ProcessMessage như:
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
}
}
Nếu bạn tra cứu SoapMessage.Stream, nó phải là một luồng chỉ đọc mà bạn có thể sử dụng để kiểm tra dữ liệu tại thời điểm này. Đây là một nguyên nhân khó hiểu nếu bạn đọc luồng, các quả bom xử lý tiếp theo mà không tìm thấy dữ liệu bị lỗi (luồng đã ở cuối) và bạn không thể đặt lại vị trí ban đầu.
Điều thú vị là nếu bạn thực hiện cả hai phương pháp, theo cách ChainStream và ProcessMessage, thì phương thức ProcessMessage sẽ hoạt động vì bạn đã thay đổi loại luồng từ ConnectStream thành MemoryStream trong ChainStream và MemoryStream cho phép các hoạt động tìm kiếm. (Tôi đã thử truyền ConnectStream sang MemoryStream - không được phép.)
Vì vậy, ..... Microsoft nên cho phép các hoạt động tìm kiếm trên loại ChainStream hoặc làm cho SoapMessage.Stream thực sự là một bản sao chỉ đọc như nó được cho là. (Viết cho dân biểu của bạn, v.v.)
Một điểm nữa. Sau khi tạo một cách để truy xuất phản hồi HTTP thô sau một ngoại lệ, tôi vẫn không nhận được phản hồi đầy đủ (như được xác định bởi trình dò tìm HTTP). Điều này là do khi dịch vụ web phát triển thêm thông báo lỗi HTML vào đầu phản hồi, nó không điều chỉnh tiêu đề Độ dài nội dung, do đó giá trị Độ dài nội dung nhỏ hơn kích thước của nội dung phản hồi thực tế. Tất cả những gì tôi nhận được là số ký tự của giá trị Độ dài Nội dung - phần còn lại bị thiếu. Rõ ràng, khi .Net đọc luồng phản hồi, nó chỉ đọc số ký tự Độ dài Nội dung và không cho phép giá trị Độ dài Nội dung có thể bị sai. Điều này là vì nó nên được; nhưng nếu giá trị tiêu đề Độ dài Nội dung sai, thì cách duy nhất bạn sẽ nhận được toàn bộ nội dung phản hồi là sử dụng trình đánh giá HTTP (Tôi sử dụng HTTP Analyzer từhttp://www.ieins Inspector.com ).