New Snippet New Snippet Recent Snippets Recent Snippets My Snippets My Snippets Web Code Search Snippets Search
Sign inor Register
Language: C#

Transformable ASP.NET Response Filter implementation

273 Views
Copy Code Show/Hide Line Numbers
/// <summary>
/// A semi-generic Response Filter that allows transformations
/// to be easily hooked up easily via a TransformStream event    
/// </summary>
public class TransformResponseFilter : Stream
{
    /// <summary>
    /// The original stream
    /// </summary>
    Stream _stream;
 
    /// <summary>
    /// Current position in the original stream
    /// </summary>
    long _position;
 
    /// <summary>
    /// Stream that original content is read into
    /// and then passed to TransformStream function
    /// </summary>
    MemoryStream _cacheStream = new MemoryStream(5000);
 
    /// <summary>
    /// Internal pointer that that keeps track of the size
    /// of the cacheStream
    /// </summary>
    int _cachePointer = 0;        
 
 
 
    public TransformResponseFilter(Stream responseStream)
    {
        _stream = responseStream;
    }
 
    /// <summary>
    /// Event that can be hooked up to handle Responsestream
    /// Transformation. Passed a MemoryStream that you can 
    /// modify and return back the transformed MemoryStream
    /// </summary>
    public event Func<MemoryStream, MemoryStream> TransformStream;
 
    /// <summary>
    /// 
    /// </summary>
    public event Func<string, string> TransformString;
 
    /// <summary>
    /// Overridable method that can handle transforming the 
    /// stream by accepting an input stream and returning a
    /// transformed stream
    /// </summary>
    /// <param name="ms"></param>
    /// <returns></returns>
    protected virtual MemoryStream OnTransformStream(MemoryStream ms)
    {
        if (TransformStream != null)
            return TransformStream(ms);
 
        return ms;
    }
 
    /// <summary>
    /// Allows transforming of strings
    /// </summary>
    /// <param name="responseText"></param>
    /// <returns></returns>
    internal string OnTransformString(string responseText)
    {
        if (TransformString != null)          
            TransformString(responseText);            
 
        return responseText;
    }
 
    internal MemoryStream OnTransformStringInternal(MemoryStream ms)
    {
        if (TransformString == null)
            return ms;
 
        //string content = ms.GetAsString();
        string content = Encoding.Default.GetString(ms.ToArray());
           
        content = TransformString(content);         
        byte[] buffer  = Encoding.Default.GetBytes(content);
        ms = new MemoryStream();
        ms.Write(buffer,0,buffer.Length);
        //ms.WriteString(content);
 
        return ms;
    }
 
 
    public override bool CanRead
    {
        get { return true; }
    }
 
    public override bool CanSeek
    {
        get { return true; }
    }
 
    public override bool CanWrite
    {
        get { return true; }
    }
 
    public override long Length
    {
        get { return 0; }
    }
 
    public override long Position
    {
        get { return _position; }
        set { _position = value; }
    }
 
    public override long Seek(long offset, System.IO.SeekOrigin direction)
    {
        return _stream.Seek(offset, direction);
    }
 
    public override void SetLength(long length)
    {
        _stream.SetLength(length);
    }
 
    public override void Close()
    {
        _stream.Close();
    }
 
    public override void Flush()
    {            
        // Check for transform implementations
        _cacheStream = OnTransformStream(_cacheStream);
        _cacheStream = OnTransformStringInternal(_cacheStream);
        
        // write the stream back out
        _stream.Write(_cacheStream.ToArray(), 0, (int)_cacheStream.Length);
 
        // default flush behavior
        _stream.Flush();
    }
 
    public override int Read(byte[] buffer, int offset, int count)
    {
        return _stream.Read(buffer, offset, count);
    }
 
 
    // The Write method actually does the filtering.
    public override void Write(byte[] buffer, int offset, int count)
    {
        // copy to holding buffer only - we'll write out later
        _cacheStream.Write(buffer, 0, count);
        _cachePointer += count;
    }
 
}
 
 
// *** TO USE IN A PAGE
 
        protected void Page_Load(object sender, System.EventArgs e)
        {
            // Put user code to initialize the page here
            if (this.chkEnableFilter.Checked)
            {
                TransformResponseFilter filter = new TransformResponseFilter(Response.Filter);
                filter.TransformStream += new Func<MemoryStream, MemoryStream>(filter_TransformStream);
                Response.Filter = filter;
            }
            else
            {
                // We have to redirect to get back to non-encoded page
                if (IsPostBack)
                    Response.Redirect("ResponseFilter.aspx");
            }
        }
 
        /// <summary>
        /// Do the transformation here
        /// 
        /// This transform replaces ~/ in string expressions
        /// with the Application's base path
        /// </summary>
        /// <param name="ms"></param>
        /// <returns></returns>
        MemoryStream filter_TransformStream(MemoryStream ms)
        {
            string output = ms.GetAsString();
 
            string path = HttpContext.Current.Request.ApplicationPath;
            output = output.Replace("\"~/", "\"" + path + "/").Replace("'~/", "'" + path + "/");
 
            ms = new MemoryStream(output.Length);
            ms.WriteString(output);
 
            return ms;
        }
by Rick Strahl
  November 12, 2009 @ 12:14pm
Tags:

Add a comment


Report Abuse
brought to you by:
West Wind Techologies


If you find this site useful and use it frequently please consider making a donation to support this free service.
Donate