Custom Session State Module - Use ASP State Service - asp.net

EDIT (clarifying my question): Is there an API or method with which we can use the Out Of Process Asp.NET State Service from our own code or is that proprietary?
We are looking into implementing a custom session state module that re-uses the components of the module that comes stock with asp. Our main goal is to just prevent session locking (without changing the session state mode to ReadOnly). Is this possible?
One of the key pieces that we would like to make work is to be able to use the same Out of Proc Session storage provider (The ASP State service) that is used internally by .NET as we have a load-balanced environment that doesn't use sticky sessions.
I have dug into the code over in the reference source, and my findings are below. I am hoping somebody has a different utility that could potentially be used to integrate a custom session state module the ASP State Service.
The default session Module is System.Web.SessionState.SessionStateModule. This is a Sealed class. This class appears to be the only class that uses the SessionStateMode.StateServer enum value (which is specified in the web config).
When this flag is set, the module sets the _store variable to be a new System.Web.SessionState.OutOfProcSessionStateStore which is a Friend Sealed class.
I had initially had a few thoughts on how to do this, and because of the modifiers on the classes above I was unable to do these. Are there other approaches that could be taken?
Instantiate a new System.Web.SessionState.SessionStateModule and reference the _store variable. This did not work, obviously because the _store variable is private.
I tried creating a class which inherits from System.Web.SessionState.SessionStateModule but obviously since it is sealed that does not work.
Looked at copying the code from the .NET framework code. Realized that would be a very poor decision.
Are there any options I am missing?

I would recommend you reading this topic: I just discovered why all ASP.Net websites are slow, and I am trying to work out what to do about it.
It provides some starting points and info on the session topic, especially locking problem.
If you look for custom implementation of session module you can look here:
http://www.codeproject.com/Articles/11712/Custom-session-state-management-in-ASP-NET

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.

asp.net serialization exception is thrown when implementing session in sql server

"serialization exception thrown in System.Web.Profile.DefaultProfile"
I'm using a lot of custom classes but have marked them all with serializable attribute. The website loads properly initially on the default page, but once a redirection happens to a different page, which inherits the custom "BasePage" class, instead of the default Page class, this exception is thrown :
Unable to serialize the session state. In 'StateServer' and 'SQLServer' mode, ASP.NET will serialize the session state objects, and as a result non-serializable objects or MarshalByRef objects are not permitted. The same restriction applies if similar serialization is done by the custom session state store in 'Custom' mode.
one of the statements in the intellitrace says something like, "failed to serialize System.Web.Profile.DefaultProfile could not be serialized". Isn't it an inbuilt .NET object, and if so cannot I presume that it should be serializable in all cases???
I just ran into this same problem yesterday. The custom object isn't necessarily the problem, but objects inside of that. If you have things like System.Drawing.Image or Dictionary<> or anything else that isn't inherently serializable, its gonna blow up. So you're gonna have to do some digging. I had to do things like convert a List into a string[] to pass it to the web service (which receives a List but shows in intellisense as receiving a string[]).
So I'd rethink that. We also found out that once we got that working in the test server, we weren't done. As soon as we published the web service, other problems started popping up that were similar. Images were not serializable so we converted them to byte[] before sending them, Dictionaries were also not serializable.
I realize this isn't much of an answer, but hopefully of some help.
It is built into ASP.Net, but that doesn't mean it's serializable. There's lots of framework classes that are not serializable.
But also, the Default profile is made to work with the asp.net profile mechanism. Why are you attempting to store that in session? It already has it's own configurable storage mechanism. I think this may be a case where you're in a place where you're fighting the system.
For my particular case, I worked around the problem by creating a new custom class with a Serializable attribute, with a property that would return the HttpContext.Current.Profile object. And then whenever I needed to add the profile into session, I'm adding it through the property of this newly created class. Thanks to #swannee and #Sinaesthetic for their ideas.

ObjectContext in ASP.Net

I'm working with a project in ASP.Net using Webforms. I'm using Entity Framework to save data on Microsoft SQL.
My question is:
Is possible to use a Static class to keep the ObjectContext of EF live and put/get entities NOT saved inside the ObjectContext?
I want to create an Object, then added with AddObject on the ObjectContext, But NOT to do the Savechanges. All this in one webform. And then, in other webform, access to the ObjectContext and get the Object when added.
It is this possible?
My rules to using ObjectContext:
Do not use static context.
Do not share context.
You are trying to violate both rules. If you do that your application will have undeterministic behavior. Create new ObjectContext instance for each request. It is the same as openning new connection and starting new transaction in the request instead of sharing one connection and one transaction among all of them.
Further explanation also here. Also check linked question in right column and you will see what type of problems people have just because of violating one or both mentioned rules.
Also in web application it becames even more interesting because ObjectContext is not thread safe.
You could add it to the application items collection. See this blog post for syntax and such.
http://www.informit.com/articles/article.aspx?p=27315&seqNum=3
Generally, you don't want to. An ObjectContext is intended to be a unit of work, alive for a single set of related transactions. In an ASP.NET application, that generally corresponds to a single request.
If you must keep it alive for multiple requests, I wouldn't use either a static class, nor the application context. Instead, I'd recommend using the Cache, and then attaching the callbacks to it that let you ensure all your transactions are committed before it gets evicted, just in case.

How can I throw an Exception if Session is written to in ReadOnly mode?

I would like to find a way to raise an exception if the Session is written to when in readonly mode. When EnableSessionState is set to "ReadOnly", values can still be put in Session, but the next request they will not be there. This seems somewhat dangerous.
One option is to create a helper class which we alway use to access session. However, this still leaves room for a developer to inadvertently use session directly, and fall into the "readonly" trap. Is there a way to create a CustomSessionStateDataStore that sits on top of the existing session code? I could not see an obvious way, and you can't inherit from System.Web.SessionState.SessionStateStoreData directly.
Thanks for any help
Session state is built atop the provider model so you could create a custom session provider, I imagine.
Here's an article that discusses the provider model from a high-level view: ASP.NET 2.0 Provider Model: Introduction to the Provider Model.
And here's an article that talks about the session state providers and shows how to create your own custom provider: Session State Providers.
I ended up implementing my own SessionStateModule to achieve what I needed. See this thread for more info: I just discovered why all ASP.Net websites are slow, and I am trying to work out what to do about it

Session information in .net (asp and webservice)

I'm making a .net component, resulting in a dll assembly, that will be referenced by an asp.net site, and in another project by an asmx webservice. All code is version 2.0.
The component has a few functions that call an external webservice, which returns an object. One of these functions is for example Login(username, password), which generates amongst others a unique session id for this user. The resulting information and session id are stored in variables in the component.
The issue in the website is:
When the user logs in in the frontend, and my component gets called and checks the login and generates the session id, I want that information in my component to persist when the user browses to another page in the site.
The issue in the web service using my component is:
I don't really care much about session state, but I want the component to just work. If per call a new session id is generated, that's okay.
The combination of the two environments causes the following problem for me:
I can't use the asp.net Session() variable in my component without referencing system.web, which is kinda silly and might not be available in the web service project that includes my component
I can't program my component as a singleton, because then in the website application, it's shared amongst all visitors, overwriting sessions and whatnot
making an array of "session information" in my component and maintaining that is hard to program (when does it get invalidated?) and might not work in a web farm environment
Is there a solution to this situation? Or should I make two instances of my component, one for use in websites, and one for use in web services?
Perhaps I'm not understanding what your asking but why can't you do something like:
Component.Login(user,pass);
Session["Component"] = Component.SessionID
I've created an extra class "Factory" which has a .Create(byref Session as HttpSessionState), that looks if the passed in session object is Nothing, if not, it checks if there is a Component object in it, if so, it uses it, if not, it creates it and adds it to the session.
In the case of the webservice call, the factory gets the Nothing-parameter, so it doesn't check in the session object. It seems to work.
Thanks for your answers!

Resources