How can I persist objects between requests with ASP.NET MVC? - asp.net-mvc

I'm just starting to learn ASP.NET MVC and I'd like to know how I can retain model objects between subsequent requests to controller action methods?
For example say I'm creating a contact list web app. Users can create, update, rename, and delete contacts in their list. However, I also want users to be able to upload a contact list exported from other programs. Yet I don't want to just automatically add all the contacts in the uploaded file I want to give the user a secondary form where they can pick which uploaded contacts should be actualy added to their list.
So first I have a ContactController.Upload() method which shows an upload form. This submits to ContactController.Upload(HttpPostedFileBase file) which reads the file that was posted into a set of Contact model objects. Then I want to display a list of all the names of the contacts in the list and allow the user to select those that should be added to their contact list. This might be a long list that needs to be split up into multiple pages, and I might also want to allow the user to edit the details of the contacts before they are actually added to their contact list.
Where should I save the model objects between when a user uploads a file and when they finally submit the specific contacts they want? I'd rather not immediately load all the uploaded contacts into the back end database, as the user may end up only selecting a handful to actually add. Then the rest would need to be deleted. Also I would have to account for the case when a user uploads a file, but never actually completes the upload.
From what I understand an instance of a controller only lasts for one request. So should I create a static property on my Contact controller that contains all the latest uploaded contact model object collections? And then have some process that periodically checks the age of these collections and clears out any that are older then some specified expiration time?

A static property on the controller is trouble. First off, it won't work in a web farm and second it you'd have to deal with multiple requests from different users. If you really don't want to use your database you could use the ASP.NET Session.

No, you don't want a static property, as that would be static to all instances of the controller, even for other users.
Instead, you should create a table used to upload the data to. This table would be used as an intermediary between when the user uploads the data, and completes the process. Upon completion, you copy the contacts you want to keep into your permanent table, then delete the temporary data. You can then run a process every so often that purges incomplete data that is older than a specified time limit.

You could also use the HttpContext.Cache, which supports expiration (and sliding expiration) out-of-the box.
Alternatively, and perhaps even better (but more work) you could use cookies and have the user modify the data using javascript in her browser before finally posting it to you.
However, I'd strongly recommend to store the uploaded information in the database instead.
As you pointed out, it might be a lot of data and the user might want to edit it before clicking 'confirm'. What happens if the user's machine (or browser) crashes or she has to leave urgently?
Depending on the way you store the data the data in this scenario will probably be lost. Even if you used the user id as a cache key, a server restart, cache expiration or cache overflow would cause data loss.
The best solution is probably a combination of database and cookie storage where the DB keeps the information in a temporary collection. Every n minutes, or upon pagination, the modified data is sent to the server and updated in the DB.

The problem with storing the data in session or memory is what happens if the user uploads 50k contacts or more. You then have a very large data set in memory to deal with which depending on your platform may effect application performance.
If this is never going to be an issue and the size of the imported contacts list is manageable you can use either the session or cache to store the dataset for further modifications. Just remember to clear it when the user has committed the changes, you don't want a few heavy datasets hanging around in session.
If you store the dataset in session using your application controller then it will be available to all controllers while it is needed.

Related

Rails: working on temporary instance between requests and then commit changes to database

I have already read Rails - How do I temporarily store a rails model instance? and similar questions but I cannot find a successful answer.
Imagine I have the model Customer, which may contain a huge amount of information attached (simple attributes, data in other tables through has_many relation, etc...). I want the application's user to access all data in a single page with a single Save button on it. As the user makes changes in the data (i.e. he changes simple attributes, adds or deletes has_many items,...) I want the application to update the model, but without committing changes to the database. Only when the user clicks on Save, the model must be committed.
For achieving this I need the model to be kept by Rails between HTTP requests. Furthermore, two different users may be changing the model's data at the same time, so these temporary instances should be bound to the Rails session.
Is there any way to achieve this? Is it actually a good idea? And, if not, how can one design a web application in which changes in a model cannot be retained in the browser but in the server until the user wants to commit them?
EDIT
Based on user smallbutton.com's proposal, I wonder if serializing the model instance to a temporary file (whose path would be stored in the session hash), and then reloading it each time a new request arrives, would do the trick. Would it work in all cases? Is there any piece of information that would be lost during serialization/deserialization?
As HTTP requests are stateless you need some kind of storeage between requests. The session is the easiest way to store data between requests. As for you the session will not be enough because you need it to be accessed by multiple users.
I see two ways to achive your goal:
1) Get some fast external data storage like a key-value server (redis, or anything you prefer http://nosql-database.org/) where you put your objects via serializing/deserializing (eg. JSON).
This may be fast depending on your design choices and data model but this is the harder approach.
2) Just store your Objects in the DB as you would regularly do and get them versioned: (https://github.com/airblade/paper_trail). Then you can just store a timestamp when people hit the save-button and you can always go back to this state. This would be the easier approach i guess but may be a bit slower depending on the size of your data model changes ( but I think it'll do )
EDIT: If you need real-time collaboration between users you should probably have a look at something like Firebase
EDIT2: Anwer to your second question, whether you can put the data into a file:
Sure you can do that. But you would need some kind of locking to prevent data loss if more than one person is editing. You will need that aswell if you go for 1) but tools like redis already include locks to achive your goal (eg. redis-semaphore). Depending on your data you may need to build some logic for merging different changes of different users.
3) Another aproach that came to my mind would be doing all editing with Javascript and save it in one db-transaction. This would go well with synchronization tools like firebase (or your own synchronization via Rails streaming API)

Hold a data object temporarily in MVC controller,MVC,MVC Controller temp storage

I have a object that i want to store for a moment. The object is in a controller for now, the controller will generate a view. A AJAX request is made from the view to next controller. For that moment i need the object previously stored. Previously, i used session and it worked well. But not sure it is the right thing to do. Is session the answer for this or is there anything else?
I have used cache also.but as per the cache concept.It will access for all the users.So one user data will be override to another.So the cached object data will be change for the same user.I need to handle the data storage for an particular user(Independent).
How is it possible? anyother approach is there please share me.
In Controller I have used Httpcontext.cache["key"]=dataset;
but some one suggested like this.but its not displaying
Explain:
In Controller: httpcontext.current.cache is not coming.
HttpContext.Currenthandler and HttpContext.Currentnotification properties only coming.So How can we handle the temp data storage in MVC.
Please help me.
You could use TempData if you want to store data for the next request only. If data should be accessible between multiple requests, then use Session. Here is short explanation of each one with examples.
As Alex said you could use TempData but if you want to use the data in multiple request, you could use TempData.Keep("YourKey") after reading the value to retain the data for the next request too. For your Information TempData internally uses Session to store your data (temporarily)
I would recommend URL parameters for a HTTP Get, or hidden form fields for a HTTP Post, if this is short lived. This is highly about avoiding the session.
But if it should really persist, then a database might be a reasonable location. Imagine a shopping cart that you don't want to dump just because a session timed out; because you'd like to remind the user next time about items they still haven't purchased.
Why not use the session? I don't generally recommend using the session, as you could find yourself with a global variable that two different browser windows are manipulating. Imagine a glass. One window is trying to fill it with Ice Tea. Another window is trying to fill it with Lemonade. But what do you have? Is it Lemonade? Is it Ice Tea? Or is it an Arnold-Palmer? If you try to put too much stuff on the session, and overly expect it to just be there, you might create an application that is non-deterministic if heaven forbid a user opens a second window or tab, and switches back and forth between the windows.
I'm more ok with Temp Data, if you truly have no other options. But this is not for persisting data for more than a second. Temp data will disappear after the first request reads it, as in, it's meant for a very temporary usage.
I personally only use TempData if I have to do a redirect where I can't otherwise keep it with me, or if I need to have that data for say generating a PDF or image that is going to be called via a HTTP Get by a viewer on the actual page, and then only if the model data is too large for the GET url ( many browsers only support just over 2000 characters, which long description or many fields could fill up.)
But again, pushing items around in hidden form variables, or in url parameters can be safe, because you have no multiple window use conflicts (each carries around its own data for peace of mind.)

"State" management for asp.net mvc multi partial view + ajax app

I am trying to convert my asp.net mvc4 app, which had fairly heavy use of SessionState, into a stateless app. I understand that I can store this information in the DB, and intend to do so.
My question, though, is about my particular architecture. My app has a main 'page' consisting of a number of partial view panels, which each have actions in them that can affect the other panels. What i've been doing up to now is storing the entire state of the viewModel (lots of inter-related EF list collections and 'record' objects) in the session, and its been working great. Except when the session just randomly dies.
So, I need to get this data out of the session, and into the DB where I can rebuild the thing at need. My concern is that, if I store the info in the database, every single action done on screen might affect 3-5 different panels, each with their own State updates, thats a minimum of 10 round trips to the DB for every interaction!
What are some strategies I can use to make this idea more scalable?
EXTRA INFO
The view in question here is a sort of POS shopping cart system. There are panels for selecting events, selecting/adding items to the cart, editing cart items, selecting contacts, editing contacts, displaying the cart items, displaying the cart 'subtotals', and finally, a panel with a [checkout] button.
Selecting a new event will change the list of available items. Selecting an item to add to the cart will change the cart item list, subtotals, as well as the checkout panel. Same for editing a cart item.
The main concern is how to recover from a lost session, as I've found the built-in asp.net session code too unreliable. My testers have encountered issues with sessions timing out, and then my app not having any kind of recovery process. When its installed on 1500 sites, each with an average of 10 users, its going to be a plague of lost session issues, and I need to combat that before it becomes a real problem.
I agree that I'm not going stateless...wrong choice of words used in a rush. I'm just trying to move that state into a form that I can rely on past the session failure. My main idea presently is to continue using the session as the local cache for the viewModel data, but to have a fallback operation that can rebuild the viewModel from DB if the session one is lost somehow.
You shouldn't necessarily be using a database to store (what sounds like) data that only needs to be persisted in the short term.
If these changes to the other partials are only relevant in the context of the current "master view," then I would suggest using jQuery AJAX to send off the requests, parse the response JSON and update the other views. Tutorials on jQuery AJAX and ASP.NET MVC are easy to find, if you don't already have the knowledge:
http://www.codeproject.com/Articles/41828/JQuery-AJAX-with-ASP-NET-MVC
This way, you don't need to make a bunch of round trips. If the changes need to be persisted beyond the context of the current view, make ONE round trip to the database to perform the update and then simply update all of the other partials from the in-memory response from the AJAX call.
You don't need to read from secondary storage multiple times when you already have all of the information you need in-memory. Just do the reading and writing once.
I decided to go with a hybrid approach. I'm still using session, but I'm building out a DB 'recovery' option, so that if the session portion is lost, the DB will be able to provide the values needed to rebuild the session seamlessly.
Seems to be working well, so far.

How would I organize the flow of this Rails code?

I'm using Shippinglogic to gather tracking information for submitted tracking numbers.
I'm handling a number of things behind the scenes of the UI, but I'm not sure how to properly organize this.
So here's the flow:
User submits tracking number either via form input or URL (example.com/track/1234567890). If the number doesn't already exist in the database, then the next step happens...
After a number is submitted, I run the number through some logic to determine who the carrier is (UPS, FedEx, USPS, DHL, etc). The user never specifies...it's all done automatically.
After the carrier is determined, then I need to make the actual call to the carrier API (via Shippinglogic) to get tracking information.
After I get the tracking details, I need to save it to the database.
Then, the tracking details are finally returned to the user.
Since users can submit either via form or via a URL (without any sort of POST action), I'm trying to run it all through my show method in the controller where I check if the number exists and if not, submit it via Number.create(:tracking_number => '1234567890') but once I get into the model, I just kinda get lost on what to do next.
Well I would have the users directed to the new or create actions where you can handle creation and detect if the record already exists. Once that's handled you most likely want to send them off to the show page where you can display the tracking information from your data source and any information you have saved in your database. This way you are preserving the nature of the application and other developers would be able to work with the application if they need to.
Edit:
I had a project like this and I move my detection code out into a separate function inside the model so I could make changes to it and abstract it from a specific call on the model. I performed my API requests in the background on the model so I could cache data in the database and refresh the records that were deemed active once an hour.
Basically if it needed to use the data from the record or save some data as part of the record I made a function in the model. This enabled me to split a bunch of functions out from specific modifications to controller actions and the like.

How do I see real-time activity of my users in Rails 3?

What I would like to do is have my admin user be able to see - in real time (via some AJAX/jQuery niceness) - what my user's are doing.
How do I go about doing that ?
I assume it has something to do with session activity - and I have started saving the session to the db, rather than the cookie.
But generally speaking, how do I take that info and parse it in real time ?
I looked at my session table and aside from the ids (id and session_id), I see a 'data' field. That data field stores a hash - which I can't make any sense of (looks like an md5 hash).
How would I use that to see that User A just clicked on Link B, and right after that User B clicked on link A, etc. ?
Is there a gem - aside from rackamole - that might be able to help me?
You might want to check out Mixpanel. They are easy to setup and have some of what you are asking for.
The session data only contains the values stored in the session[]-hash from the user. It doesn't store which action/controller was called, so you don't know which "link was clicked".
Get the activity of your users:
Besides rackamole you have two options IMHO.
Use a before_filter in your ApplicationController to store the relevant info you are interested in. (Name of controller, action or URI, additional parameters and id of the logged in user for example).
Use an AJAX-call at the bottom of each page which posts back the info you are interested in (URI, id of logged in user, etc.) to your server. This allows faster response times from the server, as the info is stored after the page has already been delivered. Plus, you don't have to use a Rails-request to store it. The AJAX-request could also be calling a simple PHP-script writing the data to disk. This is much faster.
Storing this activity:
Store this data/info either in the database or in a logfile. The database will give your more flexibility like showing all actions from one user, or all visitors for one page, etc. The logfile solution will give you better performance.
Realtime vs. Oldschool:
As for pulling out your collected data in realtime, you have to build your own solution. To do this elegantly (without querying your server once a second to look if new data has arrived) you'll need another server process. Search for AJAX Push for more info.
Depending on your application I'd ask myself if realtime notifications for this are really necessary (because of all the hassles of setting this up).
To monitor the activity on your site, it should be enough to have a page listing the latest actions and manually refresh it (or refresh it automatically every ten seconds).
Maybe you can test https://github.com/raid5/acts_as_scribe#readme
It works with Rails 3 too.

Resources