Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/333.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 我如何实现一个HTTP响应过滤器来一次对整个内容进行操作,而不进行分块_C#_Filter_Stream_Httpresponse_Flush - Fatal编程技术网

C# 我如何实现一个HTTP响应过滤器来一次对整个内容进行操作,而不进行分块

C# 我如何实现一个HTTP响应过滤器来一次对整个内容进行操作,而不进行分块,c#,filter,stream,httpresponse,flush,C#,Filter,Stream,Httpresponse,Flush,正如在其他几篇文章(参见下面的参考资料)中提到的,我正在尝试创建响应过滤器,以便修改另一个web应用程序生成的内容 我使用基本的字符串转换逻辑,并将其封装到从通用FilterBase派生的过滤器中。但是,逻辑必须对全部内容而不是大块内容进行操作。因此,我需要在写块时缓存它们,并在所有写操作完成时执行过滤器 如下所示,我从MemoryStream创建了一个新的ResponseFilter。写入时,内容被缓存到另一个MemoryStream。在Flush中,MemoryStream中的全部内容将转换

正如在其他几篇文章(参见下面的参考资料)中提到的,我正在尝试创建响应过滤器,以便修改另一个web应用程序生成的内容

我使用基本的字符串转换逻辑,并将其封装到从通用FilterBase派生的过滤器中。但是,逻辑必须对全部内容而不是大块内容进行操作。因此,我需要在写块时缓存它们,并在所有写操作完成时执行过滤器

如下所示,我从MemoryStream创建了一个新的ResponseFilter。写入时,内容被缓存到另一个MemoryStream。在Flush中,MemoryStream中的全部内容将转换为字符串,并启动过滤器逻辑。然后,修改后的内容被写回原始流

但是,在每一个请求上(基本上是在前一个过滤器上实例化一个新过滤器时),前一个过滤器的Flush方法就会被执行。此时,由于_cachedStream为空,应用程序在_outputStream.Write()方法上崩溃

事件的顺序如下:

  • 第一次请求
  • 调用Write方法
  • 调用Flush方法
  • 调用Close方法
  • 调用Close方法
  • 此时,应用程序返回并显示正确的内容
  • 第二次请求
  • 调用Flush方法
  • 应用程序在_outputStream.Write上崩溃。ArgumentOutOfRangeException(偏移量)
  • 通过崩溃继续(在Visual Studio中)
  • 调用Close方法
  • 我有几个问题:

  • 为什么叫Close两次
  • 为什么在调用Closed后调用Flush
  • 根据Jay下面的观点,在流被完全读取之前可能会调用Flush,过滤器逻辑应该驻留在哪里?接近?齐平但有“如果关闭”
  • 一次处理整个内容的响应过滤器的正确实现是什么
  • 注意:如果不重写Close方法,我会经历完全相同的行为(减去Close事件)

    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);
    
    参考资料:


      • 未显式调用Flush。可能是在代码意识到需要新对象时调用,或者可能是作为终结器的结果调用


        我认为在任何增量写入之后都可以调用flush,因此,我不确定调用flush是否足以表示一条完整的消息。

        感谢Jay关于增量写入调用flush的提示,只有在过滤器关闭且尚未关闭的情况下,我才能通过执行过滤逻辑使过滤器按需工作。这样可以确保在流关闭时过滤器只刷新一次。我用几个简单的字段完成了这项工作,_isclose和_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();
            }
        }
        

        我还没有找到上述其他问题的答案,因此我现在不会将此答案标记为例外。

        即使作为终结器的结果隐式调用,我也希望缓存内容包含写入其中的数据。但是,缓存内容似乎不包含任何数据。关于将flush用于增量写入的优点。这应该是答案-它帮助我使用HtmlAgilityPack实现了一个响应过滤器,用于修改html节点上的属性。非常感谢。我不明白为什么在重写Write方法时总是将0作为偏移量?+1。我对您的
        FilterBase
        MapServiceJsonResponseFilter
        类很感兴趣。。。