I have a asp.net project with c# code behind. I have a static class called GlobalVariable where I store some information, like the currently selected product for example.
However, I saw that when there are two users using the website, if one changes the selected product, if changes it for everybody. The static variables seem to be commun to everybody.
I would want to create (from the c# code) some kind of session variable used only from the c# code, but not only from the page, but from any class.
Yes static variables are shared by the whole application, they are in no way private to the user/session.
To access the Session object from a non-page class, you should use HttpContext.Current.Session.
GlobalVariable is a misleading name. Whatever it's called, it shouldn't be static if it's per session. You can do something like this instead:
// store the selected product
this.Session["CurrentProductId"] = productId;
You shouldn't try to make the Session collection globally accessible either. Rather, pass only the data you need and get / set using Session where appropriate.
Here's an overview on working with session storage in ASP .NET on MSDN.
You sort of answered your own question. An answer is in session variables. In your GlobalVariable class, you can place properties which are backed by session variables.
Example:
public string SelectedProductName
{
get { return (string)Session["SelectedProductName"]; }
set { Session["SelectedProductName"] = value; }
}
Related
How can I declare global variables in MVC application without using static ?
I am currently following the static approach and it is causing issues when the application is logged in from different users at the same time.
If you want to make them global per user, I would suggest to use the Session context to save the variables to. This is not really on a user level, since a user can log in multiple times, but usually this suits better in my experience.
I usually have something like this:
public string Prop
{
get
{
return (string)Session["Prop"];
}
set
{
Session["Prop"] = value;
}
}
This will make accessing the property very easy and consistent.
Similar to session you can also use application object. Also you can store variables in cache.
I have an ASP.NET application that is accessed by 120-140 users at the same time on average. I use Session to get and set user specific info. To make things easy I've got a static a class called CurrentSession and it has a property called UserInfo:
public static class CurrentSession{
public static UserInfo{
get{return HttpContext.Current.Session["userInfo"]!=null?(UserInfo)HttpContext.Current.Session["userInfo"]:null;}
set{HttpContext.Current.Session["userInfo"]=value;}
}
//And other properties
}
And whenever I needed current user's info I just used to do:
CurrentSession.UserInfo;
Recently I've come across situations when wrong user info is retrieved. Is there a problem in my approach that can cause Session conflicts?
No. It can't be that the session change can be caused by the static method. In fact, HttpContext.Current itself is a static. Assigning it to a static variable can cause this.
i have a small class with just a couple properties in it.
here is an example:
public class clsRepLogs
public string those;
public string these;
public void setThoseandThese
{
//call a stored procedure
//get results
this.those = something;
this.these = somethingElse;
}}
from my first.aspx.cs
i call the set function:
clsRepLogs cLog - new clsRepLogs()
cLog.setThoseandThese()
so now the properties have been assigned values.
i now want to use them in another aspx.cs file to populate a form... but can't figure out how to get to them...
i tried
clsRepLogs cLog;
lblThese.text = cLog.these;
but it's giving me an error: "Use of unassigned local variable 'cLog'
basically, how do i tell it to use the values i've already assigned to that class instance from before?
i hope i'm explaining this right, but i might be way of on what i'm doing. any help appreciated.
It sounds like you want to access the same instance of the class from multiple ASPX pages. There are multiple ways to do this; a per-user solution is to use session state.
// page 1
var c = new clsRepLogs();
c.setThoseAndThese();
Session["mykey"] = c;
// page 2
var c = (clsRepLogs)Session["mykey"];
"mykey" can be any string. You may also want to check if Session contains the value before accessing it, e.g. if( Session["mykey"] != null ){ ... }
Keep in mind:
Session isn't durable; restarting the web worker process will reset all in-process sessions.
It's usually not a good idea to store many large objects in Session.
If the data is confidential, be aware of Session fixation attacks.
Session can be load balanced across servers, so this solution will scale.
For reference (alternative approaches):
You could use the Cache object when you don't care about per-user isolation and want control over data expiration.
You could use the Application object; similar to Cache but no control over expiration.
You could store the object in the database and load it on each page. This is useful when you to don't want a heavy session, and/or wish to save the data more permanently (such as a shopping cart which persists across multiple sessions).
You need to initialize or set cLog to the instance of clsReport that you want.
You aren't instantiating your class. It should be
clsRepLogs cLog = new clsRepLogs();
Or, if I misunderstood your code,
clsReport cLog = new clsReport();
EDIT:
If you need to preserve these, it should be a static class so that it cannot be instantiated.
public static class clsReport
{
public static string those;
public static string these;
public static void setThoseandThese
{
//call a stored procedure
//get results
this.those = something;
this.these = somethingElse;
}
}
A lot of this depends on how you need this to function. In addition, I'm no expert on perpetuating objects/classes in memory in Webforms applications. If you wanted to re-access the class to get those values, I'm not sure they would still be in memory.
You will need to initialize your cLog class :
clsRepLogs cLog = new clsReport();
lblThese.text = cLog.these;
This is probably going to sound rather naive, but I'm developing a web application that spans multiple pages. All of these pages instantiate the same class object w/ methods that accesses a CMS using their API. Currently, when a user starts creating content, I'm storing variables like a folder ID where the content is located in a Session variable.
My question is this: Can I instantiate a single instance of a class that can be used across all pages without having to do it on every page? If so, would each person accessing that page be given their own version of the class? I assume that using static variables and methods isn't the way to go since they are shared in memory. And also, where/how is something declared if it is going to be used globally in a Web Application in a .net C# application?
I recommend making a base class which inherits from System.Page. Then have your page code behind inherit from that.
Then, inside the base class, create a property that is a reference to your object. Like this, for example:
public class BasePage : System.Web.UI.Page
{
public Foo CurrentFoo
{
get
{
return (Foo)Session["FooSessionObject"];
}
set
{
if(Session["FooSessionObject"] == null)
{
// instantiate a new one
Session["FooSessionObject"] = new Foo();
}
Session["FooSessionObject"] = value;
}
}
}
Then, from anywhere in any page, just do a CurrentFoo. and you will have access to any of the properties.
This makes for nice and clean code behind.
You should use Session state if you want to store information that is specific only to the current user.
For example in one page of the application you could store some value into the session:
SomeType someValue = ...
Session["someKey"] = someValue;
and then later on other page retrieve it from the session:
SomeType someValue = (SomeType)Session["someKey"];
The pattern you are looking for is quite easy. There are a couple of ways to accomplish it.
Create an object and store it in session
Create a multi-part form and leave the items in viewstate
Each has its benefits.
Bad thing about doing this and using global over sessions for website is the simple fact that global variables could be accessed by any user accessing the regardless of session. For example take the code below.
public class globals
{
static string _test = "MyTest";
public static string test
{
get
{
return _test;
}
set
{
_test = value;
}
}
After I created the global class I added a label to my default from and assigned the global variable text to the label.
protected void Page_Load(object sender, EventArgs e)
{
globals.test = "Some Data";
}
now you will see this on every form of you page however the down side to this is anyone else that accesses your page will also be able to see this data. If its data that needs to be shared across multiple sessions you could do this. If its data that just needs to be shared by the current user over multiple classes you need to use session variables.
I have a problem with static variable. Part of the organization of my controllers is as follows:
namespace MyApp.Controllers
{
public class DevicesController : Controller
{
static int some_var = 0;
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult SetValue(int temp){
some_var = temp;
return RedirectToAction("DisplayValue");
}
[Authorize]
public ActionResult DisplayValue(){
....
return View(some_object);
}
}
}
The problem arises when multiple users simultaneously using this view. The same static variable is used by all users and change its value. How solve this?
Your entire ASP.NET MVC application runs within an AppDomain, that is the application plus all requests being served for all users, everything!!
When you create a static variable, a single instance is declared and made available to the entire AppDomain, every request from every user will see the same value.
An instance variable (simply remove the 'static' word) is specific to an instance of the particular object it's in. In this case the object is an instance of your Controller, so your variable as an instance variable will be individual/specific to that controller object only. The ASP.NET runtime will create an instance of your Controller for each request it serves, then discard that controller object once its processed the request. So if you remove the static word, the variable will only stay around for the duration of that request, then disappear.
What you need, as other posters have said, is Session state. Session State lasts the duration of a session, as in someone browsing your site, and is specific to each user. So if you store that variable in Session State, it will be different for each user.
Problem is Session state disappears when the user leaves your website, so if you need it to the stay around longer, you then should use something like a database.
From your comments and original post, it sounds (and I'll try to put this as politely as possible) that you haven't quite grasped some Object-Oriented Programming idioms and concepts. While Session state isn't a OOP concept per se, the difference between static and instance variables is. I would recommend brushing up on these, as an understanding in these concepts (fundamental to OO programming) would mean, IMHO, you wouldn't even be asking this very question. I hope this answer has helped in your understanding somewhat.
You can use,
HttpContext.Current.Session["some_var"]
instead of some_var, this will help. This will preserve for the user that is logged, one session, and you can access it statically with HttpContext.Current
namespace MyApp.Controllers
{
public class DevicesController : Controller
{
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult SetValue(int temp){
HttpContext.Current.Session["some_var"] = temp;
return RedirectToAction("DisplayValue");
}
[Authorize]
public ActionResult DisplayValue(){
....
return View((int)HttpContext.Current.Session["some_var"]);
}
}
}
Make it a private instance variable, not static.
If you need to maintain this count per user (but only for the given session), then you can do the following:
if (Session["Count"] == null)
Session["Count"] = 0;
Session["Count"] = (int)Session["Count"] + MyNewValue;
If you want the count to persist across session, then you can persist it to a database.
Static variables (and properties) will be shared amongst all instances of that type -- in this case, your controller. The value will be lost when the application pool is restarted.
If you need the value to persist across requests, for a specific user, then you may need to look to move it to the session, or similar.
If you only need the value to remain for the duration of the current request, then a private variable would suffice.
There is an important difference between class variables and object variables. Static variables are class variables, this means all objects that are instantiated from a class share the same variable, so a change of that static variable in an object changes other objects of the same class too.
But a nonstatic variable (object variable) is created for each instantiated object, so change doesnt effect others.
But the problem is not to choose between this two because your need is different. You need a variable that will be kept for each user. So as others stated, you must use a session variable.
But i think you should read about object variables and class variables.
Statics are neither good nor bad. They simply have a different usage structure.
Consider that you are processing international telephone numbers.
You will need a country_code, country and a unique id at a minimum in order to do this. You may also need to IDD country escape prefix.
So you create an object to hold all of this and then gather them into a list from say a database or some other method.
You want a drop down to list the country that the user picks and then you want the country_code to go with whatever it is that you are gathering.
If you create the list of country objects as static then when you make the round trips to and from the server you don't have to re-load the list from it's backing store everytime, you just use it to populate the drop down list. Since this data never changes it's ok to make it static. Everyone on the site will be using the same list of countries so, having one copy does not matter. However, you will have to make the Id used to index the list non static so that when you restore the selection on the list everyone has their selection and not a global static one that shows what the last person selected.
Set your models non static county_code_id to used the id selected in the list and then when you are ready to update the data use the models country_code_id to lookup the country_code in the list of country objects to return the country_code for your update.
Like I said, statics are neither good or bad, they just have a different usage.