2011-07-06 7 views
0

ASP.NETによってレンダリングされた後、.aspxページを処理するカスタムHTTPモジュールを開発しました(単純な文字列置換を行うapp.Response.Filterを設定するだけです)。それは完璧に動作していますが、私は小さな問題に遭遇しています - OutputCache HTTPモジュールはapp.Response.Filterで行っている変更をキャッシュしません。OutputCacheの前にrewiter HTTPモジュールを実行

文字列置換と出力キャッシュを逆にすることができれば、パフォーマンス上のメリットがあるので、私は好きです。

だから、これを行う方法はありますか? 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 
} 

答えて

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 
    } 
} 
  • の出力キャッシュ機能を使用して試すことができます - 一度だけロードされているこのページありますか?またはポストバックに?
+0

ソースコードが掲載されました。明示的な有効期限についてのアイデアは興味深いものです...私は何とかそれを使用できるかどうか考えています。 – kape123

1

Response.Filterは、ページが既に生成され、キャッシュされ、送信準備が整うまでに、送信ストリームをフィルタリングします。

フィルタにカスタムキャッシュを追加する(ヒットごとのパフォーマンスに影響を及ぼす)か、ライフサイクルの早い段階でモジュールをフックする必要があります(例:UpdateRequestCache)。そのため、置換前の文字列はコンテンツキャッシュされます。

+0

まだapp.Response.Filterを使用できますか?それとも論理を変える必要がありますか?私はソースコードを掲載しており、あなたがそれについて何を言いたいのかを喜んで聞いています。 – kape123

関連する問題