I’ve developed custom HTTP module that processes .aspx page (it just sets app.Response.Filter for doing some simple string replacing) after it is rendered by ASP.NET. It is working perfectly, but I am running into one small problem – OutputCache HTTP module will not cache changes I’m doing with app.Response.Filter.
Because of performance benefit I would love if it would be somehow possible to inverse String Replacing and Output Caching.
So, is there a way to do this? Would using HttpHandlers be the way to go?
Here is the current source code of replacer:
public class StringReplaceModule : IHttpModule
{
void IHttpModule.Dispose()
{
// Nothing to dispose;
}
void IHttpModule.Init(HttpApplication context)
{
context.PreSendRequestHeaders +=
(sender, e) => HttpContext.Current.Response.Headers.Remove("Server");
context.BeginRequest += new EventHandler(context_BeginRequest);
}
void context_BeginRequest(object sender, EventArgs e)
{
HttpApplication app = sender as HttpApplication;
string url = app.Request.RawUrl.ToLower();
if (!url.Contains(".aspx/") &&
(url.Contains(".aspx") || url.Contains(".css") || url.Contains("/shorturl/")))
{
app.Response.Filter = new StringReplaceFilter(app.Response.Filter);
}
}
#region Stream filter
private class StringReplaceFilter : Stream
{
public StringReplaceFilter(Stream sink)
{
_sink = sink;
}
private Stream _sink;
private static string[] find;
private static string[] replace;
static StringReplaceFilter()
{
var config = StringReplaceModuleConfig.CurrentConfigSection();
find = config.Find.ToArray();
replace = config.Replace.ToArray();
}
public override void Write(byte[] buffer, int offset, int count)
{
byte[] data = new byte[count];
Buffer.BlockCopy(buffer, offset, data, 0, count);
string html = System.Text.Encoding.Default.GetString(buffer);
for (int i = 0; i < find.Length; i++)
{
html = html.Replace(find[i], replace[i]);
}
byte[] outdata = System.Text.Encoding.Default.GetBytes(html);
_sink.Write(outdata, 0, outdata.GetLength(0));
}
#region Less Important
public override bool CanRead
{
get { return true; }
}
public override bool CanSeek
{
get { return true; }
}
public override bool CanWrite
{
get { return true; }
}
public override void Flush()
{
_sink.Flush();
}
public override long Length
{
get { return 0; }
}
private long _position;
public override long Position
{
get { return _position; }
set { _position = value; }
}
public override int Read(byte[] buffer, int offset, int count)
{
return _sink.Read(buffer, offset, count);
}
public override long Seek(long offset, SeekOrigin origin)
{
return _sink.Seek(offset, origin);
}
public override void SetLength(long value)
{
_sink.SetLength(value);
}
public override void Close()
{
_sink.Close();
}
#endregion
}
#endregion
}
Can you paste some sample code of what you are doing here?
It sounds like you are trying to find a way of replacing any instance of a certain word/keyword with something else if you find it in the output?
You can try doing this http://forums.asp.net/t/1123505.aspx and adding a explicit expiration rather than using the output cache facilities of asp.net