Persisting a Variable across Requests - c#

I realize this may be a simple problem, but I am new to ASP.net (C#) and am having an issue with a method in which I pass a 'Ride' object that was obtained from an sql database through a LINQ-to-entities statement. I attempt to set another global variable to the value of the Ride.identity attribute (which is a long), but in the next method, when I attempt to use this value, the new value has not persisted. Any thoughts? If there is some post-back that I am missing that reinitializes this variable, is there a way to save it? Thanks.
private void displayRide(Ride ride, int carNum)
{
if (ride != null)
{
ride.AssignedCar = carNum;
ride.Status = "EnRoute";
id_ridePendingConfirm = ride.identity; //<----THE PROBLEM IS HERE!
myEntities.SaveChanges();
RideToAssignDV.DataSource = new List<Ride> {ride};
RideToAssignDV.DataBind();
}
else
{
//TODO: Redirect to error.aspx
RideToAssignDV.DataSource = null;
RideToAssignDV.DataBind();
}
}

Store the value in ViewState. For example:
ViewState["RideId"] = ride.identity;
When you go and use it in the line in your code, you would need to do this:
id_ridePendingConfirm = (long)ViewState["RideId"];
But be careful. Since ViewState[key] returns an object, you will need to make sure it isn't a null reference, or else you'll receive an InvalidCastException.
I normally tell my my peers with less experience to create a protected property that will store this value and persist it in ViewState, as follows:
protected const string RideIdViewStateKey = "CurrentRideId";
protected long CurrentRideId
{
get
{
object o = ViewState[RideIdViewStateKey];
return (null == o)? -1 : (long)o;
}
set
{
ViewState[RideIdViewStateKey] = value;
}
}
Then in your code, do this:
// Assignment before postback so that you can preserve the state:
CurrentRideId = ride.identity;
// After postback in the method you have above:
id_ridePendingConfirm = CurrentRideId;
Now, since I don't know what your code should do when no Ride identity is available, I decided for -1, but it depends on what your code actually needs.
I do not recommend Session state for your scenario because this apparently needs to persist between page postbacks, not for the entire duration of the user's session. Also be careful with how much information you store in ViewState because it can easily be abused.
For more information on ViewState and Session State see:
Undestanding View State (2004)
ViewState Property (.NET 4.0)
ASP.NET State Management Recommendations
ASP.NET Session State Overview

Variables and fields do not persist across postbacks.
You need to use session state.

See this question and my answer for multiple methods of storing data between executions of a page. In brief, you need to store the value somewhere between postbacks. ASP.NET (and .NET in general) provide a variety of tools for doing so, but nothing is done automatically between requests. The page is created, executed, and destroyed with every request.

Related

How do you keep the value of global variables (namely a struct variable) between postbacks?

I'm new to this and have already searched for this with not much luck :(
Lets say I have defined a struct array globally and filled the array with data on an Ajax ModalPopupExtender. I then have a ddl_SelectedIndexChanged event that does a postback and seems to recycle my array.
Is there a way to fire the ddl_SelectedIndexChanged event to perform some code without doing a postback? Or is there an easy way to make the array of type struct retain it's values?
(I am creating a website btw)
Thanks in advance...
To store in session...
Session["ArrayName"] = ArrayVariable;
..to get it back into the Array type
var array = (ArrayType)Session["ArrayName"];
With viewState
ViewState.Add("ArrayName", ArrayVariable);
var array= (ArrayType)ViewState["ArrayName"];
What is the difference between SessionState and ViewState?
If this is to be used only for the page you are on, then you should use ViewState. If you need it to be available across the site, then your options are Session, Cache or DB. Also, make sure you first check that the objects are available, as in..
if (Session["ArrayName"] != null)
var array = (ArrayType)Session["ArrayName"];
..or you will be victim to the Object Not Set Reference error.
See this article for using Cache in ASP.NET.
You could store your array in ViewState, like below:
ViewState["arrayName"] = array;
where array is the name of your array. Then you could easily retrieve it using ViewState["arrayName"]. If you array is an array of strings, you could easily retrieve it like:
string[] arr = ViewState["arrayName"] as string[];
For further documenation on ViewState please have a look here.
If it is page level then go for viewstate
ViewState["arrayName"] = array;
and if it is to different page then it is through session.
Session["ArrayName"] = ArrayVariable;
As said already use ViewState. Create a property in the page's class and read/write to that property. Obviously change the List to what ever type your array is.
public List<string> SomeArray
{
get
{
if (ViewState["SomeArray"] != null)
{
return (List<string>)ViewState["SomeArray"];
}
return null;
}
set { ViewState["SomeArray"] = value; }
}
Really though when you bind values to a dropdown the dropdown should hold the data in viewstate itself unless your logic clears on page load. Posting your Page_Load event may identify your real issue.
UPDATE
Although having read your question again I could be wrong, post code!

.Net updating Session object side effects

I'm having some strange (to me at least) functionality with Session objects in my .Net Webforms project. I'm passing objects around in Sessions and I'm not using any global variables. I have a method described below:
private int Foo()
{
RmRule ruleInEdit = (RmRule)Session["ruleInEdit"];
//here ruleInEdit.subjectAreaID=0
bool isValid = Validate();
if (isValid)
{
//do some stuff
//here ruleInEdit.subjectAreaID is 10 instead of 0
//the Validate function modified the ruleInEdit object
}
//other code
}
private bool Validate()
{
bool isValid;
//check some stuff
RmRule rule = (RmRule)Session["ruleInEdit"];
rule.subjectAreaID = 10;
Session["ruleInEdit"] = rule;
return isValid;
}
I thought that the value of subjectAreaID should still be 0 but clearly I'm misunderstanding something. How (or Why) does .Net update the ruleInEdit object automatically when I write the object back to the Session.
In the original method Foo, shouldn't I have to force ruleInEdit to read the session again to get the updated object and properties?
Is this object tied to the session scope because of the way that I initialized it?
You don't have to write the object back to the session collection, it never leaves.
There is only one instance of the object, it's not copied when you read it from the session collection. Any change you make to the object is instantly visible to all code that looks at the same instance (i.e. the same session).
What's stored in the session collection is just a reference to the object. The object itself is stored on the heap.
When you are using InProc (by default) session storage, then there is no serialization occured. You are operation by your custom class, which is reference type. So when your method Validate retrieves an object from session, in reality it's just a pointer where you are changing original object.
In another words object of type RmRule is the same in Foo and Validate methods.
Behavior expected by you will be after switching application settings to store session in SQL server for example.

c# TempData equivalent in php

I know I can explicitly set and unset a Session manually but I believe this is worth to ask. In c#, there is a dictionary called TempData which stores data until the first request. In other words, when TempData is called, it is automatically unset. For a better understanding here is an example:
Controller1.cs:
TempData["data"] = "This is a stored data";
Model1.cs:
string dst1 = TempData["data"]; // This is a stored data
string dst2 = TempData["data"]; // This string will be empty, if an exception is not raised (I can't remember well if an exception is raised)
So basically, this is just something like a session for 1 use only. Again, I know that I can set and unset explicitly in php, but still, does php has a function like this one?
As the others have pointed out, uses sessions to enable TempData. Here is a simple PHP implementation:
class TempData {
public static function get($offset) {
$value = $_SESSION[$offset];
unset($_SESSION[$offset]);
return $value;
}
public static function set($offset, $value) {
$_SESSION[$offset] = $value;
}
}
Test:
TempData::set("hello", "world");
var_dump($_SESSION); // array(1) { ["hello"]=> string(5) "world" }
TempData::get("hello"); // => world
var_dump($_SESSION); // array(0) { }
Unfortunately, we can not implement ArrayAccess with a static class.
You don't have that in PHP, but it shouldn't be too hard to implement it yourself. The actual implementation depends on your exact needs.
Do you need that data across users or separated for each user?
Do you want it to have a default expiration time?
Do you want it just in the active request or should it persist until someone retrieves it?
Are "misses" acceptable (see memcached) or do you want to be sure you find the data when you request it?
As #AVD tells, there is no such command. And I can't really see why. The thing with TempData is that it allows you to save some values / objects for a roundtrip to the server.
If you do use Sessions in your website there is no issue to not use Session to store these values. Session storage is placed on the server and the users is identified by a sessionid which is sent to the server each time.
The only performance penalty I can see is if you were to run your session storage outside your process running the http handler. Otherwise they are both in memory and should be pretty fast.

Is a variable stored in Session deserialized once or multiple times throughout a page lifecycle?

I would like to wrap Session variables in a manner similar to that discussed on CodeProject.
public static class WebSession
{
private const string CurrentUserKey = "CurrentUser";
private static HttpSessionState Session
{
get { return HttpContext.Current.Session; }
}
public static bool Exists
{
get { return Session != null; }
}
public static User CurrentUser
{
get { return Session[CurrentUserKey] as User; }
set { Session[CurrentUserKey] = value; }
}
}
Here is my question: if I have to access CurrentUser multiple times in the same page, would I get a performance improvement by assigning it to a local variable instead of accessing the wrapping property? Or does the HttpSessionState make sure the object is only deserialized once per request, so that subsequent calls in the same http request don't cost any more?
Thanks,
Aaron
There is an in-memory copy of your Session state on each request. Therefore the only cost that you would be saving by locally copying a session variable is that of the cast from Object to your type. The in-memory copy is then added to Session at the end of the request.
Whether or not Session is serialized and deserialized on a page depends on what Session Provider you choose. For In-proc Session State, no serialization occurs. For Session Servers the object must be serialized first.
There is an in-memory copy. You get negligible performance improvement from caching the value; it would save only a Dictionary lookup, which will be too fast to notice unless you're doing it a zillion times per page load.
Also important to note is that for a given key, each retrieval returns a reference to the same instance, and Session keeps a reference too. That means, if you retrieve an object from Session and modify it, you need not call the setter again to re-serialize it.
I just asked a question about this same thing:
Are .Net property setters ever called implicitly?
I did some work pulling apart session recently, and from what I could see, the entire state object is deserialized once and once only per request. Of course, it is easy enough to check - just fetch it out twice and check ReferenceEquals.
Of course, placing the value in a field between uses would save some "lookup" time, but you should only pay the deserialization cost once.
If you really wanted to be sure, you could also double-check this by implementing ISerializable and logging serialize / deserialize calls.
some good articles to read
http://msdn.microsoft.com/en-us/library/aa479041.aspx
http://msdn.microsoft.com/en-us/magazine/cc163730.aspx#S5

Beginner how do you maintain state in an ASP C# Web Page

Update: the clearest explanation I have found on the web as I have been struggling through this can be found here.
Maybe I just don't understand the model of runat server terribly well. It appears the following code is always executing the if block. If the code is running on the server side I guess I can understand that it has to be stateless.
I am a seasoned non-web programmer but it appears counter intuitive to me. Will I need to create some sort of session object or pass the current state along in the URL or what?
<script runat="server">
DateTime begin;
DateTime end;
int iSelectedStart = 0;
int iSelectedEnd = 0;
int iPutName = 0;
protected void Button1_Click(object sender, EventArgs e)
{
if (iPutName == 0)
{
iPutName = 1;
Label1.Text = TextBox1.Text + " you will be slecting your start and end dates.";
It looks like part of your code got cut off, but here's the basic thing with web programming -- it's stateless. Unless, that is, you do something (use ViewState, Session, etc.) to add some state into the mix.
In your case, it looks like you want to maintain some state through refreshes of the page. Put the values you want to preserve in ViewState to keep them across postbacks to the same page. If you want to hold values across pages on your site, use Session. If you want to maintain values across visits to the site, put them in a database and tie them to a login or cookie.
The important thing to remember here is that the web is stateless. Each request from a person's browser is completely separate from all previous requests. What's happening with your code is that the class is being instantiated from scratch each time the client requests a page. That includes clicking Button1.
If you want values to persist between requests, you have to store it in a location where it can be retrieved later. The Session object provides this for you.
Basically, you'll need to store the iPutName variable in the session somehow. Probably the nicest way is to encapsulate it in a property:
protected int iPutName
{
get {
if (Session["iPutName"] == null)
Session["iPutName"] == 0;
return Session["iPutName"];
}
set { Session["iPutName"] = value; }
}
Edit: The ViewState object will work as well (as long as ViewState is turned on on the page). This encodes the value in a hidden field in the HTML and decodes it when it comes back.
Edit (again): Apologies for repeated edits, but I should clear this up. What Jonathan and Emil have said is correct. You should probably be using ViewState for this rather than Session unless you want this value to remain accessible between pages. Note that this does require that ViewState is turned on and it will result in a larger payload being sent to the client.
I really recommend to look at the quick start tutorial.
http://quickstarts.asp.net/QuickStartv20/aspnet/Default.aspx
There are a lot of concepts in dot net to simulate state on the UI.
In your case I think what you really want to do is using viewstate. Sessions should be used with care and I think the concept you are looking for i localized to the page not to the entier user session.
You should also look at the concept codebehind/codefront as well.
Because ASP.NET is stateless what you're assuming is correct. The postback will cause the page to lose the variable for iPutName. Storing in session is one option, or storing in viewstate could be another option.
The main thing to understand here is how the ASP.NET page lifecycle works and what happens each time you post back to the server.
For the lifecycle, check out the following URL :
http://www.eggheadcafe.com/articles/20051227.asp
You can store your iPutName in the session by doing this :
Session["iPutName"] = iPutName;
Fetching the session variable is also easy, but you should be sure to do a NULL check, like this:
if (Session["iPutName"] != null) iPutName = Session["iPutName"];
Haven't tested any of this, but if you encounter typos... sorry ;)
The Url you posted in your update is definitely not "All You Want to Know" about ViewState.... not even close. I only scanned his article but he doesn't appear to address Page Life Cycle at all. If your going the View State route then read these 2 links:
Understanding ASP.NET View State by Scott Mitchell
Truly Understanding ViewState By Dave Reed
If you're new to ViewState then dump all that guff (1 half the article) about parsing ViewState mentioned in your linked article. It's simply not required for anything but highly specialized scenarios. It is definitely not a normal thing to be doing re:ViewState.

Categories