I'm currently implementing a wizard for making an order, it consists out of a few steps, but this differs per product.
I have to save state between steps, so the user can jump back and forth and make adjustments.
To do this, and after some browsing, it seems there are two ways to do this:
Have a main ViewModel with child-models for each Step, then Html.Serialize the models in your page
Just store the whole object in Session
I am wondering why I would choose either method. The first one has been introduced in MVC2 in 2009, and that's also about as old as all posts regarding Html.Serialize date back, so I'm wondering if its still an accepted way. Especially given it has a lot away from ViewState, which was far from secure in ASP.NET.
Session seems the most logical choice after that, but I wonder what the downsides are. Will my session be lost if the app-pool decides to recycle? Session is server-side right?
Thanks!
Little side-note: Not interested in doing it with Javascript at this point, I'd like to keep this serverside. Hence I didn't list it as a third option.
A Session has a limited lifetime and won't work properly if the user has multiple tabs opened on your wizard.
Keeping data in hidden fields is cleaner as it is truely stateless unless it's too big or you have to keep it server side for security reason.
I advice you to try with hidden fields and switch to session only if there is an issue.
Related
How to handle multiple sessions for same website using same browser with different tabs. ASP.net C#.
example like google if we open 2 account in same browser it will not effect user details.
All the tabs in a browser share the same session(i.e. identifies to the web server as the same user), this is the default behavior. There are use cases where you would like each tab to connect to the same webserver as different user, this need to be handled via your web application by adding some specific info to the query string in your URL, or hidden form fields, etc., ASP.NET provides cookieless sessions, that can be used for this scenario, see this documentation.
There are other blogs with examples out there that you can follow. One such is this one - shows using a GUID in url route to differentiate different user, and solution to use unique window name and post it back to server using hidden form fields.
Well, as noted, session() is global to the user. In fact, they can launch two different browsers, say FireFox, and Edge - and they will BOTH continue to use the same session values!
What this REALLY means is that from day one, your designs HAVE to make this assumption. If you don't make this simple assumption, then you can be in for a world of BIG hurt if you "just out of the blue" wrote code without the above concept in mind.
In other words, for global things, then session() is fine. However, if you start writing BOATLOADS of code based on using session() to persist values on a SINGLE page? DON'T!!!
And it takes a few seconds in 99% of cases to flip code from session[] to ViewState[] for a given page.
So, now then the ONLY issue is when we use session[] to pass values around from page to page.
Using session() for passing values is ok, but NOT for such information like PK row values such as booking a hotel room, or say selecting a house to buy.
However, like a lot of people, the problem is we don't really think about this issue, or don't know about this issue until it is too late.
So, this is a problem. You want the "easy" of session(), but we need a way to pass around values from page to page.
As noted, one way is to pass values around using parameters in the URL. But then again, that's rather ugly. Sure, for some things like to filter a grid by a given city, then that can be really nice, since then users can save such a URL, or often modify the URL to their liking.
However, for a simple pick of a house or say a hotel room to book, then you can't of course allow or risk doing that (since you would be exposing primary row keys and selection in plain view. Worse yet, it can be a huge security risk. (some very early credit card and other types of sites would actually let you type in values that would let you get and see OTHER USERS information!!!
So, here is how you can handle this issue:
First up, we have these simple choices:
Parameters in URL - they are ugly, high risk, but GREAT for things like city filters etc.
Session() - this is global to the user - includes separate browsers launched.
ViewState - this is per web page - ideal for what we need, and PER PAGE!!!
HiddenFields (in markup) - again, per page - ideal for what we need, but PER PAGE!!!
So, in regards the per page options, only URL parameters can work for passing.
(sans the session() option).
ViewState is great for per page, but you can't use ViewState for passing values between pages. Keep in mind that viewstate is client side, and while encrypted?
Well, for not super high security, then it ok to use. Just remember, ViewState should be kept small, since it goes with EACH button click and PostBack, ViewState becomes part of that "package" and post.
ViewState is part of the page post-back. This is certainly ok, and even better then hidden fields which appear in plain view client side. Just keep in mind ViewState increases the size of each and every post back for a page. So, keep it light, small, and don't persist LARGE amounts of data like say some large dataset.
(unlike Session() which is 100% server side).
So, we need:
Easy approach - per page, but NOT have to re-write a lot of code.
So, while you could say munge up the URL, then they start to look really ugly, and while that might get you a session for the given page, your session() code has to be changed - and it gets messy.
so, just limit using session() to pass values, but NOT persist per page - and you then quite much home free.
In effect? I am saying NEVER use Session to persist values in a page unless you have no other reasonable choice. (use ViewState).
The other issue? What good is to suggest some approach in which you have to re-write a boatload of existing code?
I find that even a page with quite a bit of Session() stuff can in less then a minute be changed over to use ViewState. In fact, you can in most cases use search + replace Session to Viewstate.
So, the only issue left is now the passing of values from page to page.
Use session freely to pass values to the next page. However, for any values that are say PK values, or row identification values, or values that will "break" or "damage" the operations of that page if MORE then one page were to be open? Then simple transfer the values in session to next page AND THEN ALWAYS on FIRST PAGE load (IsPostBack = false), you simple transfer the values to ViewState.
This works really nice, and is BOATLOADS of less work then trying to adopt some silly parameter in the URL or what ever other junk people propose. In other words, we want the LEAST DAMAGE to existing code.
And also, because session() is global? Then it starts to get REALLY messy. I want to say pass 4 values to the next page. And then on that page I might have some more values - all of sudden, while writing code, you can't even remember what session() name to use - and it piles up into a BIG MESS REALLY fast. You wind up with a boatload of session values - ever more growing in your application. It just a mess, and global values tend to be a HUGE mess in any applcation - including that of using session().
And, often, 4-5 values are for the SPECIFIC page - so do NOT create 4-5 session() values, but add a typedef or simple class to the project. And use that for passing of the values. It MUCH LESS clutter in session(), and as you about to see, it also MUCH nicer for transferring these values to Viewstate.
So, we now have this:
we adopt and use View Sate for each page.
we ONLY use session to pass values to next page.
Lets give a simple example.
We say have a grid of hotels - you pick one. As noted, for buying things, picking hotel etc, then passing that value with session is OK AS LONG as you adopt the above rule (that we transfer values to Viewstate in the target page).
The goal here is to allow multiple working tabs or copies of the browser running, and of course minimal code changes.
So, say we have a GridView, and a Hotel to book.
So, note the values we pass (hotel ID, room type, nightly rate).
As noted, we then navigate to the next page (probably additional room details, etc.) - confirm booking etc.
But, as we noted, we can't use session() anymore, since they might have two browsers open. Heck they might have the page open on both their desktop and their smartphone.
So, when we land on the 2nd page, if two pages land using session, we in huge trouble? No, not with our above approach.
So we can still use session() to pass values, BUT we do NOT persist values on that target page. In other words, we break down the two issues:
a) - we using session() to pass values to the next page
b) - we now are NOT using session() to persist values on CURRENT page <<--- this we fix!!!
So, by making our goal here CRYSTAL CLEAR then you as a developer can deal with the above with a SIMPLE change to your existing code. As I stated, you the developer have to code, build, and design your web pages with the above concepts in mind.
So, for persisting values on a given page, just start using ViewState in place of session() - such code will work un-changed in most cases, and all and any values you save ONLY BELONG to the current page.
Only major difference is a user refresh of the page can re-set the ViewState for that page (but session() would and did persist - so some caution is required here - but not much).
So do this:
Pass values by session(), but on FIRST PAGE load (IsPostBack = False), transfer the value(s) to view state, and you are done!!
So, while session() can and is and will be shared between even two browsers running? Well, you click on some row, get PK into session(). Now, say you jump to the next page, on page load (IsPostBack = false), you transfer session value(s) to ViewState, and now you have full operational page - not dependent on Session().
The above is the best solution I have found, and you don't in most cases have to change your code, or introduced some mucked up URL which I find is even more of mess.
C# - ASP MVC - .NET 4.5 - Bootstrap - Razor
I have a form wizard (http://vadimg.com/twitter-bootstrap-wizard-example/examples/basic.html) that is used to setup a complex object (obj1). A property of obj1 is a List<obj2>. On one step of the wizard I want to add multiple obj2's to the list. Since obj2 is slightly complex as well, I thought I would use another wizard to help build it. Except I need to persist this List<obj2> on wizard 1, while I'm off in wizard 2 building another obj2.
My first thought was to use a session to hold the List<obj2>, I was just wondering if that's a good option, or if there would be a better one? The user may leave from Wizard1 to go to Wizard2 and come back multiple times.
There's no perfect answer here; each approach has trade-offs. But here are some options that I can think of (and these are independent of ASP.NET/C#)
Session (as you suggest)
This will store data in web server memory (by default). If you have a lot of users, this could be a problem.
You risk the information being lost when the user gets a new cookie/the session times out.
Potentially better performance that a db, depending again on the number of users
Database (as you mentioned)
Could cause more database traffic.
Can save information for user even if they close a browser, switch computer, the power goes out, etc.
Maybe a separate NoSQL database just for transient wizard data would be worth trying.
Cookie (store data on the user's computer)
Users can potentially tamper with/view the data
There is a limit on cookie size (4 KB each?)
Local storage (HTML5)
Similar to cookies
But not such a small limit
Not every browser supports it (may need polyfill)
Form/Post/Hidden/ViewState
You could just post the data and drag the information from response to response
But this gets really annoying with back buttons & timeouts
Lots of work, and again, the user can tamper with the information
I'm trying to work a number of security issues on a rather large ASP.NET web application (C#). To prevent session fixation attacks I'd like to generate a new session id every time a user authenticates himself. However I want to only generate a new session id without losing the rest of the session. After doing some research on this topic I found a couple of working solutions:
Solution 1: Generating new SessionId in ASP.NET
This suggests clearing the session cookie manually by setting it to an empty string. However this requires either a page refresh or using AJAX to ensure that the cookie will indeed be removed, which isn't really a viable option in my specific case.
Solution 2: Generating a new ASP.NET session in the current HTTPContext
I have implemented this approach and it works as expected. However as the original poster states, this is not really what you might call an elegant solution. Also, this post is a few years old which has me hoping that there might be a better solution out there nowadays.
What I would like to know is if there are any alternatives to do this that I have missed in my research or if something like Solution 2 is possible without manipulating session management internals.
It's not that easy to achieve what you want due to how session management works by design in ASP.NET, re solution number 2. The solution (2) seems a bit risky considering ASP.NET session state implementation details change at some point.
I'd recommend a variant of solution 1, where you store the relevant data from the session to db/cache when the user authenticates, get a new session for the user and then populate that with the data you need. Since data is moving from an "unathenticated" session to an "authenticated" session you should also take care to validate that data.
Clearing the session cookie manually can be a slippery slope, re Ramping up ASP.NET session security. You'll find a more robust solution in the NWebsec.SessionSecurity's authenticated session identifiers (Disclaimer: I'm the developer on that project).
Web.Config changes
sessionState cookieName="ABC"
In Login.aspx page in block !ispostback write
Response.Cookies.Add(new HttpCookie("ABC", ""));
Enjoy
-Saving time is good!
To be clear, the two pages are only logically related in other words the values in my FirstPage.Aspx pass values to my SecondPage.Aspx so it control components and certain attributes of the controls in my SecondPage.Aspx, the SecondPage.Aspx is not a redirect or transfer from FirstPage.Asp. sorry am so sick of reading about all the answers but the one I actually need!
Consider the firstPage contains a textBox which get a value from the user or the web admin to set his preferences about the gridView page size on the SecondPage or a Text property of a label on the SecondPage
I want to explore my options to do so
PS: I was told to use a database to store values from the first page then on the page with my Label for example I connect to the database and retrieve the value and set it to the label...is this a best practice to let the page connect every time it loads to set some values sometimes it's just an int like 5, and most of the time I'd be connecting already to the database to display some table's data in a gridView or any databound control!
EDIT:
Sorry if I was a bit rude, it just hit me that I'm mainly getting the same answer that I read which is totally not my case!..and of course thanks to some of you mentioned the database solution, I hoped I could get an example or an article for my particular case since I think even it's simple but yet it's essential...
ASP.NET framework provides several mechanisms to maintain context that lasts across several HTTP requests. The data you want accessible across calls, can be stored in this context. All you have to do is decide how long do you want this context to be maintained (because it consumes resources), and if you want this context to be available across more than one server.
Application State : Which is maintained for the lifetime of the application i.e. from when the application is first loaded by ASP.NET, till it is unloaded for whatever reason.
Session State : ASP.NET is able to identify a series of HTTP requests emanating from a specific client (IP address), close to each other in time, as a session. It can create a session context that persists across such a session, in which you can store data that is accessible to the calls in the session. The session state can be made available across server boundaries by associating it with a DB or shared memory.
Database
Viewstate : You can use Viewstate to maintain context, but keep in mind that Viewstate is transferred over the wire for every request / response. It has been known to get quite large, specially if you use controls.
Cookies : Again, transferred on the wire for each request / response.
You can use:
Session variable
Cookie
Database value
each one of them have their own pros and cons
If you want the value to be stored the next time they come to page 2, use a database value. if not, use a session variable.
The database value will give you a persistent value, and you can then store other such user variables there.
the session will give persistent data, but only for the browsers current session. The data will be lost if their session times out.
From all you've stated, i would assume a database value.
U can use cookies, session etc but if you want to pass something that defines the whole content of the page, like an ID of some sort, you might just want to put it in the QueryString. (ex: default.aspx?id=4)
Cons: everyone can read (or change) the value, not usable for critical data
Pros: everyone can read the value, and the link can be sent to others
I'd suggest you start here: Get Started with ASP.NET
If I understand your question, you are looking to do Cross Page Posting. If one page isn't posting to a 2nd, you'll need to persist the data somehow (database, session, xml file, etc). But, from reading your question, you sound like you just want to cross page post...
Your question is very confusing, took me a lot of time before I could I understand what you actually need. Since there is no events in HTML, you will need to use JavaScript and some kind of web-service (AJAX).
Page A will store the value in database, and JavaScript on page B will constantly check database for new values, get them and output to the user. In order to that it needs to connect to some webservice/webmethod that will return the value from database to your page. A good example can be found here.
Alternatively you can refresh page every 5 seconds using
<meta HTTP-EQUIV="Refresh" content="5">
and check for the new database value on Page_Load server event.
I think the better answer is "Control State"
Reference : http://www.asp.net/general/videos/how-do-i-use-control-state-to-persist-information-for-a-custom-web-server-control
but I couldn't get this implemented on my case, two different pages
for example : the web user control is placed on News.aspx and the textbox which will have the value to be assigned to the control on News.aspx is placed in myAdmin.aspx page!
and to be honest, I didn't quite understand the code
So! do you think this is the best solution ? if yes do you think It can be used for my case (two different pages) ??
Let's say you're building something simple, like a data entry/CRUD form for working on an entity called Customer. Maybe you pass the CustomerID in via Session state.
I tend to write a lot of fairly boilerplate plumbing code around handling that Session variable in a particular way. The goals vary slightly but tend to be things like:
Avoid cluttering the main flow of the page with plumbing code
Handle the back button intelligently
Remove the variable from Session and persist it to ViewState ASAP
Code defensively for failure situations where the state doesn't get passed, or is lost
Do you have a best practice for handling this situation? Do you have classes in your stack that handle this perfectly every time? Do you just call the Session variables directly? Do you use encrypted QueryString and avoid Session variables in this situation entirely in order to make the back button work a little better?
Lately I've been using Properties with Session variables. Here's a simple example that I just threw together, although please keep in mind that this example would not be very tolerant of the back button:
Private ReadOnly Property CustomerID() As Integer
Get
If Me.ViewState(Constants.CustomerID) Is Nothing Then
If Me.Session(Constants.CustomerID) Is Nothing Then
Throw New ApplicationException("CustomerID was not persisted.")
Else
Me.ViewState(Constants.CustomerID) = Me.Session(Constants.CustomerID)
Me.Session.Remove(Constants.CustomerID)
End If
End If
Return Me.ViewState(Constants.CustomerID)
End Get
End Property
So, how does your shop handle this? Thanks!
Teams I have worked on do not pass this kind of workflow information around in session, primarily because of the difficulty it poses to web farms/gardens. We think of session as a container for information that is relevant most (if not all) of the time from the moment the user first hits the site to the moment they leave. Even then, I'd only use session if that information was very expensive to retrieve/build, and only if I knew that the load balancer would stick the user to a particular server in a farm or that we had a suitable out-of-process session provider in place.
Instead I would pass this type of information via the query string, hidden input field, or ViewState (if enabled), and provide friendly error-handling when invalid values are sent. If history management is important, I would leverage ASP.NET AJAX history management.