2010-04-02 25 views
1

我们试图从我们的许多Web应用程序中删除global.asax,以支持处于通用代码库中的HttpModules。对于许多应用程序事件(例如BeginRequest和PostAuthentication),这非常有效,但HttpModule中没有公开Application Start事件。如何在HttpModule中使用或模仿Application OnStart?

我可以想到几个臭的方法来克服这个赤字。例如,我可以这样做:

protected virtual void BeginRequest(object sender, EventArgs e) 
{ 
    Log.Debug("Entered BeginRequest..."); 
    var app = HttpContext.Current.Application; 
    var hasBeenSet app["HasBeenExecuted"] == null ? false : true; 

    if(!hasBeenSet) 
    { 
     app.Lock(); 
     // ... do app level code 

     app.Add("HasBeenExecuted", true); 
     app.Unlock(); 
    } 

    // do regular begin request stuff ... 
} 

但是,这只是对我没有好闻。

什么是最好的方式来调用一些应用程序的开始逻辑没有global.asax?

回答

1

只要保持一个静态布尔在HttpModule

private static bool _hasApplicationStarted = false; 
private static object _locker = new object(); 

private void EnsureStarted() 
{ 
    if (_hasApplicationStarted) return; 

    lock (_locker) 
    { 
     if (_hasApplicationStarted) return; 

     // perform application startup here 

     _hasApplicationStarted = true; 
    } 
} 

然后有需要的应用程序已经启动的任何方法,只需要调用EnsureStarted

+0

@John:这看起来像一个单身模式。比如,当多个请求同时进入时,由于线程问题,我会有点担心使用静态。应用程序对象至少有一些简单的锁定/解锁来帮助解决这个问题。 – 2010-04-02 19:42:42

+0

@John:我看到你现在添加了...... :) – 2010-04-02 19:43:41

+0

@Sailing:锁一直在那里。答案没有被编辑。 – 2010-04-02 19:45:42

0

HttpModules和HttpHandlers将在每个请求上执行,而Global.asax App Start事件是应用程序启动时的,因此只有一次。

你可以创建一个通用的global.asax,它将加载所有具有特定接口的程序集,然后放入你想为该特定应用程序执行的dll。甚至在你的web.config中注册它们,并让你的通用global.asax读取密钥,然后加载并执行你想要的代码。

我认为这比将应用程序放入模块并检查状态变量更好。

+0

其中一个目标是删除global.asax。如果我们不能这样做,那么我们可以采取的其他方法将比您所描述的更简单(例如,我们可以使HttpModule类中的Application_Start()调用为静态方法)。 – 2010-04-02 19:51:07

+1

猜猜我只是想知道为什么摆脱global.asax比包含HttpModule更简单? – 2010-04-02 19:55:21

+0

那么,我已经使用了一个HttpModule,它已经在web.config中注册了。我想说,在应用程序启动事件中添加一些反射和文件IO以“用特定接口加载所有assmeblies”并不像在另一个类上调用静态方法那么简单。 – 2010-04-02 20:08:09