Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/278.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何限制每个请求只有一个调用的HttpModule?_C#_Asp.net_Httpmodule - Fatal编程技术网

C# 如何限制每个请求只有一个调用的HttpModule?

C# 如何限制每个请求只有一个调用的HttpModule?,c#,asp.net,httpmodule,C#,Asp.net,Httpmodule,以下是我对HttpModule的实现: 包含模块的文件: public class HttpModuleRewriter : IHttpModule { #region IHttpModule public void Init(HttpApplication app) { app.BeginRequest += ProcessRequest; } public void Dispose() { } #endre

以下是我对HttpModule的实现:

包含模块的文件:

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>  

我已经在HttpModuleRewriter类的“Init”方法中设置了断点。应用程序启动时调用第一次方法。。。并且每个对pages的请求只调用一次模块

如果我快速请求页面(第二个请求将在处理第一个请求之前发送),则会另外调用方法“Init”,并且每个后续页面请求都会导致对我的模块进行2-3次调用

为什么??我怎么能避免呢

谢谢

另外,我已经在HttpModuleRewriter中添加了公共构造函数来计算引用的数量,在我的请求期间,我创建了5个模块。。。对于第2页的每个请求,模块实际上被称为。。。但仅在第一个导航页面中,对于所有后续页面(我已经检查了其他3个页面),模块只调用一次(只调用了1个实例)

为什么第一页要处理两次?建议的答案(使用'initialized'标志)也没有帮助。

如果Init()在第二个请求出现之前还没有完成,那么您的HttpModule还没有准备好。如果Init()方法中的代码只应运行一次,则可以设置标志(bool initialized)并使用锁防止代码由多个线程运行,例如:

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;
         }
    }
}
更新: 如前所述,ASP.NET可能会创建HttpModule的多个实例,因此可以多次调用Init()。这是故意的。因此,您必须调整模块的样式,以便只运行一次的代码只运行一次—通过应用锁定,如上所述。

如果在第二个请求出现之前Init()尚未完成,则您的HttpModule尚未就绪。如果Init()方法中的代码只应运行一次,则可以设置标志(bool initialized)并使用锁防止代码由多个线程运行,例如:

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;
         }
    }
}
更新:
如前所述,ASP.NET可能会创建HttpModule的多个实例,因此可以多次调用Init()。这是故意的。因此,您必须设计模块,以便只运行一次的代码只运行一次—通过应用锁定,如上所述。

我想说的是,显而易见的答案是,您的处理程序正在处理多个请求,可能是样式表或图像

将以下内容添加到ProcessRequest事件处理程序中,并向context.Request.PhysicalPath添加一个监视以确认这一点

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

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

如果您不希望处理程序运行图像请求等,则只需检查以“.aspx”结尾的路径或类似的路径。

我想说的是,显而易见的答案是处理程序正在处理多个请求,可能是样式表或图像

将以下内容添加到ProcessRequest事件处理程序中,并向context.Request.PhysicalPath添加一个监视以确认这一点

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

string filename = Path.GetFileName(context.Request.PhysicalPath);
如果不希望处理程序运行图像等请求,则只需检查以“.aspx”结尾的路径或类似的路径。

当执行Init()两次时,BeginRequest事件将调用两次处理,因为其中有两个事件处理程序。+=运算符在列表中添加新的事件处理程序,但不会替换旧的处理程序

Øyvind有一个正确的解决方案。

当您两次执行Init()时,BeginRequest事件将调用两次您的处理,因为它有两个事件处理程序。+=运算符在列表中添加新的事件处理程序,但不会替换旧的处理程序


Øyvind有一个正确的解决方案。

那么,您认为模块初始化两次或更多次是可以的吗。。。也许你是对的。谢谢。但我想,您应该为“initialized”字段使用静态变量。而且,如果没有其他可用的模块,asp.net应用程序似乎会创建一个新模块。如果未将当前创建模块的ProcessRequest分配给app.BeginRequest,则以下调用模块的尝试将不会按预期调用“ProcessRequest”方法。。。所以模块实际上不会被连接。建议的解决方案似乎不可行。您好,是的,成员变量应该是静态的。我更新了答案以反映这一点。如果您实现这样的锁定,那么您的事件处理程序将在处理任何请求之前注册。因此,您认为模块初始化两次或更多次可以吗。。。也许你是对的。谢谢。但我想,您应该为“initialized”字段使用静态变量。而且,如果没有其他可用的模块,asp.net应用程序似乎会创建一个新模块。如果未将当前创建模块的ProcessRequest分配给app.BeginRequest,则以下调用模块的尝试将不会按预期调用“ProcessRequest”方法。。。所以模块实际上不会被连接。建议的解决方案似乎不可行。您好,是的,成员变量应该是静态的。我已经更新了答案以反映这一点。如果您实现这样的锁定,那么在处理任何请求之前,您的事件处理程序都将被注册。