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 4026 posts 15836 karma points MVP 13x 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 :)

Please Sign in or register to post replies

Write your reply to:

Draft