我已经开发了自定义HTTP模块,它在ASP.NET呈现之后处理.aspx页面(它只是设置app.Response.Filter来执行一些简单的字符串替换)。它工作得很好,但我遇到了一个小问题 - OutputCache HTTP模块不会缓存我正在使用app.Response.Filter进行的更改。
由于性能优势,如果以某种方式可以反转字符串替换和输出缓存,我会很高兴。
那么,有没有办法做到这一点?是否可以使用HttpHandlers?
以下是替换者的当前源代码:
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
}
答案 0 :(得分:1)
你能粘贴一些你在这里做的样本代码吗?
听起来你正试图找到一种方法来替换某个单词/关键字的任何实例,如果你在输出中找到它?
您可以尝试执行此操作http://forums.asp.net/t/1123505.aspx并添加显式过期而不是使用asp.net的输出缓存功能
using System;
using System.Web;
namespace TT.Web.HttpModules
{
/// <summary>
/// HttpModule to prevent caching
/// </summary>
public class NoCacheModule : IHttpModule
{
public NoCacheModule()
{
}
#region IHttpModule Members
public void Init(HttpApplication context)
{
context.EndRequest += (new EventHandler(this.Application_EndRequest));
}
public void Dispose()
{
}
private void Application_EndRequest(Object source, EventArgs e)
{
HttpApplication application = (HttpApplication)source;
HttpContext context = application.Context;
context.Response.Cache.SetLastModified(DateTime.Now);
context.Response.Cache.SetExpires(DateTime.Now.AddMinutes(GetExpiryTime()));
context.Response.Cache.SetCacheability(HttpCacheability.Public);
context.Response.Cache.AppendCacheExtension("post-check=7200");
//The pre-check is in seconds and the value configured in web.config is in minutes. So need to multiply it with 60
context.Response.Cache.AppendCacheExtension("pre-check=" + (GetExpiryTime() * 60).ToString());
context.Response.CacheControl = "public";
}
#endregion
}
}
答案 1 :(得分:1)
Response.Filter过滤传出流,所以到那时页面已经生成并且已经(缓存并准备好发送)。
您必须向过滤器添加自定义缓存(会影响每次点击时的性能)或让您的模块挂钩到生命周期早期的事件,例如UpdateRequestCache,以便更换字符串仅发生一次在缓存内容之前。