ASP.NET Session and Thread issue - asp.net

In my ASP.NET application I created a custom thread. The thread is updating the session. When I am using InProc session state it works well, but when using SQLServer session state the session is not being updated. Any ideas?

I can't find documentation to back it up, but I think that the SqlServer session state will serialize the Session to the database at the end of the request processing. So anything that's changed after that time is ignored as a new request will get the session from the database.

What are doing in that process is important ? It seems that you are updating some object that stored inside session.
Now it is working with InProcess and not with Sql means you have problem with object serialization.
IF you are using some class whoes instance stored in Session that make that class serializable.
If this not help you please provide more information.
Thanks.

To see a practical example of what is going on check out this question (with example code) I posted a few days ago.
I don't think there is a way to "let the main thread know it should wait before it serializes to the data store". You just have to wait until the background thread finishes. Which kinda defeats the purpose of using the background thread in the first place.

Related

How can I slowly migrate to using Redis as a Session State Provider from in process?

Is it a bad idea to implement my own session state provider that conditionally switches based on key between the redis session provider and the inproc session provider?
I am working in a very large legacy asp.net application that currently uses the inproc session provider. We are migrating to Redis as a session state provider so that it persists deploys, however the application is chock full of session abuses (e.g. way too large objects, non-serializable object, I saw a thread in there for some reason?).
We plan to slowly correct these abuses but until they are all corrected we cannot really move to redis. I am hoping we can slowly start migrate serializable-safe keys into redis while the abuses remain in memory until we address them.
Does anyone have any advice on this? Or perhaps alternative suggestions for migrating to out of process from in process?
Thanks!
In ASP.NET Web Form and MVC, using Redis for Session State is just a couple of line of modification in Web.config. Then add SerializableAttribute to classes. There is no side effects of applying it to a class.
Based on my experience when migrating to Azure few years ago, Session State is not worth migrating slowly.
Caching is different story. It requires code changes, so we end up implementing two classes - MemoryCacheManager and RedisCacheManager, and register at run-time in IoC container. Then inject ICacheManager to dependent classes.
Source for the session state: https://github.com/Microsoft/referencesource/blob/master/System.Web/State/
Docs: https://learn.microsoft.com/en-us/dotnet/api/system.web.sessionstate?view=netframework-4.7.2
I'd start by checking out the reference source so you can search the codebase. One interface jumps out as potentially interesting.. IPartialSessionState (When implemented in a type, returns a list of zero or more session keys that indicate to a session-state provider which session-state items have to be retrieved.) Source is here
https://learn.microsoft.com/en-us/dotnet/api/system.web.sessionstate.ipartialsessionstate?view=netframework-4.7.2
I stumbled on https://www.wiktorzychla.com/2007/06/wrapped-inprocsessionstatestore.html
via ASPNET : Switch between Session State Providers ?‏.
This technique could theoretically be used with the Redis provider as well. You'd have to either maintain a list of keys suitable for storing in Redis or do some kind of try to serialize/catch/cache result of which types can be serialized and adaptively fall back to the InProc behavior. You should be able to use HttpContext.Current.Items to flow information between events in the request processing pipeline.
The SessionStateModule (the module responsible for retrieving session, locking, saving, unlocking, etc.) seems to treat InProc as special in a few places. Search its code for InProc. Essentially you're trying to plug in a magical provider that is Custom and yet still has all of the InProc semantics applied by the one and only SessionStateModule. You won't be able to/probably won't want to modify that module, but you may be able to hook up another one adjacent to it that hooks into related events in the request pipeline and does whatever needs to be done that is either In-Proc or Custom-specific. You'll probably run into internal/private methods for which you'd need to use reflection. Not sure how the licensing works on the reference source (MS-PL I think), but another option would be to copy & paste the code from SessionStateModule into your own, make adjustments as needed, unregister the original and register your replacement.
I think you're going to be stuck dealing with a lot of reflection code to get this to work.

LazyInitializationException in ASP.NET app with NHibernate

Using NHibernate with ASP.NET 4.
I have had no issues retrieving objects, but I've just got to a point with nested objects that I can't figure out.
I am using lazy=true and when accessing a lazy-load collection I get the message:
Initializing[type#3]-failed to lazily initialize a collection of role: [type], no session or session was closed
Even if I call SessionFactory.OpenSession() immediately prior to the object being accessed, it makes no difference. I have also tried accessing the collection in a using ISession block to no luck.
Edit to add - I do have current_session_context_class = web set in web.config, and I am using CurrentSessionContext.Bind on BeginRequest.
Can anyone offer some advice?
Not an MVC app
I read this - don't know how accurate it is, and it is Hibernate:
http://opensource.atlassian.com/projects/hibernate/browse/HHH-2878
It says something about a bug in many-to-many relationships.
Here is my HBM mapping:
<bag name="Objects" table="ObjectInstance" cascade="all" lazy="true">
<key column="branchId" />
<many-to-many class="InventoryObjectInstance" column="objectInstanceId" />
</bag>
Does that happen after you perform some save/update operations? Where and when are you closing the session? To me, it sounds like you close the session right after save call or in some other method before the web page gets rendered. In other words, make sure you are using Open Session in View pattern and close the session only in the end of current web-request. You can also check out this post.
When object graphs are retrieved they keep a reference to the session that spawned them. They use that session for lazy loading of their properties. If the original session is closed, you will get this error (or one just like it) when trying to access them. Opening a new session will not help.
You can try to find where the original request session is being closed and stop that. Are you in the same request though? Failing that you can try to connect your object to a new session -- I think it is Session.Lock(YourObject). Alternatively you could retrieve the object again from the new session.
For some reason you are getting a new ISession when you call SessionFactory.OpenSession(). Is your first use of the session wrapping access to it in a using block? Why are you calling OpenSession again anyway -- what happened to the reference to the session?

Getting HttpContext from BackgroundWorker process

I have an ASP.NET site and I've been doing some work refactoring code to try to remove some long running processes (in the order of an hour) from the actual http Request by creating a BackgroundWorker and sending the work off to that to process. This was running fine on cutdown tests but when I applied the logic to the real code I found problems accessing Session variables from the code running in the Background Worker. It seems that the HttpContext object that was passed has a null session and if I ask for HttpContext.Current I get null back.
I'm assuming that this is because they are in a different thread and that the session and HttpContext.Current are both reliant on being in the same thread. Is there any way I can get access to the Session from the background worker or am I stuck with finding all the variables I need from session and putting them in an usable data structure and then putting them back in session (if appropriate) afterwards? It obviously complicates the refactor massively if I need to do this so I'd rather not.
Thanks for any thoughts you might have. I'm open to other suggestions on how I might do this other than BackgroundWorker processes (which were suggested to me in another question).
I'm not sure of all of your requirements, but you may be able to get away with using the Application Cache instead of the Session if you're not looking for the long process to be tied to an individual user's request.
If so, I would try swapping out your use of Session to:
HttpRuntime.Cache.Set("CacheKeyName");
HttpRuntime.Cache.Get("CacheKeyName");
Here's an MSDN link that sheds some light on this.
The text in particular is :
If an asynchronous action method calls a service that exposes methods by using the BeginMethod/EndMethod pattern, the callback method (that is, the method that is passed as the asynchronous callback parameter to the Begin method) might execute on a thread that is not under the control of ASP.NET. In that case, HttpContext.Current will be null, and the application might experience race conditions when it accesses members of the AsyncManager class such as Parameters. To make sure that you have access to the HttpContext.Current instance and to avoid the race condition, you can restore HttpContext.Current by calling Sync() from the callback method.

ASP.NET is there a way to save application state as session state on different server?

maybe the question is wrong but here is what i want to achieve maybe there is other way to do that.
I have ASP.NET application running .net 3.5, there is a client list and few others List based objects that are shared among all users of application. ie. when client logged in his userID and few other properties are saved within some List in Application state. Problem is that this application is heavy and it's application pool needs to be restarted once a day or so so all the information saved in these List objects is lost. While client personal data which is saved in Out-of-Proc mode on external server is saved.
Is there any way to workaround it ? Shared Session? Something like that.
PLEASE NO MSSQL SOLUTIONS...
Cheers, pros !!!!
Have you looked at caching the lists of data?
This SO article has some good detials.
You should only use Application State as a cache for data persisted elsewhere. You would then use Application_Start or some Lazy loading wrapper class to retrieve such persisted data into the application object.
If you are storing volatile data not persisted elsewhere in the application object then you are in trouble. Hopefully you would have abstracted access to the application object behind some wrapper object so that all your code is accessing the wrapper not tha application object. Now you would need to ensure the modifications are saved elsewhere so that they can be recovered on restart.
To be frank the Application state object is really an aid in porting ASP-Classic sites. Since you should really just treat the application state as a cache, there is an overlap in functionality between it and the ASP.NET Cache object.

How to force NHibernate to recognize db changes not made through NHibernate

I am implementing NHibernate into an existing web application. However, we have some other processes that do bulk inserting and updating on the database. How can I make NHibernate aware that changes are occurring on the backend db that were not initiated through NHibernate?
Most of the info that I have read around NHibernate use in asp.net have mentioned storing the Session object in the HttpContext or CallContext. This would then store the session object for the duration of the application lifecycle. This is what I have implemented. I was afraid of the costs of initializing NHibernate on each request. Isn't there a significant performance hit with this approach with initializing the Session object on each request?
Also, would it make more sense to store the SessionFactory in the the HttpContext or CallContext so that the mappings don't have to be regenerated on each request?
You shouldn't. NHibernate sessions are there to help you work in an ACID environment, which means that one transaction is not aware of any concurrent transactions. You should be using short sessions which do small sets of actions. You should not be holding sessions open for long periods of time. If you do need long periods of time for working with domain objects, then you should be detaching and then re-attaching the domain objects from and to different sessions.
Once you open a new session, any changes done to the database before the session was opened will be made available through NHibernate.
You should not store the Session over multiple requests. Bad, bad idea.
There is little to no overhead with recreating it on every call. It should use database connection pooling - which is where the bulk of the overhead would be.
By default NHibernate will not cache anything between sessions. If your sessions are short lived (per request), you shouldn't have much to worry about.
If you are using second level caching or query caching though, you may need to flush the cache manually. SessionFactory.Evict or SessionFactory.EvictQueries should help there. Restarting the app should also do it, but that's probably not the answer you're looking for.
In an ASP.NET app, the general usage I've seen is to create one SessionFactory for the app and create a new Session for each request.
The SessionFactory takes a while to initialize, is thread safe, and only needs to be initialized once.
The Sessions are not thread safe and are pretty quick to create.
Anything stored in the HttpContext will only be alive for the length of the request. Storing the session in the context is normal and should give you the desired result. The SessionFactory is usually stored in a static variable and will last as long as the app.
See the NHIbernateHelper class here for an example.

Resources