HttpModules生活在ASP.NET MVC中

时间:2010-11-09 18:32:40

标签: asp.net-mvc model-view-controller httpmodule

我找到了一个关于在Asp.Net中统计在线用户的代码。我将它添加到我的MVC项目,但它无法正常工作。有一个自定义Httpmodule,它有一个Init()函数,并在每个请求中调用它。问题出在哪里。

init()必须在所有应用程序生命周期中运行一次,但它在每个请求上运行。 这段代码在asp.net上运行良好,但由于init()方法在每个请求中都运行,因此它无法在MVC上运行。

public class OnlineUsersModule : IHttpModule
{
    private static Int32 _sessionTimeOut = 20; // Set Default to 20 Minutes
    private static List<OnlineUserInfo> _onlineUsers = null;

    public static List<OnlineUserInfo> OnlineUsers
    {
        get
        {
            CleanExpiredSessions();
            return _onlineUsers;
        }
    }

    private static void CleanExpiredSessions()
    {
        _onlineUsers.RemoveAll(delegate(OnlineUserInfo user)
        {
            return user.SessionStarted.AddMinutes(_sessionTimeOut) < DateTime.Now;
        });
    }

    #region IHttpModule Members

    public void Init(HttpApplication context)
    {
        _onlineUsers = new List<OnlineUserInfo>();

        // Get the Current Session State Module
        SessionStateModule module = context.Modules["Session"] as SessionStateModule;

        module.Start += new EventHandler(Session_Start);

    }


    private void Session_Start(object sender, EventArgs e)
    {
        HttpRequest Request = HttpContext.Current.Request;
        HttpApplicationState Application = HttpContext.Current.Application;
        HttpSessionState Session = HttpContext.Current.Session;

        // Get Session TimeOut
        _sessionTimeOut = HttpContext.Current.Session.Timeout;

        Application.Lock();

        OnlineUserInfo user = new OnlineUserInfo();

        user.SessionId = Session.SessionID;
        user.SessionStarted = DateTime.Now;
        user.UserAgent = !String.IsNullOrEmpty(Request.UserAgent)
            ? Request.UserAgent : String.Empty;
        user.IPAddress = !String.IsNullOrEmpty(Request.UserHostAddress)
            ? Request.UserHostAddress : String.Empty;
        if (Request.UrlReferrer != null)
        {
            user.UrlReferrer = !String.IsNullOrEmpty(Request.UrlReferrer.OriginalString)
                ? Request.UrlReferrer.OriginalString : String.Empty;
        }
        else
        {
            user.UrlReferrer = String.Empty;
        }
        if (HttpContext.Current.User.Identity.IsAuthenticated)
        {
            user.CurrentUser = HttpContext.Current.User;
        }

        // Add the New User to Collection
        _onlineUsers.Add(user);
        Application.UnLock();
    }

    public void Dispose()
    {
    }

    #endregion
}


public class OnlineUserInfo
{
    public String UserAgent { get; set; }
    public String SessionId { get; set; }
    public String IPAddress { get; set; }
    public String UrlReferrer { get; set; }
    public DateTime SessionStarted { get; set; }
    public IPrincipal CurrentUser { get; set; }

    public override string ToString()
    {
        StringBuilder sb = new StringBuilder();
        sb.AppendFormat("UserAgent = {0} | ", UserAgent);
        sb.AppendFormat("SessionId = {0} | ", SessionId);
        sb.AppendFormat("IPAddress = {0} | ", IPAddress);
        sb.AppendFormat("UrlReferrer = {0} | ", UrlReferrer);
        sb.AppendFormat("SessionStarted = {0}", SessionStarted);
        return sb.ToString();
    }
}

另外我认为还有一个问题。当我向init()方法添加断点时,在推送F10之后它进入init()的开始意味着有其他线程试图运行init()这是一个问题吗?

2 个答案:

答案 0 :(得分:4)

HttpModules住在游泳池里。当您的应用程序启动并将其放入池中时,ASP.NET进程会创建并初始化它们(可配置的)数量。

然后,每次请求进入实例时,都会从池中获取并分配给请求服务。目前没有初始化。完成请求的处理后,将实例放回池中以供以后使用。

在负载很重的情况下,系统可以决定创建更多HttpModules实例

HTH

答案 1 :(得分:3)

也许您每次都使用Cassini并重新编译应用程序 F5 ,这会产生每次请求都会调用Init方法的错觉。