私はいくつかのレガシー Web サイトを持っており、それぞれに多数の静的 HTML ページがあります。IIS モジュールを使用して、生成されたページ コンテンツをキャプチャし、追加の HTML スニペットを追加して新しいヘッダーとフッターを作成したいと考えています (これはデコレーター パターンと呼ばれます)。これが私がモジュール用に持っているコードです。奇妙なことに、多くのテストで、モジュールが 2 回呼び出されていることに気付きました。ページがロードされ、各呼び出しがページのコンテンツの一部をモジュールに渡すとき (最初の呼び出しはページの上部を渡し、2 回目はページの残りの部分を渡します)。モジュールが 2 回呼び出されることがわかっている理由は、静的変数を使用して呼び出しの数を取得し、それを新しいヘッダーとフッターに表示したためです (2 つの数値は異なり、フッター番号は常にヘッダー番号よりも 1 大きくなります)。また、それを証明するために、ページ コンテンツを 2 つの異なるファイルにエクスポートすることもできました。
namespace MyProject
{
public class MyModule : IHttpModule
{
public void Dispose()
{
}
public void Init(HttpApplication application)
{
application.ReleaseRequestState += new EventHandler(this.My_Wrapper);
}
public String ModuleName
{
get { return "MyProject"; }
}
public void My_Wrapper(Object source, EventArgs e)
{
HttpApplication app = (HttpApplication)source;
HttpContext context = app.Context;
HttpRequest request = context.Request;
string requestPath = request.Path.ToString();
//I have guarding code here so that the following code only applies to
//web requests that has ".html" in the end.
HttpContext.Current.Response.Filter = new WrapperFilter(HttpContext.Current.Response.Filter);
}
}
public class WrapperFilter : MemoryStream
{
private static Regex startOfBody = new Regex("(?i)<body(([^>])*)>", RegexOptions.Compiled | RegexOptions.Multiline);
private static Regex endOfBody = new Regex("(?i)</body>", RegexOptions.Compiled | RegexOptions.Multiline);
private Stream outputStream = null;
private static int index = 0;
public WrapperFilter(Stream output)
{
outputStream = output;
}
public override void Write(byte[] buffer, int offset, int count)
{
string contentInBuffer = UTF8Encoding.UTF8.GetString(buffer);
string page = new StringBuilder(contentInBuffer).ToString();
byte[] outputBuffer = null;
Match matchStartOfBody = null;
Match matchEndOfBody = null;
index++;
matchStartOfBody = startOfBody.Match(page);
string header = "html snippets for header: " + index;
page = startOfBody.Replace(page, "<body " + matchStartOfBody.Groups[1] + ">" + header);
matchEndOfBody = endOfBody.Match(page);
string footer = "html snippets for footer: " + index;
page = endOfBody.Replace(page, footer + "</body>");
outputBuffer = UTF8Encoding.UTF8.GetBytes(page);
outputStream.Write(outputBuffer, 0, outputBuffer.Length);
}
}
}
質問:
モジュールが 2 回読み込まれる理由は、ページ コンテンツが大きすぎるか、キャッシュを増やす必要があるためですか? もしそうなら、どのように?
技術的に、私のアプローチは機能しますか? HTML ページを装飾することができましたが、2 つの呼び出しプロセスが原因で、いくつかの高度な状況を処理できません。
ブラウザ ページに画像を表示する必要があり、画像の要求が IIS モジュールを通過する場合
アップデート
usr からの貴重な情報に基づくと、「奇妙な」動作は IIS の通常の動作にすぎません。彼/彼女の提案のために、クラス変数を追加しました:
private byte[] allContent = new byte[0];
および次の更新されたメソッド:
public override void Write(byte[] buffer, int offset, int count)
{
//new bigger array
byte[] newArr = new byte[allContent.Length + buffer.Length];
//copy old content
System.Array.Copy(allContent, newArr, allContent.Length);
//append new content
System.Array.Copy(buffer, 0, newArr, allContent.Length, buffer.Length);
//reset current total content
allContent = newArr;
}
以前の Write メソッドからすべてのコードをコピーした新しいメソッドを追加します。
protected override void Dispose(bool disposing)
{
//code copied from my earlier code, with "buffer" changed to "allContent".
}
今、すべてが動作します!ありがとうございます!