ऐसा लगता है कि अगर वेब संदर्भ के लिए कॉल एक अपवाद फेंकता है तो टिम कार्टर का समाधान काम नहीं करता है। मैं कच्चे वेब रिसपॉन्स पर जाने की कोशिश कर रहा हूं ताकि एक बार अपवाद को फेंकने के बाद मैं त्रुटि कोड में (कोड में) इसकी जांच कर सकूं। हालाँकि, मुझे पता चल रहा है कि कॉल के अपवाद को फेंकने पर टिम की विधि द्वारा लिखा गया प्रतिक्रिया लॉग खाली है। मैं पूरी तरह से कोड को नहीं समझता हूं, लेकिन ऐसा प्रतीत होता है कि टिम की प्रक्रिया उस बिंदु के बाद प्रक्रिया में कटौती करती है जहां .Net पहले से ही अमान्य है और वेब प्रतिक्रिया को त्याग दिया है।
मैं एक क्लाइंट के साथ काम कर रहा हूं जो निम्न स्तर की कोडिंग के साथ मैन्युअल रूप से एक वेब सेवा विकसित कर रहा है। इस बिंदु पर, वे अपने स्वयं के आंतरिक प्रक्रिया त्रुटि संदेशों को जोड़ रहे हैं क्योंकि HTML ने प्रतिक्रिया स्वरूप संदेशों को SOAP स्वरूपित प्रतिक्रिया से पहले दिया है। बेशक, स्वचालित .Net वेब संदर्भ इस पर चल रहा है। अगर मुझे एक अपवाद के बाद कच्चे HTTP प्रतिक्रिया मिल सकती है, तो मैं मिश्रित रिटर्निंग HTTP प्रतिक्रिया के भीतर किसी भी SOAP प्रतिक्रिया की तलाश और पार्स कर सकता हूं और यह जान सकता हूं कि उन्हें मेरा डेटा ठीक मिला या नहीं।
बाद में ...
यहां एक समाधान है जो काम करता है, यहां तक कि एक निष्पादन के बाद भी (ध्यान दें कि मैं केवल प्रतिक्रिया के बाद हूं - अनुरोध भी मिल सकता है):
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" को लाइब्रेरी के नाम से बदल दिया जाएगा (जो कि टेस्ट कंसोल ऐप का नाम था जो मैं काम कर रहा था)।
आपको वास्तव में चैनस्ट्रीम में नहीं जाना चाहिए; आप इसे अधिक सरलता से कर सकते हैं
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 को देखते हैं, तो यह केवल पढ़ने योग्य स्ट्रीम माना जाता है जिसका उपयोग आप इस बिंदु पर डेटा का निरीक्षण करने के लिए कर सकते हैं। यदि आप स्ट्रीम पढ़ते हैं, तो यह एक पेंच-अप 'कारण है, बाद में कोई डेटा नहीं मिलने वाली त्रुटियों के साथ प्रसंस्करण बम (स्ट्रीम अंत में था) और आप स्थिति को शुरुआत में रीसेट नहीं कर सकते।
दिलचस्प बात यह है कि यदि आप दोनों तरीके, चेनस्ट्रीम और प्रोसेसमैज तरीके से करते हैं, तो प्रोसेसमेसेज मेथड काम करेगा क्योंकि आपने कनेक्टस्ट्रीम से लेकर चैनस्ट्रीम में मैमोरीस्ट्रीम में स्ट्रीम टाइप को बदल दिया है, और मेमोरीस्ट्रीम ऑपरेशन की अनुमति देता है। (मैंने कनेक्टस्ट्रीम को मेमोरीस्ट्रीम में डालने की कोशिश की - अनुमति नहीं थी।)
इसलिए ..... Microsoft को या तो चैनस्ट्रीम प्रकार पर परिचालन की अनुमति देनी चाहिए या SoapMessage.Stream को सही मायने में केवल पढ़ने के लिए कॉपी करना चाहिए क्योंकि यह होना चाहिए। (अपने कांग्रेसमैन आदि को लिखें ...)
एक और बात। एक अपवाद के बाद कच्चे HTTP की प्रतिक्रिया को वापस लेने का एक तरीका बनाने के बाद, मुझे अभी भी पूर्ण प्रतिक्रिया नहीं मिली (जैसा कि एक HTTP स्नीफर द्वारा निर्धारित किया गया है)। ऐसा इसलिए था क्योंकि जब विकास वेब सेवा ने प्रतिक्रिया की शुरुआत में HTML त्रुटि संदेश जोड़े थे, तो उसने सामग्री-लंबाई शीर्ष लेख को समायोजित नहीं किया था, इसलिए सामग्री-लंबाई मान वास्तविक प्रतिक्रिया निकाय के आकार से कम था। मेरे पास सभी वर्णों की सामग्री-लंबाई मान संख्या थी - बाकी गायब थे। जाहिर है, जब .Net प्रतिक्रिया धारा पढ़ता है, तो यह केवल सामग्री की लंबाई-लंबाई वर्ण पढ़ता है और सामग्री-लंबाई मान को गलत तरीके से होने की अनुमति नहीं देता है। यह वैसा ही है जैसा इसे होना चाहिए; लेकिन अगर सामग्री-लंबाई हेडर मान गलत है, तो आपको कभी भी संपूर्ण प्रतिक्रिया बॉडी मिलेगी एक HTTP स्निफ़र (I उपयोगकर्ता HTTP विश्लेषक से)http://www.ieinspector.com )।