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.
Related
I was always under the impression that to access a variable in multiple methods, you'd either have to declare it as a class member or pass it in as an argument.
However, I was looking over some sample code recently to learn .NET, and I came across something called a ViewState. I understand it's meant to track some Pages and Control Properties, but I don't understand how it's being used here.
The code looks somewhat like this:
private void RowValidating(object sender, EventArg e) {
ViewState[Backup] = ViewState["TestId"];
// more code that does not include ViewStates
}
private void UpdateBox() {
// some code that does not include ViewStates
int box_id = ViewState[Backup];
// ...
}
How is ViewState accessible everywhere? It is not declared anywhere in the class or in any of the other class files, and this [Backup] key is just sort of created without initializing it. As far as I can tell, ViewState[Backup] does not exist until RowValidating is called.
Would it be possible to set ViewState as a global variable? Or could I always just make my own key that is accessible anywhere? It seems to behave like a dictionary, but I thought the notation was dict.Add(item, value), not dict[item] = value when working with a new item. It must be initialized somewhere, perhaps in some imported library?
Both Session() and ViewState are and can be used to persist values in your code. You don't have to declare them, they are built in features of asp.net
Session() is per user and thus is often used to persist values or even pass values between pages. However in some cases ViewState is preferable.
So for example if you have a productID or maybe even a house you are about to buy? Well, if you have two tabs open or even two different browsers open then Session() applies to all instances of the browser(s) in question open. So if a user has two seperate browsers opened, then the "ID" value you persist in session() will apply to both (so, be carefull, which house ID are you about to buy when you have 3 browser pages open to 3 differnt houses open? So session() is global to the user.
So for say "persisting" a row of data to pass to the next web page/form, Session() can be great - but keep in mind it is shared among all pages opened and in operation by that user. So session() is still per user - but global to that user.
Session() can be server "in memory" (the default). However, if you are using a server farm, then each of those multiple servers can't share their memory, and as such you have to adopt what is called SQL server based session. So in place of holding these values in memory, the session() state is shuffled from a serialized "blob" stored in SQL server. So if you hosting your site say on a cloud based system like Azure (as opposed to regular hosting), then session() can't persist on these so called "large services" based systems (or you are using a server farm with load balancing in which you have multiple-servers hosting the site for scalability reasons). Since multiple copies of the hosted web site can exist at the same time, then a means to have a common session() is required (so they shove a blob thing into SQL server). So you can still use session(), but it actually stored in sql server. It is noted that in some cases session() based on SQL server can cost performance. As high as 10% - perhaps a bit more. I find that in most cases you not notice this performance hit. But it works seamless() and in fact adopting SQL server based session will mean that session() is not frequent lost due to site execution errors. I had all kinds of issues with a site losing session(). If the web hosting and management system puts the server to sleep, or even .net code errors occur, it can (and will!!) often cause a application pool re-start - and that blows out session() (but not with SQL server based ones - they are rock solid).
ViewState is often preferred since it is by EACH NEW web page. And this is stored 100% in the browser. So to persist that houseID or product you about to purchase, then this occurs by page, and not all web pages in use by the user (so in this case, VieweState would be a far better choice). ViewState is thus stored by the browser and is much the SAME mechanisum used when you enter bunch of values in text boxes, and then do a post back. The web page travels up to server - page is processed and sent back down. But you will notice that MOST controls on the page retain their value. To achieve this then ViewState is used. And this applies to hidden text boxes (or hidden fields - much the same as a hidden text box). So this encrypted blob lives in the browser client side. And this blob thing thus goes along for the post-backs and round trips to keep those controls values in-tact.
So you can use session(), or ViewState But, as noted, you don't want to stuff too much into that ViewState, since it becomes part of that round trip life cycle. But ViewState as noted is often preferred since it is per page operation. However, since each new browser page opened creates a new local per page ViewState? Then ViewState can't as a general rule be used to pass values between web pages like Session() can.
However, you CAN pass all values of all controls to the next page. You can do this by using the post-back URL of a button. When you do this, then on FIRST page load, you can use the page.previous property in the on-load event. This will give you use of ALL values from the previous page - and you don't need Session() to do this. You can also use page.Previous if you do a server.TransferRequest as opposed to a Response.Redirect().
Last but not least? You see a lot of sites have a whole bunch of parameters in the URL. So this is often used and has a long history of use. Of course users can mess and change with these values - but they are still often used and often make the URL's rather ugly. For this reason I do like asp.net sites, since then URL's don't expose a bunch of stuff in the URL as parameters and keeps such information out of site and mind. You see a lot of shopping site still using parameters and values in the URL - and they do this for reasons of scalability - (they don't have to store the persisting values server side - it saves resources).
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.
I'm working with ASP.NET and I want to load once a big object (specific by user) in my controller and then use it in my view.
I though about a static property but I find some problems with it.
See : Is it a bad idea to use a large static variable?
I'm not familiar with this language and I have no idea how to properly share the same object between the different methods for each user. Could you tell me how to do that ? Do you know if singleton could be a solution ?
A singleton won't help you here if this big object is going to be different for every user.
Without knowing all the details, I'd say perhaps your best option is to store it in the Session object,
HttpContext.Current.Session["bigObject"] = bigObject;
Depending on the size & traffic, this can have performance problems, so I'd suggest you read up on the pros and cons of using Session
If you want to get to use something for the next simultaneous request, then use TempData - which is a bucket where you can hold data that is only needed for the following request. That is, anything you put into TempData is discarded after the next request completes.
If you want to persist the information specific to user, then go for Session. With session, you will have timeout, so that after certain amount of time the data stored in session will be lost. You can configure this value to much more bigger value. Apart from that when you go for Webfarm of servers, then maintaining session will be a problem, probably you might need to go for managing session in SQL Server or in some other store.
Alternatively you can Use Runtime Cache object in ASP.Net MVC to keep all the common data. Cached data can be accessed fast and we have other benefits like expiring cache etc. You can share this Cache object across users, or you can maintain different cache objects for different users, that is purely dependent on your logic. In case of webfarms, yo u have distributed cache servers like redis, Azure Cache service etc., which you can use them.
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) ??
I'm new to NHibernate (my 1st big project with it).
I had been using a simple method of data access by creating the ISession object within a using block to do my grab my Object or list of Objects, and in that way the session was destroyed after exiting the code block.
This doesn't work in a situation where lazy-loading is required, however.
For example, if I have a Customer object that has a property which is a collection of Orders, then when the lazy-load is attempted, I get a Hibernate exception.
Anyone using a different method?
Session management:
http://code.google.com/p/dot-net-reference-app/source/browse/trunk/src/Infrastructure/Impl/HybridSessionBuilder.cs
Session per request:
http://code.google.com/p/dot-net-reference-app/source/browse/trunk/src/Infrastructure/Impl/NHibernateSessionModule.cs
check out the SummerOfNHibernate webcasts for a great tutorial... What you're looking for specifically doesn't come until webisode 5 or 6.
Keep your session open for your entire unit of work. If your session is life is too small, you cannot benefit from the session level cache (which is significant). Any time you can prevent a roundtrip to the database is going to save a lot of time. You also cannot take advantage of lazy loading, which is crucial to understand.
If your session lifetime is too big, you can run into other issues.
If this is a web app, you'll probably do fine with the session-per-httpRequest pattern. Basically this is an HttpModule that opens the session at the beginning of the request and flushes/closes at the end. Be sure to store the session in HttpContext.Items NOT A STATIC VARIABLE. <--- leads to all kinds of problems that you don't want to deal with.
You might also look at RhinoCommons for a unit of work implementation.
Since you are developing a Web App (presumably with ASP.NET), check out NHibernate Best Practices with ASP.NET at CodeProject.