在OutputCache之前执行rewiter HTTP Module

时间:2011-07-06 19:00:52

标签: c# asp.net iis

我已经开发了自定义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
}

2 个答案:

答案 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,以便更换字符串仅发生一次在缓存内容之前。