I am having one doubt regarding the use of static variable in Asp.net pages.
I am having one page say UserDetails.aspx.
In this page, I have one static variable to store some data specific to a user. So, will this variable be shared across multiple user or a separate variable will be created for each user?
public partial class UserDetails : System.Web.UI.Page
{
static int numberOfReviews=0;
protected void Page_Load(object sender, EventArgs e)
{
numberOfReviews= GetReviews();
}
}
Here, will numberOfReviews be specific to each user or will be shared?
numberOfReviews
Application Scope: The variables that have application scope are available throughout the application, i.e to all users of the applications across all pages.
Session Scope: When many users connect to your site, each of them will have a separate session (tied to the identity of the user that is recognized by the application.) When the variable has session scope it will have new instance for each session, even though the users are accessing the same page. The session variable instance is available across all pages for that session.
Page Scope: When you have a instance variable on a Page it is specific to that page only and that session only.
Static variables have Application scope. All users of the application will share the same variable instance in your case.
Please note that although static variables have one instance in the app domain. So if you have your application deployed on a load balanced web farm, each app domain will have a separate instance of the variable. This might give you incorrect result.
Based on this you should decide what scope your variable should be in. IMO, using static variables is a code smell and should be discouraged.
static variable scope is application wide. numberOfReviews will be shared among all users. you need to use Session to store per user, so it is accessible in all pages. On the other hand, if you just need it on a specific page, you can save it in ViewState and can get it in post back.
It will be shared application wide just like Application["some_id"].
Use normal int variable for this.
As Adeel already mentioned: static(or shared in VB.Net) variables are application-wide. That means they are the same for every user and exist till webserver is stopped or last session has abandoned.
You could use the Session to store variables that belong to the current User.
If you need access to other user's numberOfReviews(f.e. as administrator or for statistics), you could use database, asp.net-cache or a simple static dictionary with the userid as key.
usually to do this a database is used
Data Table
userId | UserViews
Also you can use static variable as u are saying in that case you have to store data in Application State, problem with that is, ur whole data will be resett whenever ur will re-start.
Related
Sessions' variables
In all web app you can get/set sessions' variables
PHP:
$foo = $_SESSION['myVar'];
.NET (MVC, in Controller):
using System.Web.Mvc;
// ...
var foo = Session["myVar"];
I am looking for some detailed informations on sessions' variables :
Their initial purpose (what problems did they aimed to address ?)
Common use cases
Storage
Where is it stored on the system ?
Hard drive, RAM, ...
Who is storing it?
Client / Server
I guess it's server-side, so what is managing it ?
Web Server (Apache, IIS, ...) / Web App
What is the lifetime of a session's variable ?
The session, right. So when do a session start, when does it end and how do the system know when it can get rid of these variables (GC mechanism) ?
Security
Known security flaws ?
PS: I would like to allow people here to build a good documentation about this concept. Feel free to edit the question if you think some questions should be added or edited.
Purpose
Session Variables were created primarily to deal with the stateless behavior of the HTTP protocol. Because each page request was handled pretty much completely separately from each other page request, developers wanted ways to tie strings of requests together. The canonical example of this is a login page that authenticates the user and then changes the behavior of pages requested after login.
To help with this problem, many languages and/or frameworks provided the concept of a Session Variable which would let the developer store data that would be associated with a specific browser and would persist across separate requests from that same browser.
So, to take logins as an example, on the first request from a new browser, the Session Variable would be blank. Then the user would fill out authentication information and assuming it was correct, on the server side the code would set the Session Variable for that browser to contain some sort of identifier to say that his browser was authenticated. Then during subsequent requests the code could check that identifier in the Session Variable to do some specific code that required logging in.
Another common use case would be for a "wizard" workflow. You might have a multi-page form that you want the user to fill in over several separate requests. As the user fills out the form, you can add the values to the session until the user gets to the end of the form at which time you could save it in some more permanent storage.
Storage and Management
There are many ways to store Session Variables. Any sort of persistent storage that is persistent across requests will work. Probably the most basic way is to just create a separate file for each session. PHP does this by taking a session ID that it has stored as a cookie in a browser and then looks for a file with a named derived from the session ID.
You can also store Session Variables in databases, shared memory, or even in the cookie itself. Ruby on Rails stores Session Variables by encrypting the data and then setting the cookie to the encrypted data. So the session gets stored in the user's browser itself.
Most typically the Session Variable is associated with a cookie that is stored in web browser in some way. This cookie is usually managed automatically by the language or framework that the web server application is written in. The language or framework detects a new session and creates a new Session Variable that it provides to the web server application via some sort of API. The web server application can then use the API to store information in the Session Variable, to delete it, create a new one, etc... Usually the framework has some default value for the lifetime of the session, but usually this is adjustable via the API. I think the most typical default lifetime is the the lifetime of the browser process via a cookie that has a lifetime associated with the user's browser process.
Security
There are a lot of security issues around Session Variables because they are typically used to manage authorization and authentication in web applications.
For example, many applications set the session lifetime just using the lifetime associated with the cookie. Many login systems want to force the user to re-login after a specified time, but you can't trust the browser to expire the cookie when you tell it to. The browser could be buggy, could be written by a malicious person, or manipulated by the user herself to adjust the lifetime of the cookie. So if the Session Variable API you are using relies on the cookie lifetime, you may need to have a secondary mechanism that forces the Session Variable to expire even if the cookie doesn't.
Some other security issues involve storage. If you store A Session ID in a cookie and then use that Session ID as your file name to store the Session Variable in, a malicious browser can change the Session ID in the cookie to another ID and then requests from that browser would start using some other browser's session file.
Another issue is stolen session information. Through XSS or packet inspection, session information can be stolen from a users browser session and then used by a malicious user to access the other user's accounts. This sort of problem is typically mitigated by using SSL to protect the session in transit.
This page explains a lot of the security issues when using PHP's implementation of Session Variables. Ruby on Rails has a similar page that outlines the security issues with Session Variables for that platform.
So, I will be taking this question on under two considerations:
1. I am answering under PHP guidelines.
2. I am assuming that a shared hosting service is used.
Storage
With the use of shared hosting, the php.ini file holds this answer. The file is created, physically, at the path you specify through the "session.save_path" line within the php.ini file.
Source: php.net Manual
Who Stores Session
The session is TECHNICALLY stored by the SERVER but at request, obviously, by the client. So, answer: SERVER.
Source: session_start
Who Manages It
If your session.save_path is set to go somewhere on a shared hosting server, then they control the GC that destroys it or ignores it until later. Actually, instances have happened for me where other clients within the shared hosting server had their session_gc.maxlifetime at a MUCH shorter amount than I did, therefore causing my session files to be destroyed in the amount of time that THEY set (other shared users). To get around this, edit your "session.save_path" to within your OWN file tree.
Lifetime
As said previously, "session.gc_maxlifetime" controls this file's "expiration". Along with this, the "session.gc_probability" and "session.gc_divisor" should be considered, and set to "1" and "100", respectively. Google search this for further explanation.
Source: session.gc_maxlifetime
Security
I'm going to let php.net handle this, but here's the link!
Source: Security
I take an ASP.NET application scenario as an example.
In ASP.NET/MVC HttpContext.Current.Session provides access to RAM that is managed by the Server (WebServer/AppServer, IIS). In the case of the Internet Information Server, the RAM used is located inside a so called Application Pool and used by one or more Apps running inside the Web-/AppServer. The structure from the programmer's point of view is a Dictionary which means for access via C# that you can use the this[] operator to write to and read from the Session object.
// write access
var CurrentArticle = 123456;
Session["CurrentArticle"] = CurrentArticle;
//...
// read access
var CurrentArticle = 0;
CurrentArticle = (int)Session[nameof(CurrentArticle)];
The Session object provided by .NET will be created in the method Session_Start and deleted in Session_End. However, you don't have to use the System's default Session Store and can implement your own, i.e. like this:
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Caching;
using System.Web;
// using MyOtherStuff;
namespace MyStuff.Server.Context
{
public class HttpSessionState : HttpSessionStateBase
{
Dictionary<string, object> _sessionStorage = new System.Collections.Generic.Dictionary<string, object>();
public override object this[string name]
{
get
{
if (HttpContext.Current == null || HttpContext.Current.Session == null)
if (!_sessionStorage.ContainsKey(name))
return null;
else return _sessionStorage[name];
return HttpContext.Current.Session[name];
}
set
{
if (HttpContext.Current == null || HttpContext.Current.Session == null)
_sessionStorage[name] = value;
else HttpContext.Current.Session[name] = value;
}
}
}
public class Current
{
/// <summary>
/// Objects stored in Cache expire after some time; compare Application
/// </summary>
public static ExpiringCache Cache = new ExpiringCache();
/// <summary>
/// Objects stored in Application don't expire
/// </summary>
public static Application Application = new Application();
public static HttpSessionState Session = new HttpSessionState();
private static System.Web.HttpServerUtility server;
public static System.Web.HttpServerUtility Server
{
get
{
if (System.Web.HttpContext.Current != null)
return Context.Current.Server;
if (server != null)
return server;
server = new System.Web.HttpApplication().Server;
if (server != null)
return server;
throw new NotSupportedException("HDitem.ApplicationServices.Current was not initialized (server)");
}
set { server = value; }
}
}
//..
}
Every new Browser connecting to your server creates a new session. If you don't care about the data from recent sessions of the same user (if your app has users) than you are probably done here.
If you want to re-connect a new session to one or more previous sessions, i.e. identified by some combination of data you have available about this user (e.g. through the request, a cookie or alike) or in the easiest form the authentication of the user than you might want to store the data of the session in Session_End rather than deleting it and recover it in Session_start or any time thereafter (as soon as you have enough data about the user of this session to identify her. In this case you need any form of Session Persistence (presumably this boils down to a Hard Disk or SSD to refer to your question) which in this case can come in any form of per-user-based storage, sometimes stored in a user-profile in a database or any file format like XML- or JSON-based.
So in other words: I don't want to generalize too much here but Session Storage is ideally very fast Memory Storage, potentially saved to any external storage if Session Persistence is implemented.
The above mentioned Session Storage is located on the server side. Modern browsers have a built in localstore that can be accessed via JavaScript. This local storage can also be used to create a session memory that can be used differently from the server-side session but can of course be synchronized in form of explicit requests or attachment to requests (cookie).
I am in a situation where requirement is to keep an application level object in web api which can be accessed by all requests. I know one can use HttpContext.Current but that is not required since HttpContext is only for the liftime of request. I need a solution where i can keep an object that all requests can access and update as required.
Use a static class to hold your application level objects. static classes and static data members are created once for the application lifetime and all ASP.NET requests can access them.
I learnt it the hard way. Some time back, I mistakenly created a static field to hold customer-specific database connection string, in a ASP.NET Web API project and it became a mess. On each customer's login it was being set (overridden) in the code and the requests from the previously logged customers were using this newly set static SQL connection string for their queries. It was an embarrassing situation when customer's inadvertently saw each other's data.
You could use SessionState (per session).
I.e.
Session["YourDataKey"] = ApplicationLevelObject;
And then check the session state variable on each request that requires it.
However if you require the object for longer, I.e. every single user session, then I would suggest persisting your object to a database. You could use an ORM such as Entity Framework.
Cheers
Our company has a multi tenant asp.net web application. The application is 3 tier e.g. website,business and dataaccess. We hold the tenant id in session after the user logs in.
When we need to get a list of 'customers or orders' we pass the tenant id from the website to the business to the data access and then to the database (and query for customers or orders for that tenant). (almost every business function takes tenantId as a parameter)
Sometimes when creating new functions developers forget to add the tenant id from the website to the database, causing a security issue.
Is there a way we could do this so that the developers dont need to always remember to pass the tenant id.
Any suggestions on how best to resolve this issue.
public class CommonService
{
public int getTenantId()
{
//do your validations and error handlings
string tid = session["tenantId"] // or get it from customs claims principal or set it in a httpcontext.current.items
return tid;
}
}
Then use the service in every business object to get the tenant id and pass it to the data layer without depending on the developers to do it. Its a very big security hole, missing an tenantId might return data which the user is not supposed to see and might shutdown the company
It sounds like you are passing all the values around individually.
If you construct an object that you can pass around freely, you will always have the information you need. I would assume that the UserId is always associated with a tenant. Can you build a simple object, store it in the session and then pass it to all functions needing it.
class user{
int userID;
int tenantID;
}
If you have a value in the Session and you need it in the database queries, you have to propagate it through the tiers to the database queries.
If your developers sometimes forget to pass the value and they get security issues, that is actually not a security issue but a security feature.
If the database needs that id, then the business layer methods should have parameters for it. How can they forget it?
One approach would be to create a View per table per tenant (may not be practical depending on the number of tenants you have and how frequently they change) and deny access to the application to the underlying tables.
This article explains how to do this as well as several other approaches and their performance tradeoffs:
http://msdn.microsoft.com/en-us/library/aa479086.aspx
I'm creating a generic flexible site that I can use over and over again but with different features activated or deactivated. I'm looking for the best method to approach my solution.
Specific areas will need to be closed off in certain circumstances, for instance, the application will contain an event management page, but it will not always be required. The application will pull out the active and deactivated features from a data source.
They're going to be like Application wide settings, that will be required on each page, hiding away those settings that are turned off from the menu and not allowing users to access the deactivated feature pages.
I have thought of a number of ways to achieve this :
Store the feature statuses in the database, then on each time the page / menu is accessed / displayed, call the database requesting whether to hide the page / menu item.
Store the feature statuses in the database and access them on the application startup, store them application wide then they can be accessed as and when.
Put the feature statuses in the web config, this way we don't need to query the database every single time or have globally accessible properties.
I would like you advice on which method would be best, or if a better method is available I would be grateful. I don't want to hit the database too many times, or would a simple check like this not be too performance expensive? I'm also not sure if the web config is secure enough for managing active site features.
Regards,
I think putting configuration in configuration file(web.config) would be better option. Because while displaying page/loading menu going to database every time to see whether it should be de/active, required database trip which is overhead.
And if the configuration is stored in web.config it is easily accessible by admin and also easy to modify without compiling or changing anything.
So, in my view best option is to store configuration in web.config. In addition to that you can also make administration page which will change configuration settings and should be reflected in configuration file.
I suggest 2nd approach - store the settings in the database and then retrieve them at startup and store in application scoped containers.
The advantage of such approach over the web.config is that you can easily take client database and immediately run it in your development environment for testing/debugging. If, on the other hand, some settings are stored outside of the database, cloning the site means that you not only have to clone the database but also all the settings from various other resources (like the web.config).
The answer depends on how often you will be changing the status of the features.
If you are going to only set the statuses once when you clone the site and will never touch it again, go with option #2 (load on application start).
If there is any possibility that you will need to change the status of the features in the future, go with option #1 (get statuses on each page load). A simple datareader read to the db will not affect the speed of your site. The db is your friend, remember that's what it is there for. Also, if you ever need to change the statuses while the site is up and running, this method allows you to do so without restarting the entire application.
Whatever method you finally decide to implement, make sure the "application wide" location you store the settings is multi-threaded ready. Remember, each page request will be run on a separate thread and they will all access the same resource.
My suggestion taken from MS (multi-thread safe Singleton Pattern):
using System;
public sealed class Singleton
{
private static volatile Singleton instance;
private static object syncRoot = new Object();
private Singleton() {}
public static Singleton Instance
{
get
{
if (instance == null)
{
lock (syncRoot)
{
if (instance == null)
instance = new Singleton();
}
}
return instance;
}
}
}
I have an ASP.net web application running in the default application pool. A user has reported getting results returned that were meant for a different user. As far as I know there is no way two users on two different machines should ever see each other's results.
Here is very roughly what the internal structure looks like
namespace SomeApplication
{
public partial class _Default : System.Web.UI.Page
{
static ArrayList results = new ArrayList();
protected void Button_Click(object sender, EventArgs e)
{
// Add data to results
// Display in asp:Table element
}
}
}
User1 and User2 were both using the above application at roughly the same moment. User1 got normal results but user2 got a mix of their results and User1's results appear in the asp:Table.
Now I know the results object is in the global scope, but it was my understanding that is this a per-instance of the application object.
Static variables are not user specific, they are global within the ASP.NET worker process currently running. It is entirely possible that this one process served both your users. This means that any code running in the process will see this static variable. Statics are also dangerous because IIS can recycle the worker process at any point it pleases, this will bin the values in the variables.
Instead you may need to use one of the state/caching mechanisms provided in ASP.NET, like Session State:
http://msdn.microsoft.com/en-us/library/ms972429.aspx
As already pointed out by Adam, static variables are not user specific but are per AppDomain. So in ASP.NET scenario where you are running multiple sites in one app-pool, each app-pool process (you can more than one worker process per app pool based on configuration) will have one app domain for each web application. So all your users will share same static variables.
Not only that there is no thread-safty built in for static variables and you can actually see in-consistent data when two different threads are accessing those variables.
For the example that you have sited, you will be better off using a instance variable which corresponds to per request scope (in ASP.NET scenario) but full-fill most of use cases (and you don't have to worry about thread-safty). For data that you want to maintain for the same page over repeated post-back, view-state is the way to go. For data that has more life time, you can choose between Session State, ASP.NET Cache, Application state etc. First two are thread-safe implementations while Application state provides means to lock the slot before accessing them.
Refer these links for various state management options that you have available in ASP.NET:
http://msdn.microsoft.com/en-us/library/z1hkazw7.aspx
http://msdn.microsoft.com/en-us/library/75x4ha6s.aspx