ASP.NET MVC saving Entity session - asp.net-mvc

I have been working with entity framework and ASP MVC for a while. I have stored the entity object in the HttpContext.Current.Session in order to use the same session at all times. Now I have encountered some problems and I am wondering if this may have been a bad idea and if so, how should I do it otherwise.
The problem I have now is that the entity object caches data and that one user cannot see changes that the other user has done.

The session is basically a hash table-like structure that is specific to a user. If you want to store data that can be seen by all users of the system, you either want to use the Application scope or caching.
This article from MS covers the different options for state management, including session and application:
http://msdn.microsoft.com/en-us/library/75x4ha6s.aspx
Caching is slightly different in that it allows you to do things like set expiration. If you don't need this kind of functionality, I would recommend sticking with application state. Article on caching from MS:
http://msdn.microsoft.com/en-us/library/6hbbsfk6(VS.71).aspx

The problem with storing Entities in memory between requests / sessions or whatever is that you have to be very careful if you have a new ObjectContext for each request / session whatever, because and entity can only be attached to one ObjectContext at a time, and can be easy to forget to detach (between requests in the same session) or to correctly share an object (between concurrent requests in different sessions).
Check out this Tip for clues on how to cache data between requests / users / sessions etc.
Hope this helps
Alex

By the book you would want your object context exist the shortest time possible.
so you create a context, grab some data, return your view to client.
and dispose everything.
Start caching when your db can't handle your load.

Related

nHibernate w/ASP.NET Session Per Request And Active Work Item

I am building an ASP.NET application using nhibernate and I implemented the session per request architecture. Each request I am opening a session, using it, then closing it. I am using one large object across several views and I am storing the object in user session cache so it maintains state for them across several different pages. The users do not want to have to save their changes on each page, they want the ability to navigate between several pages making changes, then commit them to the DB. This works well except for when the users try to hit a page that triggers lazy loading on the proxy object (which fails due to the session per request design closing the nhibernate session in the previous request). I know that turning lazy loading off would fix it; however, that is not an option due to the performance issues it would cause in other areas. I have tried changing the session per request design but have had no luck since I do not know when it is "safe" to close the nhibernate session.
Has anyone else done anything similar to this or have any advice?
Thanks in advance!
Keeping any objects in user session - the server session, server resource is not the best approach. Just imagine, that accidently your application will be very very successful... and there will be many users... therefore many sessions == many resources.
I would suggest (based on some experience), try to re-think the architecture to avoid session. Extreme would be to go to single page application... but even some async during "...navigation among several pages..." will be better.
All that will mean, that:
we passs data to client (standard ASP.NET MVC way with rendered views or some Web Api JSON)
if needed we send data back to server (binding of forms or formatting JSON)
In these scenarios, standard NHiberante session will work. Why? Because we "reload and reassign" objects with standard NHibernat infrastructure. That would be the way I suggest to go...
But if you want to follow your way, then definitely check the merge functionality of NHibernate:
9.4.2. Updating detached objects
9.4.3. Reattaching detached objects
19.1.4. Initializing collections and proxies
Some cites:
In an application with a separate business tier, the business logic must "prepare" all collections that will be needed by the web tier before returning. This means that the business tier should load all the data and return all the data already initialized to the presentation/web tier that is required for a particular use case. Usually, the application calls NHibernateUtil.Initialize() for each collection that will be needed in the web tier (this call must occur before the session is closed) or retrieves the collection eagerly using a NHibernate query with a FETCH clause or a FetchMode.Join in ICriteria. This is usually easier if you adopt the Command pattern instead of a Session Facade.
You may also attach a previously loaded object to a new ISession with Merge() or Lock() before accessing uninitialized collections (or other proxies). No, NHibernate does not, and certainly should not do this automatically, since it would introduce ad hoc transaction semantics!

TempData: Is It Safe?

I am using the TempData in order to preserve my model in when using a RedirectToAction. It works fine, but I have a nagging feeling that it might not be the right thing to do. I really try to avoid using Session data, and I've read that TempData uses the Session. Is it safe to use? Are there issues which might arise in using it in a load balanced environment?
Trivia Question: "Is It Safe?"-- name the movie.
Yes, TempData is backed by session storage, so if you are in a load balanced environment extra care must be taken when using it (sticky sessions, persistent session state, etc).
TempData has been the de-facto choice when using the PRG pattern, and is what it was designed for.
As to whether it's the right thing to do... it depends on your use case!
PS Marathon Man.
Well, I would argue that it depends. If you handle lot of traffic with load balancers and multiple front end server, then session objects is something to avoid because it could degrade performance and make hotizontal scaling difficult (on farm request doesn't come always to same web server).
TempData is short-lived, and if you don't put there lot of objects there and think twice about whole architecture, I think then it's safe. There's lot of sites that use it extensively and don't have problems with it (I worked on shared and dedicated hosted sites with up to avarage 50-70k visitors/day that use session, often with web and db on same server).
I would go, whenever possible, for a fully stateless approach. It's more scalable and is not affected by problems with individual servers. Typically, you can just use a cookie (properly secured against tampering) to identify the user and pull the data from the database every time.
Besides that, I also suggest you to evaluate whether you can use View instead of RedirectToAction. This:
TempData["model"] = model;
return RedirectToAction("SomeAction");
Can be replaced with:
return View("SomeAction", model);
Of course assuming "SomeAction" is a valid view that is accessible from the current controller (it's either a view in the same ctrl or one defined in Shared) and that it's not just an intermediate action that redirects to another one.
Session state can work in a clustered environment, providing that one of two things happens
Your load balancer supports "sticky" sessions (i.e. all requests in a given session are routed to the same machine)
You configure the session provider to use an out of process session provider, you can use either the ASP.NET State Service or the SQL Session State Provider
The question of whether you should use tempdata or not is a different question altogether. I would argue that there is usually a way around it. If you are trying to avoid a hit to the database to reload an object that one action has already loaded, look at using a cache instead.
I have limited the use of TempData to pass model object validation message between views and action. I haven't looked into the usage of Tempdata from security perspective but following SO thread discuss the same : HttpContext.Items with ASP.NET MVC. See the last few thread comments and related discussions.

JSF 2 Handling Data

I'm developing an app with JSF2 in Tomcat. Still pretty fresh to JSF I have a question which I guess is pretty simple to answer to someone who's got fairly good experience developing web aps and specifically in JSF 2. It's about the way one should store user's data during their interaction with the application. As it stands right now I am saving a lot of data in a session scoped managed bean (like collection of earlier pulled from database entities which themselves are linked to other entities) and whenever a request is made the application will serve anyone of those objects stored in that collection. But I am worried that the session bean is becoming over bloated and don't know how much memory it is safe for a single session bean to consume. What I don't know is whwther when the app goes into production, and a lot of users log, is then the server gonna be ok to handle it. So I guess my question is as follows.
Is there any rule to go buy about storing, handlind and serving large amounts of users data that comes from the database:
Is it ok to do it my way (that is store a lot of stuff in a session scoped bean) so that with each request the app doesn't nee to query and retrieve the data from database. And it that's the case how to best load entities linked to an object stored in a list so they are not all loaded at once but only after the actual object is used to perform some operations before sending the data to the user.
Or should the app keep session beans fairly light (no lists of pre-pulled enities, objects etc) and instead make a trip to the database every time a larger piece of data is required, retrieve it and serve on the fly?
Or perhaps there's an entirely different method, preferred or recommended, to do this.
All suggestions and help are very much appreciated.
You should definitely not do the entity caching job by a JSF session scoped bean. You should delegate the entity caching job to the persistence layer and configure/finetune it over there. JPA and Hibernate for example have pretty good caching support. Here are some articles to read about it:
Javalobby - JPA Caching
EclipseLink Examples - JPA Caching
Hibernate Reference - Chapter 21 - Improving performance
A JSF session scoped bean should merely just contain session scoped data which is used in every request of the webapp throughout the entire browser session. For example, the logged-in user, the user preferences, the user language/locale, etcetera.
The (form) data should just be represented by a JSF request or view scoped bean. Just call the database on every fresh new request or view and do not worry about the costliness of the database trips in your JSF backing bean. Let the persistence layer worry about it.

Relying on nhibernate's second level cache vs pushing objects into asp.net session

I have some big entities which are frequently accessed in the same session. For example, in my application there is a reporting page which consist of dynamically generated chart images. For each chart image on this page, the client makes requests to corresponding controller and the controller generates images using some entities.
I can either use asp.net's session dictionary for "caching" those entities or rely on nhibernate's second level cache support with using cached queries for example.
What is your opinion?
By the way I will use shared hosting, is nhibernate's second level cache hosting friendly?
Thanks.
I think you should use NHibernate's cache. If user makes distinct request to get each entity one by one then you probably should use different NHibernate ISession implementations to get them (bacause of session per web request strategy).
Also when using Nhibernate cache you won't have troubles with concurrency issues - it will handle them for you.
Be aware of caching an entity (from the session you loaded it from) in a static variable, that is then accessed by another session (eg, pulled from the cache system you made).
Entity instances are tied to a Session remember, so you shouldn't mix and match instances across Session boundaries.
I've solved this before by creating a light version of the class (that is not NH Session aware) and caching that basic class instead.
Alternatively, use the 2nd level cache, which doesn't have this problem.

Proper way to maintain (non-critical) state accross multiple asp.net MVC Pages

This sounds like a contradiction in terms, or flamebait, but I'm hoping its not actually.
Background:
I need to maintain a few preferences across the entirety of a user's log in. These preferences mostly affect how something is viewed, although they may be passed to the controller layer to accomplish this. At no time should any of these user/session preferences affect data directly.
Question:
How do I temporarily store data across pages/controllers in an MVC setting, so that the controllers can use it (not depend on it) when convenient.
I am thinking session but searches on session and asp.net MVC turn up lots of material on tempdata, which is not what I need. Rather a dictionary per user session of non-essential data would be ideal.
Thanks
Adam
Option 1. You store it on the client-side. Put these settings in cookies, they will be available at each following request.
Option 2. You store it server-side. Put it in session but bind it to user id, it can also be easily accessed.
Option 3. You store it in database. Consequently, load these settings from the db on each request. Alternatively, cache it.
I don't believe there's any good reason not to use session. I'd be tempted to say that the moment something is required across pages then it's no longer 'temporary'.
You could use MS's distributed cache velocity, backed by a database table if necessary. Maintaining your settings this way only requires some extra memory, and shouldn't bog down your server with extra requests. The settings will also expire when they haven't been used recently, or when enough new settings are placed in the cache.
There is also a session provider within velocity which may do what you want.
Using the Session object on the controller/viewpage is probably what you want to do. Normally, what I would do is persist the user choices to a database (preferences table), then use the Session as a cache for the user's Preferences object. I often make this a property on a base controller that is lazy-loaded from the Session, if it exists, or the database, populating the Session as needed.

Resources