2

Referencing this answer regarding regenerating new SessionID

I created this code in my Global.asax.cs:

        protected void Application_Start(object sender, EventArgs e)
        {
            Bootstrapper.Initialized += new EventHandler<ExecutedEventArgs>(Bootstrapper_Initialized);
        }

        void Bootstrapper_Initialized(object sender, Telerik.Sitefinity.Data.ExecutedEventArgs e)
        {
            if (e.CommandName == "Bootstrapped")
            {
                EventHub.Subscribe<ILoginCompletedEvent>(LoginCompletedEventVerification);
            }
        }


        private void LoginCompletedEventVerification(ILoginCompletedEvent evt)
        {
            if (evt.LoginResult == UserLoggingReason.Success)
            {
                var manager = new SessionIDManager();
                var oldId = manager.GetSessionID(Context);
                var newId = manager.CreateSessionID(Context);
                bool isAdd = false, isRedir = false;
                manager.SaveSessionID(Context, newId, out isRedir, out isAdd);
                var ctx = HttpContext.Current.ApplicationInstance;
                var mods = ctx.Modules;
                var ssm = (SessionStateModule)mods.Get("Session");
                var fields = ssm.GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Instance);
                SessionStateStoreData rqItem = null;
                SessionStateStoreProviderBase store = null;
                FieldInfo rqIdField = null, rqLockIdField = null, rqStateNotFoundField = null;
                foreach (var field in fields)
                {
                    if (field.Name.Equals("_store")) store = (SessionStateStoreProviderBase)field.GetValue(ssm);
                    if (field.Name.Equals("_rqId")) rqIdField = field;
                    if (field.Name.Equals("_rqLockId")) rqLockIdField = field;
                    if (field.Name.Equals("_rqSessionStateNotFound")) rqStateNotFoundField = field;
                    if ((field.Name.Equals("_rqItem")))
                    {
                        rqItem = (SessionStateStoreData)field.GetValue(ssm);
                    }
                }
                var lockId = rqLockIdField.GetValue(ssm);
                if ((lockId != null) && (oldId != null))
                {
                    store.ReleaseItemExclusive(Context, oldId, lockId);
                    store.RemoveItem(Context, oldId, lockId, rqItem);
                }
                rqStateNotFoundField.SetValue(ssm, true);
                rqIdField.SetValue(ssm, newId);
            }
        }

Please keep in mind that I am developing in a Sitefinity web application. Every time my application hits LoginCompletedEventVerification during a successful login, Context comes up as null. Now, I initially wanted to add this snippet to the Sitefinity LoginWidget, but making that happen is a whole other story.

I did not include it in the code sample, but I do have Session_Start firing to create my application's "shopping cart." I am just trying to create a new SessionID for the cart after authentication.

Is there a reason I cannot get a value for Context during this event?

Thanks in advance. I appreciate any suggestions or criticism!

EDIT: Sitefinity knowledge base article where I got my Bootstrapper_Initialized code

Community
  • 1
  • 1
terbubbs
  • 1,512
  • 2
  • 25
  • 48

2 Answers2

4

I did not include it in the code sample, but I do have Session_Start firing to create my application's "shopping cart." I am just trying to create a new SessionID for the cart after authentication.

Nooooo. Forget about accessing HttpContext in the Application_Start event.

Alternatively you could do that in Application_BeginRequest:

private static object syncRoot = new object();
private static bool initialized = false;
public void Application_BeginRequest(object sender, EventArgs e)
{
    if (!initialized)
    {
        lock (syncRoot)
        {
            if (!initialized)
            {
                // Do your stuff here with HttpContext

                initialized = true;
            }
        }
    }
}

Another thing you should be aware of is that HttpContext will not be available in any background threads that you might have spawned and in which the HTTP request has already finished executing. So you should be extremely careful where you are trying to access this HttpContext.

Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
  • I wasn't accessing HttpContext in Application_Start but maybe I'm not understanding correctly. and thank you for a prompt response! – terbubbs Dec 30 '15 at 15:49
  • 1
    Yes, I can see that you are accessing it in some background thread. This also won't work for obvious reasons. The HttpContext should only be accessed from the main executing pipeline of the HTTP request. Trying to access it in any other event handlers which are outside of the control of ASP.NET will simply fail miserably. So make sure that this `LoginCompletedEventVerification` is not triggered on some background thread. If this is the case you will not be able to work with the HttpContext. – Darin Dimitrov Dec 30 '15 at 15:49
  • 1
    The solution with `Application_BeginRequest` won't help you if you are trying to access HttpContext in a background thread. It will help you only if you needed to access HttpContext directly in `Application_Start` (which isn't allowed, so doing it in the first Begin_Request is a workaround). – Darin Dimitrov Dec 30 '15 at 15:54
  • Okay. I should've mentioned I am following an article from Sitefinity in regards to `LoginCompletedEventVerification`. I'll have to see if this is triggered on a background thread. thank you for the information. – terbubbs Dec 30 '15 at 15:56
  • 1
    If `HttpContext.Current` is null it is clear that it is triggered on a background thread, unrelated with any ASP.NET context. It's the same as if you were trying to access `HttpContext.Current` in a Console Application. – Darin Dimitrov Dec 30 '15 at 15:57
1

The LoginCompletedEvent event is synchronous - it is not fired in a background thread, it is rather part of the authentication request. You can access the current context by either directly calling HttpContect.Current or since you are in the context of a Sitefinity application you can use the Sitefinity wrapper for the current context:

var currentContext = SystemManager.CurrentHttpContext;