IIS:模块的奇怪行为

时间:2016-03-22 14:39:10

标签: c# iis iis-modules

我有一些遗留网站,每个网站都有很多静态HTML网页。我想使用IIS模块捕获生成的页面内容并添加其他HTML片段,以使其具有新的页眉和页脚(这称为装饰器模式)。这是我对模块的代码。奇怪的是,在许多测试中,我注意到当加载页面时,模块被调用 TWICE ,并且每次调用都将页面内容的一部分传递给模块(第一次调用通过顶层页面的一部分,第二部分是页面的剩余部分)。我知道模块被调用两次的原因是因为我使用静态变量来捕获调用的数量并在新的页眉和页脚中显示它(两个数字不同,页脚数总是比标题数大1)。我还能够将页面内容导出到两个不同的文件中来证明它。

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);
        }
    }
}

问题:

  1. 模块加载两次的原因是页面内容太大或我需要增加缓存?如果是这样,怎么样?

  2. 从技术上讲,我的方法是否正常运作?我能够装饰HTML页面,由于两个调用过程,我无法处理一些高级情况。

  3. 当图像需要显示在浏览器页面中时,图像请求是否通过IIS模块?

  4. 更新

    基于来自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".
        }
    

    现在一切正常!谢谢,usr !!!

1 个答案:

答案 0 :(得分:1)

好的,我应该早点解决这个问题。我承认我没有阅读问题的每一句话。我应该对测量结果产生怀疑。事实证明测量结果已经破裂。

  

感谢您提出有关页面大小是否重要的​​问题。我再次做了测试。确实如此。对于小页面,我在页眉和页脚中看到相同的数字。对于大页面,我看到3和4或类似的东西。

然后:

Visible

NotificationManager mNotificationManager = (NotificationManager) getActivity().getSystemService(Context.NOTIFICATION_SERVICE); // Check if the notification policy access has been granted for the app. if (!mNotificationManager.isNotificationPolicyAccessGranted()) { Intent intent = new Intent(android.provider.Settings.ACTION_NOTIFICATION_POLICY_ACCESS_SETTINGS); startActivity(intent); } 可能被称为任意次数。这是 public override void Write(byte[] buffer, int offset, int count) { //... index++; 实现。任何人都可以随时拨打Write。你可以期待任何Stream

每页可以多次递增索引。计数代码被破坏,其余的工作。

此外,由于您无法在任意边界分割UTF-8编码数据,因此UTF-8处理被破坏。