Persisting complex data between postbacks in ASP.NET MVC - asp.net-mvc

I'm developing an ASP.NET MVC 2 application that connects to some services to do data retrieval and update. The services require that I provide the original entity along with the updated entity when updating data. This is so it can do change tracking and optimistic concurrency. The services cannot be changed.
My problem is that I need to somehow store the original entity between postbacks. In WebForms, I would have used ViewState, but from what I have read, that is out for MVC. The original values do not have to be tamper proof as the services treat them as untrusted. The entities would be (max) 1k and it is an intranet app.
The options I have come up are:
Session - Ruled out - Store the entity in the Session, but I don't like this idea as there are no plans to share session between
URL - Ruled out - Data is too big
HiddenField - Store the serialized entity in a hidden field, perhaps with encryption/encoding
HiddenVersion - The entities have a (SQL) version field on them, which I could put into a hidden field. Then on a save I get "original" entity from the services and compare the versions, doing my own optimistic concurrency.
Cookies - Like 3 or 4, but using a cookie instead of a hidden field
I'm leaning towards option 4, although 3 would be simpler. Are these valid options or am I going down the wrong track? Is there a better way of doing this?

If you do Store it in a session then you need to ensure that if you implement a web farm that the session is loaded correctly.
We have (exactly) the same question here at the moment and what we've decided to do is to implement the Repository Pattern and link it to a cookie.
Then, if this becomes an issue, we can simply slot in either a session manager, db manager or whatever and our code need not even know because of the repository pattern.
We tinkered with the idea of hidden fields but it felt too much like ViewState and we all hated it in WebForms so the idea was scrapped. But not just because we hated view state. There were issues when you pressed Ctrl F5. The contents would be cleared and then what do you do?
So at this point its a repository pattern with a cookie which may change but the implementation lends itself kindly to change.
EDIT
We also decided against hidden fields because it would be too easy to make changes to them and so you need to do some token stuff from the server to ensure it wans't tampered with.
The hidden fields just kept on adding complexity to what essentially should have been a very simple problem.
At least that was our thoughts on the matter.

I am not quite sure why Session is a bad idea, if the client dose not need that backup copy, keeping the whole thing in server memory sounds the best; since the rest of the candidates are all sending from server to place (temporary) in clients' browser, and then get it back whenever client does any action. Situation is, whenever client ping back, server will unpack the encoded data (either in hidden field, cookie, url etc) and would possibly place in server again! It also waste bandwidth IMO.
OK, if client need (to inspect) the backup, I would consider hidden field(set) or simply serialize the data in XML and put it somewhere in the HTML.
EDIT
I still vote for Session. If you plan to take care the server farm, consider implement a cross server session provider:
http://msdn.microsoft.com/en-us/library/ms178587%28VS.80%29.aspx
and simply store the state in database.

Related

ASP MVC vs. WebForms: using SessionState for user logon

i've a question regarding handling of user logon while porting an application to MVC:
in the "old" WebForm days, developers simply used the SessionState object to set a user to logged-on, by -for example- simply putting the userobject into the SessionState (and this userobject holds simple properties like name/lastlogon/etc.)
this stuff worked very well for us, and i've seen lots of applications doing it that way
yes, i know there is this MembershipProvide-thingy, but i've never used it
Now, in MVC, everybody tells me that "using SessionStat for this is bad" and "apps built that way are flawed in design" and that "there are tons of security risks" and so on.
I've used this method because it worked for the app very reliable, it was simple to implement and it covered all stuff we need.
(Sure, there is the thing with recycling web worker process and emptying the session - but thats not a problem in our case, since the app runs for each country on a dedicated machine)
I've read tutorials, telling me to put that stuff in the DB and -attention- doing a request to the DB to check if the user is logged in, per EACH request? But: Under no circumstances, this is a doable way since i want to keep DB requests on a minimum.
So my question is:
A) whats wrong using this way also in the new MVC app?
B) whats the best way to handle this scenario in a newly built MVC app?
Regarding the session-in-DB-idea: instead of doing this, i'd rater setup an additional service, like a "session-manager" thats get query over the network, but such simple requests should not go to the DB - isn't that a good idea?
Any idea, hint /etc. is highly appreciated since this scenario is really confusing me :-X
A)
A fundamental principal of the asp.net mvc framework is that its stateless. Data is passed around using http requests and sent to the views in viewmodels. Web forms tried to maintain state with viewstate etc thats why you would have seen the logged in user in session approach. Thats not to say session shouldnt be used completely in asp.net mvc, there are some circumstances when it can be useful. Like maintaining a 3 step form process that has to be persisted on the last step. But generally we already have a recommended way to handle the user logins, and thats forms authentication
B)
For accessing the user object, you can create a custom identity implementing the IPrincipal interface and add the required user fields you need. Then set the custom identity in a global filter and access it in your action results. Regarding not wanting to query the database for every request, why dont you just call it for the initial request, then cache the result until the user is updated where you then can reload the object and set it in the custom identity again.

Session State between Pages in MVC

besides TempData, which I believe isn't the best thing to use nowdays, what are some best practices in how you can persist user data from page to page?
Do you usually just go back to the DB every time...ajax or not...do you make a request every time or do you store it in lets say the Request object or some other in process object instance?
I'm just looking for a broad range of ideas as I am overwhelmed with looking this up on the net...there's a LOT out there and it would be easier for me to get some insight via stack as well.
There are several options. If we're talking about intrarequest, then of course ViewBag is the best choice. Intrapage (across requests) then the best choice is probably hidden fields, unless it's sensitive data.
Between pages, then there are several options. You can of course pass data as query string parameters. Session also makes a convenient option, so long as the data size is small, and it's ok if the session gets lost (ie, you can get it again or regenerate it). In certain other situations, you can post data to another page using hidden fields, but this should largely be discouraged since you should prefer to use PRG (Post/Redirect/Get) pattern.
Some other options are using the context cache HttpContext.Cache (Which i feel is misnamed, but oh well) or saving it in temporary tables in the database. Any "in-memory" option will have scalability issues if you decide to move to a web farm (Session can be made to be backed by database, but it slows things down).
It also depends on what data you're talking about. If it's user data, then another option is to store it in a cookie, or to use the user data portion of the Forms Authentication cookie, and create a custom IIdentity object.
Finally, there's just rebuilding the data from its source on every request.

ASP.NET MVC - what's the equivalent of ViewState

I have an existing web-forms website that runs on a web-farm (multiple web servers, each request is NON-sticky).
One of the tasks is to retrieve a lot of data from a 3rd party webservice. This is an expensive process (in terms of time taken to respond). The optimal solution has been to initially grab all the data and stick it in the page's ViewState (as a List<Product>. We then have a grid that allows us to page through this list of products. For each request for the next page we don't have to re-visit the slow web service because we've already cached the data in the ViewState.
So, how would I accomplish this using MVC? If I were using classic ASP, I would serialize the list and hold it in a hidden field in the form.
But what is the preferred approach when using MVC? As mentioned, I'm using non-sticky sessions so can't rely upon caching on the server.
If I am to hold it in a hidden-field, then is it sensible to compress the data first (zip) to reduce the size of the page? Again, what's "best practice" here?
Many thanks for any/all advice
Griff
PS - I know there are similar posts out there (e.g. ASP.NET MVC and ViewState), but they don't quite provide the detail I require.
Caching, in my humble opinion, is the best way to deal with this; hit the webservice, cache the data, and use that for each subsequent request.
It is possible to share a cache across many web servers. The default behaviour is to hold it InProcess, but this is by no means fixed and can be configured to store it in a remote InProc cache, a database, or any other method of semi-persistant storage. AzureAppFabric caching comes to mind.
Second to that, as you mentioned is to dump all the data in a hidden field, but I dont like this idea for a number of reasons
Page bloat - you're submitting this data every time the page is changed
Lost data - you must submit a form for every navigation, forgetting to do this means loosing your data
To name 2.
Your strategy should depend on how volatile the data retrieved from the 3rd party service is going to be and how expensive it is to call it.
Volatile and expensive. I would go down the road of caching the data in a distributed cache such as Appfabric Velocity, or Memcached.
Non-Volatile and expensive. Cache a copy of it in memory on each server node.
Cheap. Hit the call every time you need it. Don't bother caching.
If the data set returned from the service is large, I would not pass this up and down every time you page through your grid data. Only retrieve the data for the current page and render it in your grid. Telerik have a good implementation for this or you could try and roll your own.

Asp Net MVC 3 - Moving through Actions and Views, SessionState

How can I keep some values between different Views in MVC 3?
I tried using TempData and HiddenField to keep these values but in our hosting this tecnique seems to have short life so exceptions are coming out furthermore if user uses Back button every starts to fail.
I would like to understand the better way to keep values between views in MVC 3, thanks in advice!
By design, MVC3 TempData values are removed after they are used.
The most simple answer is to use the Session object directly in your controllers.
There are other related questions with detailed answers such as these:
Session variables in ASP.NET MVC
Asp.Net MVC and Session
Your question is about the lifecycle of objects in between requests. It's important to understand that webapplications are used over the HTTP(S) protocol which is a stateless protocol. This means that every request is a completely new request for the webserver and there's no state shared between requests.
However it would be foolish to send the credentials of a user to the server each and every time so a webserver can create a thing they call a Session (and session-state). This object is an object that remains available for the lifetime of the session of the current user (most of the times from logging in until logging out). You can use this object to store items that you wish to share over various requests of the same user.
If the values you're trying to keep are specific to the page you can probably use a hidden field or something like that. However if the data is more related to the user than to a specific page and it must have a lifecycle longer than a single request then sessionstate is the best place to store the data.
You could use the Session (as you mention in your title and tags). Or store a cookie on the user's machine

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