I am using Symfony ( current version 2.6.4 ) whenever I want to check if a user is loggedin ( I am also using FOSUserBundle ) I use $user = $this->getUser(); in my controller which works out just fine but if I open 10 links in 1 second this query is repeated for all 10 pages in that second, not so ideal in my option. So my question is, is there a way to cache this query for say 60 seconds and is it even advisable, will it affect new registrations or something. I am using APC as my doctrine cache but if someone knows the answer please also tell us how to use other ways incase other people also wonder how to do this. Thanks.
To start with, sql databases do a good job of automatically caching queries. So while there is some overhead in composing and sending the query to the server, the server itself will respond very quickly. You won't save much be adding another cache.
Should you still try and optimize? In your example of 10 requests per second one assumes that the requests are actually doing something besides getting the user. It's up to you to decide if caching the query will actually speed things up. In most cases the answer will be no. Trying to save every possible microsecond is called premature optimization and is something to avoid.
Having said that, it's worthwhile to look at what the security system is doing. Selected user information is stored in the session. You can use the debug profile bar to look at it. For each request, the security system pulls the user out of the session and then calls $user = $userProvider->refreshUser($user); By default, refreshUser is what causes the database to be queried.
You can easily plug in your own user provider (http://symfony.com/doc/current/cookbook/security/custom_provider.html) which just returns $user. No database interaction at all. Of course if the user's database information does change then they will need to log out and then log back in to see the changes. Or do something else to trigger a real refresh. But for many apps, not refreshing at all will work just fine.
It would also be easy enough to put a time stamp into the session. Your refreshUser method could then use the time stamp to decide if a refresh was actually needed.
So it's easy enough to eliminate the query and actually worthwhile just as a learning experience. Security is one of the more complicated components. The more you understand it the better off you will be. Customizing a user provider is one of the easier things to do.
I just saw your comment about the OAuthBundle. I have not used the bundle in awhile. Implemented my own but I'm surprised that it's hitting the oauth server on each request. If it is then this would in fact be a good use case for overriding the user provider. But I'd be surprised if it was really doing that just for user information.
Im working on asp.net website.
In some pages I'm saving the datatable into chache as
cache["dt"]=dt;
and using whereever I want in that page by fetching from chache.
I'm thinking that whenever session close I want to clear session in session_end event of global.asax file.
as cache["dt"]=null;
What is the better location to close either application_end or session end.
If I close in session_end will it affect to another user?
Please provide me clear helpful info regarding this.
Thanks
Since you are putting the datatable in Cache, meaning, that it's shared by all the users, then there's no right place/need to do this, since the only time when it actually needs to be removed is when the application ends and at that point all resources are freed; your application is no longer running.
Perhaps what you should/meant to do was to put the datatable in Session. If that is what you want, then you could remove it OnSession_End in Global.asax but know that SessionEnd is not guaranteed to fire. You can also do Session.Abandon() when the user logs out, which will clear all session objects.
I think you misunderstood the concept between Application Data, Session Data, and Cache. These three of them all different things.
Application Data/State stores the information available in application scope, i.e. all session/user can access these data.
Session Data store info for the current session data. The duration of the session can be specified in the configuration files.
Cache stores frequently used data. And this data may be costly to regenerate every time.
In your case, since you are using cache, I assume that this cache stores some frequently used data. Ideally, this cache should always be valid, as long as the information does not changes.
As such, my recommendations is to keep this cache value as long as possible.
Weird problem here, we're running a few mixed environment web applications, that use Windows or Forms authentication depending on where the user comes from.
I'm curious how everyone else might be handling expired sessions to avoid the errors you would get from someone leaving an idle session open for too long and then trying to resume work, mainly looking for best practices on the subject.
Any suggestions or opinions would be greatly appreciated.
Thanks,
I'm not sure how your authentication method affects session timeouts, the mechanism they use to get in shouldn't affect how long they can stay in.
Generally speaking, if someone does have an expired session, you can add code to check to see if their session is active. If it isn't, just redirect them to a login page, or display some other friendly text.
Basically something like:
if (Session.IsNewSession)
Response.Redirect("login.aspx");
Don't store unnecessary information on the session.
If you are storing something you can reload, have the appropriate code that will reload it if it wasn't found in the session
Consider if some processes are meant to be handled in long periods of time, in which case save intermediate info to the database.
If the user is doing a process that uses the session, and the data is missing, take them to step 1 (not much you can do about it, if you don't have the info elsewhere).
I have been asked up to come up with a state management strategy for a ASP .NET / MVC C# 3.5 web app
I have chose to go with storing sessions on a state server - this will be a separate physical box. I am concerned about the time that would be taken to serialize/deserialize objects when storing into sessions...
Does anyone know of a technique to get maximum performance when doing this?
Also would something like compressing information before storing it in session help or would this also result in slower performance times.
EDIT: I am using a separate box for the state server as we will have multiple web servers.
Personally the most common elements here are to work with reducing the amount of information put into session.
Compression MIGHT save space, but it is going to take more CPU time to get it done, more than likely causing either reduced performance or at minimum no net gain. Unless you are talking about REALLY big objects.
Example of Zip Compression on Session, Application, and Cache, used right here at StackOverflow.
Make sure you disable Session State on pages that don't use it. "By default, the ASP.NET session state manager performs two accesses—one read access and one write access—to the session data store in every request, regardless of whether the page requested uses session state." --MSDN Magazine
Be careful you're not trying to prematurely optimize your solution. Before implementing something like Session compression, it would probably be a good idea to conduct a series of benchmarks to determine if something like that is even necessary in your application.
You sure you'll be storing that much data in your session storage? Typical use of a session for a single user is a few hundred bytes!
As for serializing and de serializing, with that kinda small size is negilable.
Of course you'll be expecting more users than that, but still.
If your storing large amounts data in your session, then IMO, your doing it wrong.
Several have pointed out that too much data in session state per-user is a sign of a problem, but they haven't directly pointed at the solution to it: keep a user SQL database and store all the user info in that. Then the session state typically consists of just the logged in user's id. Any other state is probably directly related to the user's current activity, which suggests it can possibly be carried along more appropriately as in-memory cookies or querystring variables. Often this is the better option anyway, so that things to get into a corrupt state when users click their Back and Forward buttons.
I am wanting to store the "state" of some actions the user is performing in a series of different ASP.Net webforms. What are my choices for persisting state, and what are the pros/cons of each solution?
I have been using Session objects, and using some helper methods to strongly type the objects:
public static Account GetCurrentAccount(HttpSessionState session)
{
return (Account)session[ACCOUNT];
}
public static void SetCurrentAccount(Account obj, HttpSessionState session)
{
session[ACCOUNT] = obj;
}
I have been told by numerous sources that "Session is evil", so that is really the root cause of this question. I want to know what you think "best practice", and why.
There is nothing inherently evil with session state.
There are a couple of things to keep in mind that might bite you though:
If the user presses the browser back button you go back to the previous page but your session state is not reverted. So your CurrentAccount might not be what it originally was on the page.
ASP.NET processes can get recycled by IIS. When that happens you next request will start a new process. If you are using in process session state, the default, it will be gone :-(
Session can also timeout with the same result if the user isn't active for some time. This defaults to 20 minutes so a nice lunch will do it.
Using out of process session state requires all objects stored in session state to be serializable.
If the user opens a second browser window he will expect to have a second and distinct application but the session state is most likely going to be shared between to two. So changing the CurrentAccount in one browser window will do the same in the other.
Your two choices for temporarily storing form data are, first, to store each form's information in session state variable(s) and, second, to pass the form information along using URL parameters. Using Cookies as a potential third option is simply not workable for the simple reason that many of your visitors are likely to have cookies turned off (this doesn't affect session cookies, however). Also, I am assuming by the nature of your question that you do not want to store this information in a database table until it is fully committed.
Using Session variable(s) is the classic solution to this problem but it does suffer from a few drawbacks. Among these are (1) large amounts of data can use up server RAM if you are using inproc session management, (2) sharing session variables across multiple servers in a server farm requires additional considerations, and (3) a professionally-designed app must guard against session expiration (don't just cast a session variable and use it - if the session has expired the cast will throw an error). However, for the vast majority of applications, session variables are unquestionably the way to go.
The alternative is to pass each form's information along in the URL. The primary problem with this approach is that you'll have to be extremely careful about "passing along" information. For example, if you are collecting information in four pages, you would need to collect information in the first, pass it in the URL to the second page where you must store it in that page's viewstate. Then, when calling the third page, you'll collect form data from the second page plus the viewstate variables and encode both in the URL, etc. If you have five or more pages or if the visitor will be jumping around the site, you'll have a real mess on your hands. Keep in mind also that all information will need to A) be serialized to a URL-safe string and B) encoded in such a manner as to prevent simple URL-based hacks (e.g. if you put the price in clear-text and pass it along, someone could change the price). Note that you can reduce some of these problems by creating a kind of "session manager" and have it manage the URL strings for you but you would still have to be extremely sensitive to the possibility that any given link could blow away someone's entire session if it isn't managed properly.
In the end, I use URL variables only for passing along very limited data from one page to the next (e.g. an item's ID as encoded in a link to that item).
Let us assume, then, that you would indeed manage a user's data using the built-in Sessions capability. Why would someone tell you that "Session is evil"? Well, in addition to the memory load, server-farm, and expiration considerations presented above, the primary critique of Session variables that they are, effectively, untyped variables.
Fortunately, prudent use of Session variables can avoid memory problems (big items should be kept in the database anyhow) and if you are running a site large enough to need a server farm, there are plenty of mechanisms available for sharing state built in to ASP.NET (hint: you will not use inproc storage).
To avoid essentially all of the rest of Session's drawbacks, I recommend that implement an object to hold your session data as well as some simple Session object management capabilities. Then build these into a descendent of the Page class and use this descendent Page class for all of your pages. It is then a simple matter to access your Session data via the page class as a set of strongly-typed values. Note that your Object's fields will give you a way to access each of your "session variables" in a strongly typed manner (e.g. one field per variable).
Let me know if this is a straightforward task for you or if you'd like some sample code!
As far as I know, Session is the intended way of storing this information. Please keep in mind that session state generally is stored in the process by default. If you have multiple web servers, or if there is an IIS reboot, you lose session state. This can be fixed by using a ASP.NET State Service, or even an SQL database to store sessions. This ensures people get their session back, even if they are rerouted to a different web server, or in case of a recycle of the worker process.
One of the reasons for its sinister reputation is that hurried developers overuse it with string literals in UI code (rather than a helper class like yours) as the item keys, and end up with a big bag of untestable promiscuous state. Some sort of wrapper is an entry-level requirement for non-evil session use.
As for "Session being evil" ... if you were developing in classic ASP I would have to agree, but ASP.NET/IIS does a much better job.
The real question is what is the best way to maintain state. In our case, when it comes to the current logged in user, we store that object in Session, as we are constantly referring to it for their name, email address, authorization and so forth.
Other little tidbits of information that doesn't need any long-term persistence we use a combination of cookies and viewstate.
When you want to store information that can be accessed globally in your web application, a way of doing this is the ThreadStatic attribute. This turns a static member of a Class into a member that is shared by the current thread, but not other threads. The advantage of ThreadStatic is that you don't have to have a web context available. For instance, if you have a back end that does not reference System.Web, but want to share information there as well, you can set the user's id at the beginning of every request in the ThreadStatic property, and reference it in your dependency without the need of having access to the Session object.
Because it is static but only to a single thread, we ensure that other simultaneous visitors don't get our session. This works, as long as you ensure that the property is reset for every request. This makes it an ideal companion to cookies.
I think using Session object is OK in this case, but you should remember Session can expire if there is no browser activity for long time (HttpSessionState.Timeout property determines in how many minutes session-state provider terminates the session), so it's better to check for value existence before return:
public static Account GetCurrentAccount(HttpSessionState session)
{
if (Session[ACCOUNT]!=null)
return (Account)Session[ACCOUNT];
else
throw new Exception("Can't get current account. Session expired.");
}
http://www.tigraine.at/2008/07/17/session-handling-in-aspnet/
hope this helps.
Short term information, that only needs to live until the next request, can also be stored in the ViewState. This means that objects are serialized and stored in the page sent to the browser, which is then posted back to the server on a click event or similar. Then the ViewState is decoded and turned into objects again, ready to be retrieved.
Sessions are not evil, they serve an important function in ASP.NET application, serving data that must be shared between multiple pages during a user's "session". There are some suggestions, I would say to use SQL Session management when ever possible, and make certain that the objects you are using in your session collection are "serializable". The best practices would be to use the session object when you absolutely need to share state information across pages, and don't use it when you don't need to. The information is not going to be available client side, A session key is kept either in a cookie, or through the query string, or using other methods depending on how it is configured, and then the session objects are available in the database table (unless you use InProc, in which case your sessions will have the chance of being blown away during a reload of the site, or will be rendered almost useless in most clustered environments).
I think the "evil" comes from over-using the session. If you just stick anything and everything in it (like using global variables for everything) you will end up having poor performance and just a mess.
Anything you put in the session object stays there for the duration of the session unless it is cleaned up. Poor management of memory stored using inproc and stateserver will force you to scale out earlier than necessary. Store only an ID for the session/user in the session and load what is needed into the cache object on demand using a helper class. That way you can fine tune it's lifetime according to how often that data us used. The next version of asp.net may have a distributed cache(rumor).
Session as evil: Not in ASP.NET, properly configured. Yes, it's ideal to be as stateless as possible, but the reality is that you can't get there from here. You can, however, make Session behave in ways that lessen its impact -- Notably StateServer or database sessions.