How to limit HttpModule with ONLY ONE call per request?

若如初见. 提交于 2020-01-01 19:21:07

问题


Here is my implementation of HttpModule:

file with module:

public class HttpModuleRewriter : IHttpModule
{
    #region IHttpModule

    public void Init(HttpApplication app)
    {
        app.BeginRequest += ProcessRequest;
    }

    public void Dispose()
    {
    }

    #endregion

    #region Protected Methods

    protected void ProcessRequest(object sender, EventArgs e)
    {
        ...
    }
}

web.config:

<?xml version="1.0"?>
<configuration>  
  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true">
      <add name="HttpModuleRewriter" preCondition="managedHandler" type="HttpModuleRewriter" />
    </modules>
  </system.webServer>
</configuration>  

I've put break point in 'Init' method of HttpModuleRewriter class. The 1st time method is called when application is started... and each request to pages calls module only once.

If I do requests to pages quickly (2nd request will be send earlier than 1st request is processed) then method 'Init' is called few additionally and each following request to pages causes 2-3 calls to my module...

Why? How could I avoid that?

Thanks.

P.S. I've added public constructor into HttpModuleRewriter to calculate amount of references, and during my requests I have 5 modules created... and for each request to page 2 modules are actually called... but only for the 1st navigated page, for all following pages (I've checked 3 others) modules are called only once (only 1 instance is called)...

Why 1st page is processed twice? Suggested answer (to use 'initialized' flag) doesn't help too.


回答1:


If Init() hasn't finished before the second request comes along then your HttpModule isn't ready yet. If you have code in your Init() method that should run only once then you can set a flag (bool initialised) and use a lock to prevent the code from being run by more than one thread, e.g.:

private static bool initialised;
private static object lockObject = new object();

public void Init(HttpApplication app)
{
    lock(lockObject)
    {
         if(!initialised)
         {
           app.BeginRequest += ProcessRequest;
           //... other code here
           initialised = true;
         }
    }
}

Update: As this article explains, ASP.NET may create more than one instance of your HttpModule, so Init() can be called more than once. This is by design. Therefore you must fashion the module so that code that should run only once is run only once - by applying locking, like above.




回答2:


I'd say the obvious answer is that your handler is handling more than one request, likely for stylesheets or images.

Add the following into your ProcessRequest event handler and add a watch to context.Request.PhysicalPath to confirm this.

HttpApplication application = (HttpApplication)sender;
HttpContext context = application.Context;

string filename = Path.GetFileName(context.Request.PhysicalPath);

If you don't want your handler to run for requests for images etc, all you need to do is check for the path ending ".aspx" or something similar.




回答3:


When you execute Init() twice, the BeginRequest event will call twice your processing because it has two event handlers in it. The += operator adds the new event handler in a list, it doesn't replace the old handler(s).

Øyvind has a correct solution.



来源:https://stackoverflow.com/questions/5518814/how-to-limit-httpmodule-with-only-one-call-per-request

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!