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.
Related
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.
I have a webmethod inside a webservice that calls another webservice to get data and fills a generic list then it returns it, what i want to do is to save the list in memory, so the next time the webmethod is invoked it does not hit the other webservice but just returns the list, i have tried but when i invoke the web method for the second time the list count shows as 0, looks like garbage collection is cleaning all. any suggestions ?
Store it in the ASP.NET cache. Setting an absolute expiration of midnight should assure that you only get it once per day (unless it gets tossed from the cache due to space issues).
[Web Method]
public List<Foo> GetFoos()
{
var foos = Cache["FooList"] as List<Foo>;
if (foos == null)
{
... get foos from remote web service ...
var expiration = DateTime.Today.AddHours(7);
if (DateTime.Now >= expiration)
{
expiration = expiration.AddDays(1);
}
Cache.Insert( "FooList", foos, null, expiration, Cache.NoSlidingExpiration );
}
return foos;
}
Note: you could also use output caching as well, but you're limited to a sliding expiration. That is, it will be cached for a duration based on when the request occurs. It's not clear that's what you want. For example, what if the first request occurs at 11pm with a 24 hour duration, you wouldn't check again until 11pm the next day. If you have data changing on a daily basis, you're better off using the ASP.NET cache in conjunction with output caching on a shorter duration to ensure that you get the latest, daily data in a timely fashion.
Updated example based on comments.
It sounds to me like your list might either not be static, or it might constantly be new'd within a non-static constructor. There are three possible fixes for this:
Make sure that your generic list is a static property which only get initialised within a static constructor.
Seeing your time requirements I would also suggest potentially looking into MemoryCache or Cache.
Use the WebMethod attribute and set a CacheDuration (i.e: [WebMethod(CacheDuration=86400)])
I have not tried this on a webservice, but I think output cashing would work.
[WebMethod(CacheDuration=86400)]
public string FunctionName(string Name)
{
...code...
return(sb.ToString());
}
Read: How to perform output caching with Web services in Visual C# .NET
In my web project, I am using Static List. So say suppose I have 2 users (A, B) logged in to my website at the same time, then this List will store some information about A and as well as B. But say when I process B List's records, A's List's are getting processed instead of B's.
Can somebody point out the problem please?, also please suggest me some possible solution to avoid this problem.
I am using ASP.NET C# 3.5.
Thank you in advance :)
Edit:
Now I have changed the data type from Dictionary to List, but still the same problem...
A static variable is one that is the same for all instances of a particular class. So this means your website uses the exact same dictionary for User A, B, C, D, etc. Essentially whichever user last writes to the dictionary is the one whose content you will see, regardless of which user is looking.
As other's have suggested, you can use Session variables. These are stored in the server's memory, and are related to a specific browser 'session' (i.e. user).
Personally, I prefer to use the ViewState as this is stored in the response to the browser, and returned to you whenever the page makes a postback. This means less memory usage on the server, the viewstate is not volatile across sessions (or subject to application resets like session). However this also means that whatever you are storing is sent across the wire, so you would never want to store things like credit card numbers, SSN's, etc.
It also means that if you're storing a lot of very large objects, you're going to have a very large response and postback (possibly slowing the cycle), so you have to be more careful about how and what you store.
So that's a few different options for you, you should do the research and decide which is best for your requirements.
Storing values in session is like:
Session["mykey"] = value;
And reading values from session is like:
Object value = Session["mykey"];
The session will time out after a couple of minutes and the value would then be null.
To avoid this consider using:
Viewstate["mykey"] = value;
Viewstate is used exactly like session except that the value has to be serializable.
The viewstate is send to the client and back again so consider the amount of data that you want to store this way. The viewstate is stored in "__VIEWSTATE" and encoded in base64.
Don't use a static dictionary. Use Session variables to store information about a user's session.
For better information, you will have to provide us with a bit more information: what records? in what format? etc.
When a variable is declared static, that means there is exactly 1 instance of that variable per class (this also includes classes in web applications).
Thus, a static variable is not tied to a user. If you need to store data specific to a user, consider using a Session variable.
You could store the dictionary in the Session, that way each user would have their own and the code wouldn't have access to others.
Or if you sometimes want to be able to access other users' info, you could declare it as
static Dictionary<String, Dictionary<T, T>>
where the string key is the unique user id.
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
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.