I know the general consensus for information like shopping cart items is to store them in session. But what about objects that belong to a user that can be altered by other users? Say, for instance, an eBay-like site. If you store a user's "items" in session, which contain the current bid amount, and another user comes in and places a bid on that item, you would have to update both the item in the database as well as the item in session, wouldn't you?
In cases like these, are the only options to store in session and refresh whenever any action another user takes affects a person's session values or store everything in the database and retrieve it every time (could get expensive if, say, you have the bids displayed on the side panel of every page).
I would store it all in the database and retrieve it everytime. Depending on the volatility of the data caching for a few seconds may be in order. The biggest problem is keeping the two consistent.
I think that it isn't as expensive as you think to retrieve the data every time. Databases are very efficient if you are looking up based on a key. I'd err on the side of simplicity (store in DB and retrieve) until performance problems show up under load (ie in Load Testing).
If there is only going to be a handful of times, you may be able to use the Application Cache (unless you have more than one worker process/server) and make sure the DB and cache stay in sync.
I would personally store it in a database. Firstly, because your data is a lot safer there, and it makes it easier to share in the case where you need a web farm. Also, you don't need to have the data on every page. Just when the user goes to the shopping cart. The other plus of storing it in the database is that you can analyze later, the stuff that people are adding to the cart, but not actually purchasing.
Related
What would be considered best practice for implementing a persistent shopping cart in an ASP.net Web Forms(*) based application? The only built-in way seems to be involving the Session state, which is not ideal because once you close the browser... it's gone. One way seems to be involving the localStorage via Javascript, but that creates awkward client/server mixups, as the data processing is meant to be done server side.
(* please pay attention to that part - MVC or Blazor based solutions will not work for this particular case)
Well, I can't imagine any practical application that involves database operations having ANY kind of suggesting that some kind of session, or view state will have ANY kind of relevance to database operations?
Be it a person filling out an invoice, or making orders or anything?
Not at all different then if you were writing a desktop application.
If a user is building up a list of items or "things" for/in an order?
Then as they build up such an order, then a database "order" record and structure will be built up. No different than say even building an invoice system say for the desktop with ms-access.
The only "use" of say session in most cases allows you to pass information from one page to another. (In place of say using parameters in the URL).
So, person might have a shopping basket of items (in your database, right!!!!).
They browse/search for more things to add to that shopping cart.
So say while on some items page, they choose to buy/select. When they make that choice, then you might say shove the ProductID into session, and then jump back into the current basket of items page, check session for a new product, and then insert/add that new item to the basket (which was being saved in the database).
If they log off, then fine. When they log back on, then you can load the current basket of items for display, and then allow them to continue shopping.
the only thing you going to use session for (or viewstate) is to allow the person to jump around looking at items, and then upon selection, you get/grab that particular product ID into session, jump back to the basket page, and add this new item from session, and then display their list of selected items.
So, in your database you have their current active order/basket, and thus when the user logs on, you can jump to that most recent or only "active order" page, and pull that order from the database. And then display all the details etc.
No session or viewstate would be required nor used at that point in time.
Not really any different than building up a invoice in a accounting package, then closing the program, and then next day, you launch the accounting package, load up the invoice, and thus can continue working on that invoice until you are done.
So, they look at the order, and go, "hum", I want to browse some more. So, they go look at/buy/choose/select another product. When they do, then you can now jump back to the current orders/basket page, and check session for the value just passed, add to order/basket, and now display the items in the basket, and that one "product id" in session can be pulled out, and is no longer required.
so session is not some kind of "magic" database system but is really only a feature to allow you to persist some values for a very short time, and only a simple "id" or simple variable in code for a rather short time. So session is ideal for passing a few values for use in code behind variables from one page to another.
Thus things like an address, name, products selected? That goes in the database, and not session.
For the most part, such software really not much different then desktop software.
You save and build up the list of items attached to a given order, and that order going to exist in the database.
So no real development approach here suggests saving their name, billing address, their past orders, the current new basket/order they have? That all going to be saved in a database.
So, session() is only relevant in most cases to "pass" some values, or "hold" some values for code behind.
So, if they select some product from a grid, you would shove productID into session, jump to the basket, add the new item in code behind to that order, and then let the page pull the information from the database to display items in that order.
So "session" persisting of data? That really only for a few variables that your code might need for some data operations, but your data for that order is not persisted in session - it goes into the database.
Session has VERY little to do with using a database system to "manage" and "hold" and "have" the order saved in the database system.
Session is not some kind of database - only a "active" storage of some variables you might need during program operation.
Easy, store it in database for logged in user.
use local storage or cookies for guess.
Is there a way to clear a session cache key for all users?
For example, I am storing the users currently selected shop item under the following session key "currentItem". In the management area of the website, I decide to delete that particular shop item. I now want to invalidate all the "currentItem" cache entries across all sessions.
Is there a way to do this?
I realise the example I have given is a little contrived, but it gets the point across. I suspect one solution would be to use the normal Cache api to store all of the users current items. That way I could invalidate them when required.
thanks
You can't get all the current Sessions from all users
(Frankly speaking, you can, but I don't recommend this, and still you can read only InProc sessions this way).
So the only thing you can do is something like this:
Store in Session only ID of the user cart
Add item with corresponding ID to the Cache
Then adding the item to the Cache, set the dependency to the Item
Then just generate event to change whole carts in Cache.
Also you should think about re-creating items if for some reasons Cache is being emptied - you should provide the CacheItemRemovedCallback callback for this event.
You could move the shopping cart to the database. Unless you have a very rapid buying process, or an extremely redundant environment, Session or Cache will probably not be durable enough. Since they are not persisted, you also won't have a direct method to analyze buying decisions, attrition, etc.
Depending on how often your inventory changes, you might only need to validate that a cart item is available at checkout. As a user, it would be very confusing to me to see that an item had just "magically" disappeared from my cart or that the price had changed. It would be better to explicitly call this out, in my opinion.
Again, a database would be a superior solution as you could track the state of the item at the time it was added to the cart against the current definition of the product.
If you must use a Session or Cache-based solution, then #VMAtm's proposed solution is a valid option.
I have a question in the field of optimization and application design.
I am building a web application using asp.net and sql server.
In one of my screens I must perform an action that generates a random number of user ids. I present the viewer with some statistics about the selected users. If the viewer likes the statistics I want to save them.
So basically I need to save the temporary random data, and if user likes it keep it.
Should I store the generated ids in the database or should I store them in the session?
Well, since you are generating random ids, you are using some kind of pseudorandom generator. Have you considered the possibility of just storing the seed for that generator? I've recently had a similar issue. In fact, very similar. Have a look:
My Post about Random(int seed)
EDIT: In comments you suggest you want to do much of this on the SQL server. Have a look at the following post. In addition you may want to consider the special case of new user being added whilst your admin or whatever ponders if he "likes" to save this or not. In that case you'd need to additionally store the number of users when the request was made, and adjust your random selection function accordingly. In the even more special case of removed user, this approach, admittedly, is useless.
Seeding SQL
It depends on your case and requirements. If you store the data in the session, then that is fine, but you will lose the data once the session is abandoned, or ended. But if that is not important, meaning that you don't want to keep the data there forever, then storing in the session (temporary) is better. But you will need to look into performance issues, specially if multiple users do the same thing at once, that will decrease performance.
If you choose to store in a database, then that will also work but you will need to decide on having ViewState enabled or disabled, again for the sake of performance.
if i have to do so , i store data in temp table in sql which will be drop on every page load event and recreate, i show the data in a grid where from selected user id can be deleted and saved
I know there are a million questions out there on how to implement a shopping cart in your site. However, I think my problem may be somewhat different. I currently have a working shopping cart that I wrote back in the 1.1 days that uses ASP.NET session variables to keep track of everything. This has been in place for about 6 years and has served its purpose well. However, it has come time to upgrade the site and part of what I have been tasked with is creating a more, erm, user-friendly site. Part of this is removing updatepanels and implementing real AJAX solutions.
My problem comes in where I need to persist this shopping cart over several pages. Sure I could use cookies, but I would like to keep track of carts for statistical purposes (abandonment stats, items added but not bought, those kinds of stats) as well as user-friendliness, like persisting their cart so that if they come back it is remembered. This is easy enough if a user is logged in, but I don't want to force a user to create an account if they don't want.
Additionally, the way we were processing orders was a bit, ehh, slapped-together. All of the details (color selected, type selected, etc) are passed to paypal via their description string which for the most part is ok, but if a product has selections that are too long for the string (255 chars i believe), they are cut off and we have to call the customer to confirm what they bought. If I were to implement a more "solid" shopping cart, we wouldn't have to do that because all the customer's choices would be stored, in addition to the order automatically being entered into the order processing system (they're manually entered into an excel spreadsheet. i know, right).
I want to do this the right way, but I don't want to use any sort of overblown software that won't really work with our current business model. Do I use a cookie to "label" each visitor to match them with their cart (give them a cookie with a GUID) across pages, keep their whole cart client side, keep the cart server side and just pull it from the db on each page refresh? Any help would be greatly appreciated.
Thanks!
So this isn't really the answer to your question, but it is part of the answer. I'm trying to find the duplicate that this is of (it may not be) but you can keep a lot of the same code if you'll use IRequiresSessionState. I didn't find any exact duplicates, but I recognized the subject matter.
Handler with IRequiresSessionState does not extend session timeout
other answers:
ASP.NET: How to access Session from handler?
Authentication in ASP.NET HttpHandler
So what you want to really do is just look to implement PageMethods in your pages, and then you can reduce a LOT of the overhead of communicating with the pages. But if you want to migrate away from what you're doing now you want to start implementing handlers (and configure them to use JSON - there's a decorator for that) and you can use that with the likes of jQuery.ajax() as a direct URL and keep it within the same scope of your project. Note that it will by default send the cookies for you, so that's no big deal. The reason why I say that is that the cookie has the identifier from Forms to let the session be identified.
So if you're using the IRequireSessionState then you can still use all the session state information that you're used to using. There's nothing wrong with using Session in combination with AJAX. The two really don't have a lot to do with each other. One is used for server storage, the other is used for server communication.
Now, if you're trying for a completely clientside app and a RESTful server solution, then you're going to need to start passing complex JSON structures back and forth (not a big deal, just a matter of making sure you define your datatypes for yourself pretty well in your own documentation) and you can keep everything restricted to only what's passed.
I actually use all three types of these methods in my applications on the same server, depending on what I'm trying to do with each of my apps. I have found that each has their own strength and weakness. (Ok, I don't use the session part, because I handle my state in other ways, but I could use session state)
What could I clarify with here?
There are a few ways you can handle this. The main question is how long do you need to persist their shopping cart information (30minutes, 1 hour, 1 day, 1 week, ...etc.).
Short Storage Requirements Easiest Implementation (30min - 1hr)
You can use session with Page Methods by using HttpContext.Current.Session["key"] so you can keep your session storage the same as it currently works for you. You can call these Page Methods using jquery ajax pretty easily and would eliminate the need for update panels, a script manage, etc. So it gets you halfway there in my opinion. Your pages will load faster and be more responsive and you don't have to throw away any of the code involved with caching stuff in session. Main downside to this is that you are still using session so you really don't want to persist sessions for too long as that will bog down the server hosting a site if it is fairly active.
Long Storage Requirements Server Side implementation
Same stuff above applies except you are not using session and you can use stateless web services if you like. You would generate a GUID for each visitor and storing that GUID in a cookie. On each ajax call you would send this GUID along with the data to persist. This info would get stored in a database identified by the GUID. If the customer completes their order then the information can be moved from the cache database to the completed orders database. In this implementation you would want to write some service or scheduled job that would delete cached orders (not completed) after a certain amount of time to keep the cache database lean.
Nice thing about this solution is you can have a pretty long lived cache, write some reports that key off this cached data, and the load on your web server will be reduced. Additionally if your site becomes more popular it is easy to scale out because you don't have to worry about keeping sessions in sync across multiple web servers.
Long Storage Requirements Client Side Implementation
This approach still uses web services or page methods but there is no caching database involved. Essentially you jam all your information into a cookie or set of cookies and key off that. You might still be able to get some information if you read out the contents of the cookie(s) on each POST and store that somewhere to report off of.
If you don't need to track what customers added things but didn't order then the major benefit of this solution is that you can cut the amount of POST's you have to do down by a lot. You can write to the cookie(s) in javascript and just POST everything when they are completing their order. Just be careful not to put any sensitive information in the cookies unencrypted (contact info, billing info, ..etc.) as there are ways to mine data in cookies from other domains in some less secure browsers. For the sensitive stuff you would POST it to the server and have it returned the encrypted information for storage in the cookie(s).
Downside to this solution is that if the information you need to store is large you could run up against the max cookie size and/or max number of cookies per domain limitation. With a good strategy (ie. storing product id's not product description) you will probably be ok.
Let me know if any of the above is unclear or if you have additional questions.
EDIT: Didn't see the answer above that essentially lays out the Short Storage Requirements one I have. If that is the accepted solution give him the check mark (he beat me to it (= ). Leaving my answer as it lays out some additional options.
I need to store IDs (Contact IDs, Claim IDs, etc.) between multiple .aspx pages.
At the moment I am storing the ID in the Session and have set the Session timeout to 300 minutes. However, I am still getting errors because users are attempting to perform operations after the Session has expired.
I think users are leaving their web broswers open, locking their computers, going home for the evening, coming in the next morning and attempting to pick up where they left off.
I don't want to use the Querystring. Cookies are more for User IDs than Contact IDs and Claim IDs. Viewstate is only maintained per page. Persisting Session to a database seems unnecessarily complicated. I don't want to extend the Session timeout too much.
I'd ideally like them to be able to pick up where they left off in the morning.
What are the best practices for dealing with storing IDs between pages? How can I do this without them receiving a message saying their session has expired? Am I overlooking something obvious?!
I would put all this information into a database. This is classic use of a database, a means to store information needed for the application.
Cookies are bad because you have to assume they will be at the same PC from session to session. You have seem the problem with sessions.
If you do not want to use a database then you can use a file on the server. And read from that file.
You might actually find it much easier than complicated to create a sort of "landing pad" database where a user's item history is stored, or MRU list. I wouldn't tie it to their immediate session or cookie though. Let the session maintain the user state, let the database handle where they were when they went home or took that 7 hour lunch break.
As #David said this is a classic use of databases.
If you are in need of doing this without using databases, you can fall back on some of the "tricks" (read hacks) that are used in non-dynamic languages:
Create a hidden field which exists on every page, name the field appropriately for the data you are storing.
When you render the page create an XML fragment containing your ids and other data, encrypt it for display purposes (using base64 etc), place the value into the hidden field you created.
When the page is posted back, reverse #2 and recover your data, then apply the page changes.
Rinse and repeat. :)
Really this is not a very scalable solution, as the XML and base64 encoding will add 50% or more to your data size, and if there is significant data (100's of KB) this process can get out of control.
The last time I was asked to use this solution it was for moving a list of well defined data around with an application that did not always have access to the DB. It worked ok for the purposes, but was definitely not ideal.
You could go ahead and store the IDs in viewstate on the page, then on each page that requires that ID have a settable property for that page. Before redirecting to the page instantiate it and set the ID property.
You're correct, storing this type of data in session isn't really what it's meant for. Viewstate is a better mechanism for this.