2010-12-16 2 views
8

जैसा कि कुछ अन्य पदों में उल्लिखित है (नीचे संदर्भ देखें) मैं दूसरे द्वारा उत्पादित सामग्री को संशोधित करने के लिए प्रतिक्रिया फ़िल्टर बनाने का प्रयास कर रहा हूं वेब एप्लीकेशन।मैं एक ही समय में पूरी सामग्री पर काम करने के लिए एक HTTP प्रतिक्रिया फ़िल्टर को कैसे कार्यान्वित करूं, कोई चंकिंग

मेरे पास मूल स्ट्रिंग ट्रांसफ़ॉर्मेशन तर्क है जो एक सामान्य फ़िल्टरबेस से प्राप्त फ़िल्टरों में काम कर रहा है और encapsulated है। हालांकि, तर्क पूरी सामग्री पर काम करना चाहिए, न कि सामग्री के टुकड़े। इसलिए मुझे लिखने के बाद भाग को कैश करने की आवश्यकता होती है और जब सभी लिखते हैं तो फिल्टर निष्पादित करते हैं।

जैसा कि नीचे दिखाया गया है मैंने मेमोरीस्ट्रीम से प्राप्त एक नया ResponseFilter बनाया है। लिखने पर, सामग्री को अन्य मेमोरीस्ट्रीम पर कैश किया जाता है। फ्लश पर, पूर्ण सामग्री, अब मेमोरीस्ट्रीम में एक स्ट्रिंग में परिवर्तित हो जाती है और फ़िल्टर तर्क में शामिल होता है। संशोधित सामग्री को मूल स्ट्रीम पर वापस लिखा जाता है।

हालांकि, हर दूसरे अनुरोध पर (मूल रूप से जब एक नया फ़िल्टर पिछले एक पर तुरंत चालू होता है) पिछले फ़िल्टर की फ्लश विधि निष्पादित की जा रही है। इस बिंदु पर एप्लिकेशन _outputStream.Write() विधि पर क्रैश हो जाता है क्योंकि _cachedStream खाली है।

  1. पहले अनुरोध
  2. लिखें विधि
  3. फ्लश विधि कहा जाता है कहा जाता है
  4. बंद विधि कहा जाता है
  5. बंद विधि कहा जाता है:

    घटना का क्रम इस प्रकार है

  6. इस बिंदु पर ऐप लौटाता है और उचित सामग्री प्रदर्शित होती है।
  7. दूसरा अनुरोध
  8. फ्लश विधि
  9. _outputStream.Write पर आवेदन दुर्घटनाओं कहा जाता है। ArgumentOutOfRangeException (ऑफ़सेट)।
  10. जारी दुर्घटना के माध्यम से (/ दृश्य स्टूडियो में डब्ल्यू)
  11. बंद विधि कहा जाता है

के प्रश्न के एक जोड़े मैं है कर रहे हैं:

  1. क्यों बंद दो बार कहा जाता है?
  2. बंद होने के बाद फ्लश क्यों कहा जाता है?
  3. नीचे जय के बिंदु तक, धारा पूरी तरह से पढ़ने से पहले फ़्लश कहा जा सकता है, फ़िल्टर तर्क कहाँ रहना चाहिए? बंद में? फ्लश में लेकिन "अगर बंद हो रहा है" के साथ?
  4. एक प्रतिक्रिया फ़िल्टर के लिए उचित कार्यान्वयन क्या है जो पूरी सामग्री पर एक बार में काम करता है?

नोट: मैं ठीक उसी व्यवहार (ऋण बंद घटनाओं) का अनुभव करता है, तो मैं बंद विधि ओवरराइड नहीं करें।

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); 

संदर्भ:

उत्तर

0

फ्लश स्पष्ट रूप से बुलाया जा रहा है नहीं है। शायद इसे तब कहा जाता है जब कोड को एक नई वस्तु की आवश्यकता होती है, या शायद अंतिमकरण के परिणामस्वरूप।

मुझे लगता है कि कोई भी वृद्धिशील लिखने के बाद फ्लश कॉल कर सकता है, इसलिए मुझे यकीन नहीं है कि फ्लश करने के लिए कॉल एक पूर्ण संदेश का पर्याप्त संकेत है।

+0

यहां तक ​​कि अगर अंतिम रूप के परिणामस्वरूप स्पष्ट रूप से बुलाया जाता है, तो भी मैं _cachedContent को उस डेटा को शामिल करने की अपेक्षा करता हूं जो इसे लिखा गया था। हालांकि, _cachedContent में कोई डेटा नहीं है। वृद्धिशील लिखने के लिए फ्लश के बारे में अच्छी बात है। –

7

फ्लश के बारे में जय से एक टिप के लिए धन्यवाद, बढ़ते लिखने के लिए बुलाया जा रहा है, मैं फ़िल्टरिंग बंद कर रहा हूं, फ़िल्टर फ़िल्टर बंद करके वांछित के रूप में फ़िल्टर काम करने में सक्षम हूं और फ़िल्टर अभी बंद नहीं हुआ है। यह सुनिश्चित करता है कि फ़िल्टर बंद होने पर फ़िल्टर केवल तभी फ़्लश हो जाता है। मैंने इसे कुछ सरल क्षेत्रों के साथ पूरा किया, _isClosing और _isClosed जैसा कि नीचे अंतिम कोड में दिखाया गया है।

public class ResponseFilter : MemoryStream 
{ 
    private readonly Stream _outputStream; 
    private MemoryStream _cachedStream = new MemoryStream(1024); 

    private readonly FilterBase _filter; 
    private bool _isClosing; 
    private bool _isClosed; 

    public ResponseFilter (Stream outputStream, FilterBase filter) 
    { 
     _outputStream = outputStream; 
     _filter = filter; 
    } 

    public override void Flush() 
    { 
     if (_isClosing && !_isClosed) 
     { 
      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(); 
     } 
    } 

    public override void Write(byte[] buffer, int offset, int count) 
    { 
     _cachedStream.Write(buffer, 0, count); 
    } 

    public override void Close() 
    { 
     _isClosing = true; 

     Flush(); 

     _isClosed = true; 
     _isClosing = false; 

     _outputStream.Close(); 
    } 
} 

मुझे अभी तक उपरोक्त मेरे अन्य प्रश्नों के उत्तर नहीं मिला है इसलिए मैं इस समय को छोड़कर इस उत्तर को चिह्नित नहीं करूंगा।

+0

यह जवाब होना चाहिए था - यह मुझे HTML नोड्स पर विशेषताओं को संशोधित करने के लिए HtmlAgilityPack का उपयोग कर एक प्रतिक्रिया फ़िल्टर को लागू करने में मदद करता था। धन्यवाद! –

+1

मुझे समझ में नहीं आता कि लिखने की विधि के ओवरराइड में आप ऑफसेट के रूप में हमेशा 0 डालते हैं? – Durden81

+1

+1। और आपकी 'फ़िल्टरबेस' और 'MapServiceJsonResponseFilter' कक्षाओं में रुचि है ... – jerone

संबंधित मुद्दे

 संबंधित मुद्दे