asp.net会话没有存储在sql中

时间:2017-05-19 13:00:26

标签: c# asp.net-mvc session

我使用带有个人用户帐户的asp.net mvc 5网站模板项目,基于custom session state provider编写了我自己的entity framework。 当我启动我的应用程序时,注册一个新的网站用户并登录,除了我手动将一些值设置为UserId变量之外,没有会话信息(如Session)存储在数据库表中。在调试我的custom session state provider后,我可以说它运作良好,但这不是我想要的。

我认为每个网站页面加载都会以唯一的会话ID启动新会话,或者继续当前会话ID,会话ID存储在浏览器cookie中,并通过custom session state provider写入数据库。我尝试实现这样的应用程序行为,我该如何实现这样的应用程序行为?

经过6个月的努力解决这个问题后,我完全

更新

我想跟踪数据库中的所有会话,甚至是匿名用户的空会话,但只有在我将某些值设置为Session变量时才会创建新的会话数据库记录。我还需要在密码更改时强制所有计算机/浏览器的注销用户。这是一个复杂的asp.net会话状态机制,我无法理解。

public class WebsiteSessionStateProvider : SessionStateStoreProviderBase
{
    WebsiteDbContext m_DbContext;
    int m_Timeout;

    public WebsiteDbContext DatabaseContext
    {
        get
        {
            return m_DbContext ?? HttpContext.Current.GetOwinContext().GetUserManager<WebsiteDbContext>();
        }
        private set
        {
            m_DbContext = value;
        }
    }

    public override void Initialize(string name, NameValueCollection config)
    {
        if (config == null) throw new ArgumentNullException(nameof(config));
        base.Initialize(name, config);

        var applicationName = System.Web.Hosting.HostingEnvironment.ApplicationVirtualPath;
        var configuration = WebConfigurationManager.OpenWebConfiguration(applicationName);

        var configSection = (SessionStateSection)configuration.GetSection("system.web/sessionState");
        m_Timeout = (int)configSection.Timeout.TotalMinutes;
    }

    public override void Dispose()
    {

    }

    public override SessionStateStoreData GetItem(HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actions)
    {
        return GetSessionItem(context, id, false, out locked, out lockAge, out lockId, out actions);
    }

    public override SessionStateStoreData GetItemExclusive(HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actions)
    {
        return GetSessionItem(context, id, true, out locked, out lockAge, out lockId, out actions);
    }

    private SessionStateStoreData GetSessionItem(HttpContext context, string id, bool exclusive, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actions)
    {
        locked = false;
        lockAge = new TimeSpan();
        lockId = null;
        actions = 0;

        var SessionItem = DatabaseContext.Sessions.Find(id);

        if (SessionItem == null) return null;

        if (SessionItem.IsLocked)
        {
            locked = true;
            lockAge = DateTime.UtcNow - SessionItem.TimeLocked;
            lockId = SessionItem.LockId;
            return null;
        }

        if (DateTime.UtcNow > SessionItem.TimeExpires)
        {
            DatabaseContext.Entry(SessionItem).State = EntityState.Deleted;
            DatabaseContext.SaveChanges();
            return null;
        }

        if (exclusive)
        {
            SessionItem.LockId += 1;
            SessionItem.IsLocked = true;
            SessionItem.TimeLocked = DateTime.UtcNow;
            DatabaseContext.SaveChanges();
        }

        locked = exclusive;
        lockAge = DateTime.UtcNow - SessionItem.TimeLocked;
        lockId = SessionItem.LockId;

        var data = (SessionItem.Content == null)
            ? CreateNewStoreData(context, m_Timeout)
            : Deserialize(context, SessionItem.Content, m_Timeout);

        data.Items["UserId"] = SessionItem.User.Id;

        return data;
    }

    public override void ReleaseItemExclusive(HttpContext context, string id, object lockId)
    {
        var SessionItem = DatabaseContext.Sessions.Find(id);
        if (SessionItem.LockId != (int)lockId) return;

        SessionItem.IsLocked = false;
        SessionItem.TimeExpires = DateTime.UtcNow.AddMinutes(m_Timeout);
        DatabaseContext.SaveChanges();
    }

    public override void SetAndReleaseItemExclusive(HttpContext context,
                                                    string id,
                                                    SessionStateStoreData item,
                                                    object lockId,
                                                    bool newItem)
    {
        var intLockId = lockId == null ? 0 : (int)lockId;
        var userId = (string)item.Items["UserId"];

        var data = ((SessionStateItemCollection)item.Items);
        data.Remove("UserId");

        var Content = Serialize(data);

        if (newItem)
        {
            var session = new Session
            {
                SessionId = id,
                User = DatabaseContext.Users.Find(userId),
                TimeCreated = DateTime.UtcNow,
                TimeExpires = DateTime.UtcNow.AddMinutes(m_Timeout),
                TimeLocked = DateTime.UtcNow,
                IsLocked = false,
                Content = Content,
                LockId = 0,
            };

            DatabaseContext.Sessions.Add(session);
            DatabaseContext.SaveChanges();
            return;
        }

        var state = DatabaseContext.Sessions.Find(id);
        if (state.LockId == (int)lockId)
        {
            state.User = DatabaseContext.Users.Find(userId);
            state.Content = Content;
            state.TimeExpires = DateTime.UtcNow.AddMinutes(m_Timeout);
            state.IsLocked = false;
            DatabaseContext.SaveChanges();
        }
    }

    public override void RemoveItem(HttpContext context, string id, object lockId, SessionStateStoreData item)
    {
        var state = DatabaseContext.Sessions.Find(id);
        if (state.LockId != (int)lockId) return;

        DatabaseContext.Entry(state).State = EntityState.Deleted;
        DatabaseContext.SaveChanges();
    }

    public override void ResetItemTimeout(HttpContext context, string id)
    {
        var SessionItem = DatabaseContext.Sessions.Find(id);
        if (SessionItem == null) return;

        SessionItem.TimeExpires = DateTime.UtcNow.AddMinutes(m_Timeout);
        DatabaseContext.SaveChanges();
    }

    public override SessionStateStoreData CreateNewStoreData(HttpContext context, int timeout)
    {
        var data = new SessionStateStoreData(new SessionStateItemCollection(),
                                                SessionStateUtility.GetSessionStaticObjects(context),
                                                timeout);

        data.Items["UserId"] = String.Empty;
        return data;
    }

    public override void CreateUninitializedItem(HttpContext context, string id, int timeout)
    {
        var session = new Session
        {
            SessionId = id,
            User = null,
            TimeCreated = DateTime.UtcNow,
            TimeExpires = DateTime.UtcNow.AddMinutes(timeout),
            TimeLocked = DateTime.UtcNow,
            IsLocked = false,
            Content = null,
            LockId = 0,
        };

        DatabaseContext.Sessions.Add(session);
        DatabaseContext.SaveChanges();
    }

    public override bool SetItemExpireCallback(SessionStateItemExpireCallback expireCallback) { return false; }
    public override void EndRequest(HttpContext context) { }
    public override void InitializeRequest(HttpContext context) { }

    private byte[] Serialize(SessionStateItemCollection items)
    {
        var ms = new MemoryStream();
        var writer = new BinaryWriter(ms);

        if (items != null) items.Serialize(writer);
        writer.Close();

        return ms.ToArray();
    }

    private SessionStateStoreData Deserialize(HttpContext context, Byte[] serializedItems, int timeout)
    {
        var ms = new MemoryStream(serializedItems);

        var SessionItems = new SessionStateItemCollection();

        if (ms.Length > 0)
        {
            var reader = new BinaryReader(ms);
            SessionItems = SessionStateItemCollection.Deserialize(reader);
        }

        return new SessionStateStoreData(SessionItems, SessionStateUtility.GetSessionStaticObjects(context), timeout);
    }

}

1 个答案:

答案 0 :(得分:0)

  

除非我手动将某些值设置为会话变量

,否则没有会话信息(如UserId)存储在数据库表中

这正是会话提供者的用途:从Web应用程序中抽象出会话数据的存储。

如果您未在会话中放置任何内容,则您的提供商不会存储任何内容。