जैसा कि कुछ अन्य पदों में उल्लिखित है (नीचे संदर्भ देखें) मैं दूसरे द्वारा उत्पादित सामग्री को संशोधित करने के लिए प्रतिक्रिया फ़िल्टर बनाने का प्रयास कर रहा हूं वेब एप्लीकेशन।मैं एक ही समय में पूरी सामग्री पर काम करने के लिए एक HTTP प्रतिक्रिया फ़िल्टर को कैसे कार्यान्वित करूं, कोई चंकिंग
मेरे पास मूल स्ट्रिंग ट्रांसफ़ॉर्मेशन तर्क है जो एक सामान्य फ़िल्टरबेस से प्राप्त फ़िल्टरों में काम कर रहा है और encapsulated है। हालांकि, तर्क पूरी सामग्री पर काम करना चाहिए, न कि सामग्री के टुकड़े। इसलिए मुझे लिखने के बाद भाग को कैश करने की आवश्यकता होती है और जब सभी लिखते हैं तो फिल्टर निष्पादित करते हैं।
जैसा कि नीचे दिखाया गया है मैंने मेमोरीस्ट्रीम से प्राप्त एक नया ResponseFilter बनाया है। लिखने पर, सामग्री को अन्य मेमोरीस्ट्रीम पर कैश किया जाता है। फ्लश पर, पूर्ण सामग्री, अब मेमोरीस्ट्रीम में एक स्ट्रिंग में परिवर्तित हो जाती है और फ़िल्टर तर्क में शामिल होता है। संशोधित सामग्री को मूल स्ट्रीम पर वापस लिखा जाता है।
हालांकि, हर दूसरे अनुरोध पर (मूल रूप से जब एक नया फ़िल्टर पिछले एक पर तुरंत चालू होता है) पिछले फ़िल्टर की फ्लश विधि निष्पादित की जा रही है। इस बिंदु पर एप्लिकेशन _outputStream.Write() विधि पर क्रैश हो जाता है क्योंकि _cachedStream खाली है।
- पहले अनुरोध
- लिखें विधि
- फ्लश विधि कहा जाता है कहा जाता है
- बंद विधि कहा जाता है
- बंद विधि कहा जाता है:
घटना का क्रम इस प्रकार है
- इस बिंदु पर ऐप लौटाता है और उचित सामग्री प्रदर्शित होती है।
- दूसरा अनुरोध
- फ्लश विधि
- _outputStream.Write पर आवेदन दुर्घटनाओं कहा जाता है। ArgumentOutOfRangeException (ऑफ़सेट)।
- जारी दुर्घटना के माध्यम से (/ दृश्य स्टूडियो में डब्ल्यू)
- बंद विधि कहा जाता है
के प्रश्न के एक जोड़े मैं है कर रहे हैं:
- क्यों बंद दो बार कहा जाता है?
- बंद होने के बाद फ्लश क्यों कहा जाता है?
- नीचे जय के बिंदु तक, धारा पूरी तरह से पढ़ने से पहले फ़्लश कहा जा सकता है, फ़िल्टर तर्क कहाँ रहना चाहिए? बंद में? फ्लश में लेकिन "अगर बंद हो रहा है" के साथ?
- एक प्रतिक्रिया फ़िल्टर के लिए उचित कार्यान्वयन क्या है जो पूरी सामग्री पर एक बार में काम करता है?
नोट: मैं ठीक उसी व्यवहार (ऋण बंद घटनाओं) का अनुभव करता है, तो मैं बंद विधि ओवरराइड नहीं करें।
public class ResponseFilter : MemoryStream
{
private readonly Stream _outputStream;
private MemoryStream _cachedStream = new MemoryStream(1024);
private readonly FilterBase _filter;
public ResponseFilter (Stream outputStream, FilterBase filter)
{
_outputStream = outputStream;
_filter = filter;
}
// Flush is called on the second, fourth, and so on, page request (second request) with empty content.
public override void Flush()
{
Encoding encoding = HttpContext.Current.Response.ContentEncoding;
string cachedContent = encoding.GetString(_cachedStream.ToArray());
// Filter the cached content
cachedContent = _filter.Filter(cachedContent);
byte[] buffer = encoding.GetBytes(cachedContent);
_cachedStream = new MemoryStream();
_cachedStream.Write(buffer, 0, buffer.Length);
// Write new content to stream
_outputStream.Write(_cachedStream.ToArray(), 0, (int)_cachedStream.Length);
_cachedStream.SetLength(0);
_outputStream.Flush();
}
// Write is called on the first, third, and so on, page request.
public override void Write(byte[] buffer, int offset, int count)
{
// Cache the content.
_cachedStream.Write(buffer, 0, count);
}
public override void Close()
{
_outputStream.Close();
}
}
// Example usage in a custom HTTP Module on the BeginRequest event.
FilterBase transformFilter = new MapServiceJsonResponseFilter();
response.Filter = new ResponseFilter(response.Filter, transformFilter);
संदर्भ:
- How do I deploy a managed HTTP Module Site Wide?
- Creating multiple (15+) HTTP Response filters, Inheritance vs. Composition w/ Injection
यहां तक कि अगर अंतिम रूप के परिणामस्वरूप स्पष्ट रूप से बुलाया जाता है, तो भी मैं _cachedContent को उस डेटा को शामिल करने की अपेक्षा करता हूं जो इसे लिखा गया था। हालांकि, _cachedContent में कोई डेटा नहीं है। वृद्धिशील लिखने के लिए फ्लश के बारे में अच्छी बात है। –