Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • Topic author was deleted

    Jun 24, 2013 @ 14:36

    Need to grab the contents of ClientDependency.Core.Module.ResponseFilterStream

    This is a difficult one so apologies ahead of time.  The following piece of code works in v4, but not v6 inside an HttpModule.

    ResponseCaptureStream filter = app.Response.Filter as ResponseCaptureStream;              

    if (filter != null)
    {
    //filter is null for v6 not v4.
    }

     

    The main differences I can find between v4 and v6 is the output filtering is the filter type: 

    In v4 the type is: System.Web.HttpResponseStreamFilterSink

    In v6 the type is: ClientDependency.Core.Module.ResponseFilterStream

    In v6, 'filter' is null because it fails a cast.

    What I'm truly after is the final HTML on every request.  I don't actually need to perform my own filtering.  Any suggestions on how to read the stream?

    The ResponseCaptureStream class is as follows:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Text;
    using System.IO;

    namespace FastCache
    {
    public class ResponseCaptureStream : Stream
    {
    private readonly Stream _streamToCapture;
    private readonly Encoding _responseEncoding;

    private string _streamContent;
    public string StreamContent
    {
    get { return _streamContent; }
    private set
    {
    _streamContent = value;
    }
    }

    public ResponseCaptureStream(Stream streamToCapture, Encoding responseEncoding)
    {
    _responseEncoding = responseEncoding;
    _streamToCapture = streamToCapture;
    }

    public override bool CanRead
    {
    get { return _streamToCapture.CanRead; }
    }

    public override bool CanSeek
    {
    get { return _streamToCapture.CanSeek; }
    }

    public override bool CanWrite
    {
    get { return _streamToCapture.CanWrite; }
    }

    public override void Flush()
    {
    _streamToCapture.Flush();
    }

    public override long Length
    {
    get { return _streamToCapture.Length; }
    }

    public override long Position
    {
    get
    {
    return _streamToCapture.Position;
    }
    set
    {
    _streamToCapture.Position = value;
    }
    }

    public override int Read(byte[] buffer, int offset, int count)
    {
    return _streamToCapture.Read(buffer, offset, count);
    }

    public override long Seek(long offset, SeekOrigin origin)
    {
    return _streamToCapture.Seek(offset, origin);
    }

    public override void SetLength(long value)
    {
    _streamToCapture.SetLength(value);
    }

    public override void Write(byte[] buffer, int offset, int count)
    {
    _streamContent += _responseEncoding.GetString(buffer);
    _streamToCapture.Write(buffer, offset, count);
    }

    public override void Close()
    {
    _streamToCapture.Close();
    base.Close();
    }
    }

    }

     

    I have tried to simply extend the ClientDependency class to no avail.

  • Phil Harvey 2 posts 92 karma points
    Jun 24, 2013 @ 14:58
    Phil Harvey
    0

    The underlying type of Filter should always be a Stream, so can you just do...

    Stream filter = app.Response.Filteras Stream;              

    if(filter !=null)
    {
     
    //do work
    }

    The constructer for ResponseCaptureStream takes a Stream, so should be able to cope with it.

    System.Web.HttpResponseStreamFilterSink and ClientDependency.Core.Module.ResponseFilterStream both derive from Stream.

     

  • Lee Kelleher 3945 posts 15163 karma points MVP 10x admin c-trib
    Jun 24, 2013 @ 15:05
    Lee Kelleher
    0

    The approach that I take on a few of my packages that make use of the Response.Filter stream is outlined in this blog post:

    http://www.west-wind.com/weblog/posts/2009/Nov/13/Capturing-and-Transforming-ASPNET-Output-with-ResponseFilter

    See my code examples for SafeMailLink (here) and Shortcodes (here).  Not sure if this approach is 100% applicable to your issue though - sorry.

    Cheers, Lee.

  • Comment author was deleted

    Jun 24, 2013 @ 15:10

    A bit more code to chew on:

    public void Init(System.Web.HttpApplication _app)
    {
    if (enabled)
    {
    app = _app;
    _app.ResolveRequestCache += new EventHandler(Start);
    _app.PreSendRequestContent += new EventHandler(Finish);
    }
    }

     

    private void Start(Object sender, EventArgs e)
    {
    app.Response.Filter = new ResponseCaptureStream(app.Response.Filter, app.Response.ContentEncoding);
    }

     

    private void Finish(object sender, EventArgs e)
    {
    ResponseCaptureStream filter = app.Response.Filter as ResponseCaptureStream;
    if (filter != null){
    //never make it here in v6
    string responseText = filter.StreamContent;// this is how I'm grabbing the 'final' output
    }
    }
  • Phil Harvey 2 posts 92 karma points
    Jun 24, 2013 @ 15:20
    Phil Harvey
    100

    I do it slightly differently, here's some code. I can't remember why I stick the StreamWatcher in the context items, but there was a good reason (probably haha). 

    private void Start(Object sender,EventArgs e)
    {
    var watcher = new StreamWatcher(context.Response.Filter); context.Context.Items["StaticCacheModule_watcher"] = watcher; context.Response.Filter = watcher;  
    private void Finish(object sender,EventArgs e)
    {
    var watcher = context.Context.Items["StaticCacheModule_watcher"] as StreamWatcher; if (watcher != null) {
    string value = watcher.ToString().Trim();
    }
    }
        public class StreamWatcher : Stream
        {
            private Stream _base;
            private MemoryStream _memoryStream = new MemoryStream();
    
            public StreamWatcher(Stream stream)
            {
                _base = stream;
            }
    
            public override void Flush()
            {
                _base.Flush();
            }
    
            public override int Read(byte[] buffer, int offset, int count)
            {
                return _base.Read(buffer, offset, count);
            }
    
            public override void Write(byte[] buffer, int offset, int count)
            {
                _memoryStream.Write(buffer, offset, count);
                _base.Write(buffer, offset, count);
            }
    
            public override string ToString()
            {
                return Encoding.UTF8.GetString(_memoryStream.ToArray());
            }
    
            #region Rest of the overrides
            public override bool CanRead
            {
                get { return _base.CanRead; }
            }
    
            public override bool CanSeek
            {
                get { return _base.CanSeek; }
            }
    
            public override bool CanWrite
            {
                get { return _base.CanWrite; }
            }
    
            public override long Seek(long offset, SeekOrigin origin)
            {
                return _base.Seek(offset, origin);
            }
    
            public override void SetLength(long value)
            {
                _base.SetLength(value);
            }
    
            public override long Length
            {
                get { return _base.Length; }
            }
    
            public override long Position
            {
                get
                {
                    return _base.Position;
                }
                set
                {
                    _base.Position = value;
                }
            }
            #endregion
        }
    
    
  • Comment author was deleted

    Jun 24, 2013 @ 16:16

    I'm spinning up your code now, thanks for the lead

  • Comment author was deleted

    Jun 24, 2013 @ 16:20

    Brilliant, it seems to be working :)  Thank you so much :)

  • This forum is in read-only mode while we transition to the new forum.

    You can continue this topic on the new forum by tapping the "Continue discussion" link below.

Please Sign in or register to post replies