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
Related
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;
}
}
}
The context:
(Note: in the following I am using "project" to refer to a collection of software deliverables, intended for a single customer or a specific market. I am not referring to "project" as it is used in Visual Studio to refer to a configuration that builds a single EXE or DLL, within a solution.)
We have a sizable system that consists of three layers:
A layer containing code that is shared across projects
A layer containing code that is shared across different applications within a project
A layer containing code that is specific to a particular application or website within a project.
The first two layers are built into DLL assemblies. The top layer is an assortment of EXEs and/or .aspx web applications.
IIRC, we have a number of different projects that use this pattern. All four share layer 1 (though often in slightly different versions, as managed by the VCS). Each of them has its own layer 2. Each of them has its own set of deliverables, which can range from a website, or a website and a background service, to our largest and most complex (and the bread-and-butter of our business) which consists of something like five independent web applications, 20+ console applications/background services, three or four independent web services, half-a-dozen desktop GUI apps, etc.
It's been our intent to push as much code into levels 1 and 2 as possible, to avoid duplicating logic in the top layers. We've pretty much accomplished that.
Each of layers 1 and 2 produce three deliverables, a DLL containing the code that is not web-related, a DLL containing the code that is web-related, and a DLL containing unit tests.
The problem:
The lower levels were written to make extensive use of singletons.
The non-web DLL in layer 1 contains classes to handle INI files, logging, a custom-built obect-relational mapper, which handles database connections, etc. All of these used singletons.
And when we started building things on the web, all of those singletons became a problem. Different users would hit the website, log in, and start doing different things. They'd do something that generated a query, which would result in a call into the singleton ORM to get a new database connection, which would access the singleton configuration object to get the connection string, and then the connection would be asked to perform a query. And in the query the connection would access the singleton logger to log the SQL statement that was generated, and the logger would access the singleton configuration object to get the current username, so as to include it in the log, and if someone else had logged in in the meantime that singleton configuration object would have a different current user. It was a mess.
So what what we did, when we started writing web applications using this code base was to create a singleton factory class, that was itself a singleton. Every one of the other singletons had a public static instance() method that had been calling a private constructor. Instead, the public static instance() method obtained a reference to the singleton factory object, then called a method on that to get a reference to the single instance of the class in question.
In other words, instead of having a dozen classes that each maintained its own private static reference, we now had a single class that maintained a single static reference, and the object that it maintained a reference to contained a dozen references to the other, formerly singleton classes.
Now we had only one singleton to deal with. And in its public static instance() method, we added some web-specific logic. If we had an HTTPContext and that context had an instance of the factory in its session, we'd return the instance from the session. If we had an HTTPContext, and it didn't have a factory in its session, we'd construct a new factory and store it in the session, and then return it. If we had no HTTPContext, we'd just construct a new factory and return it.
The code for this was placed in classes we derived from Page, WebControl, and MasterPage, and then we used our classes in our higher-level code.
This worked fine, for .aspx web applications, where users logged in and maintained session. It worked fine for .asmx web services running within those web applications. But it has real limits.
In particular, it won't work in situations where there is no session. We're feeling pressure to provide websites that serve a larger user base - that might have tens or hundreds of thousands of users hitting them dynamically. Up to now our users have been pretty typical desktop business users. They log into our websites, and stay in them much of the day, using our web apps as an alternative to a desktop app. A given customer might have as many as six users who might use our websites, and while we have a thousand or more customers, combined they don't make for all that heavy a load. But our current architecture will not scale to that.
We're also running into situations where ASP.NET MVC would be a better fit for building the web UI than .aspx web forms. And we're exploring building mobile apps that would be communicating with stand-alone WFC web services. And while in both of these, it looks like it's possible to run them in an environment that has a session, it looks to limit their flexibility and performance fairly severely.
So, we're really looking at ways to eliminate these singletons.
What I'd really like:
I'm trying to envision a series of refactors, that would eventually lead to a better-structured, more flexible architecture. I could easily see the advantages of an IoC framework, in our situation.
But here's the thing - from what I've seen of IoC frameworks, they need their dependencies provided to them externally via constructor parameters. My logger class, for example, needs an instance of my config class, from which to obtain the current user. Currently, it is using the public static instance() method on the config class to obtain it. To use an IoC framework, I'd need to pass it as a constructor.
In other words, from where I sit, the first, and unavoidable task, is to change every class that uses any of these singletons so as to take the singleton factory as a constructor parameter. And that's a huge amount of work.
As an example, I just spent the afternoon doing exactly that, in the level 1 libraries, to see just how much work it is. I ended up changing over 1300 lines of code. The level 2 libraries will be worse.
So, are there any alternatives?
Typically, you should try to wrap the contextual information into its own instance and provide a static accessor method to refer to it. For example, consider HttpContext and its available every where in web application via HttpContext.Current.
You should try to devise something similar so that instead of returning singleton instance, you would return the instance from the current context. That way, you need to not change your consumer code that refers to these static methods (e.g. Logger.Instance()).
I generally roll-up information such as logger, current user, configuration, security permissions into application context (can be more than one class if need arises). The AppContext.Current static method returns the current context. The method implementation goes something like
public interface IContextStorage
{
// Gets the stored context
AppContext Get();
// Stores the context, context can be null
void Set(AppContext context);
}
public class AppContext
{
private static IContextStorage _storageProvider, _defaultStorageProvider;
public static AppContext Current
{
get
{
var value = _storageProvider.Get();
// If context is not available in storage then lookup
// using default provider for worker (threadpool) therads.
if (null == value && _storageProvider != _defaultStorageProvider
&& Thread.CurrentThread.IsThreadPoolThread)
{
value = _defaultStorageProvider.Get();
}
return value;
}
}
...
}
IContextStorage implementations are application specific. The static variables _storageProvider gets injected at the application start-up time while _defaultStorageProvider is a simple implementation that looks into current call context.
App Context creation happens in multiple stages - for example, a global information such as configuration gets read and cached at application start-up while specific information such as user & security gets formed at authentication stage. Once all info is available, the actual instance is created and stored into the app specific storage location. For example, desktop application will use a singleton instance while web application can probably store the instance into the session state. For web application, you may have logic at start of each request to ensure that the context is initialized.
For a scalable web applications, you can have a storage provider that will store the context instance into the cache and if not present in the cache then re-built it.
I'd recommend starting by implementing "Poor Man's DI" pattern. This is where you define two constructors in your classes, one that accepts an instance of the dependencies (IoC), and another default constructor that new's them up (or calls a singleton).
This way you can introduce IoC incrementally, and still have everything else work using the default constructors. Eventually when you have IoC being used in most places you can start to remove the default constructors (and the singletons).
public class Foo {
public Foo(ILogger log, IConfig config) {
_logger = log;
_config = config;
}
public Foo() : this(Logger.Instance(), Config.Instance()) {}
}
I need to implement several application-level behavior in a project I'm currently working on.
There are several things I need to get my head around:
1. Where and how do I define application level variables?
2. What is the lifetime of these variables? or more accuratly, in what scenarios are they discarded? (Application pool recycle? App binaries dropped from memory and recompiled on the next request? etc.)
3. Is the global.asax file a good place to put a session counter, or maybe storing the value to a DB / file is a better way of persisting this kind of data?
Any comments or ideas are welcome.
Thank you!
-Elad
Application-level variables have an application life-time. It means that it the application pool is recycled, they're discarded.
The application pool can be recycled for different reasons. IIS 6/7 can be configures so that the app pool is recycled after a certain amount of time, after a certain number of request or at specified intervals.
You set an application variable this way:
Application["DbConfig"] = "my value";
but you have to be aware of the problems you might encounter if you try to set/access in different place. You have to adopt a way to lock the variables when they're updated.
I us the web.config for all the configuration parameters and then I've created my own class which I use to store application fields:
namespace Web.My
{
public class Application
{
public static string ApplicationStorageFolder
{
get
{
return (System.IO.Path.Combine(HttpContext.Current.Server.MapPath("~"), "_AppStorage"));
}
}
}
}
If I need set some fields I do it at the application startup Application_Start
If you need to persist infos you can create your own config file (xml or simple text) to store and read values at the application startup and shutdown. You can serialize your class in a XML file so you can ready it, repopulating your properties easily.
A db would be fine as well.
I would do the same with the session counter.
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.
I have some ASP.NET web services which all share a common helper class they only need to instantiate one instance of per server. It's used for simple translation of data, but does spend some time during start-up loading things from the web.config file, etc. The helper class is 100% thread-safe. Think of it as a simple library of utility calls. I'd make all the methods shared on the class, but I want to load the initial configuration from web.config. We've deployed the web services to IIS 6.0 and using an Application Pool, with a Web Garden of 15 workers.
I declared the helper class as a Private Shared variable in Global.asax, and added a lazy load Shared ReadOnly property like this:
Private Shared _helper As MyHelperClass
Public Shared ReadOnly Property Helper() As MyHelperClass
Get
If _helper Is Nothing Then
_helper = New MyHelperClass()
End If
Return _helper
End Get
End Property
I have logging code in the constructor for MyHelperClass(), and it shows the constructor running for each request, even on the same thread. I'm sure I'm just missing some key detail of ASP.NET but MSDN hasn't been very helpful.
I've tried doing similar things using both Application("Helper") and Cache("Helper") and I still saw the constructor run with each request.
You can place your Helper in the Application State. Do this in global.asax:
void Application_Start(object sender, EventArgs e)
{
Application.Add("MyHelper", new MyHelperClass());
}
You can use the Helper that way:
MyHelperClass helper = (MyHelperClass)HttpContext.Current.Application["MyHelper"];
helper.Foo();
This results in a single instance of the MyHelperClass class that is created on application start and lives in application state. Since the instance is created in Application_Start, this happens only once for each HttpApplication instance and not per Request.
It's not wise to use application state unless you absolutely require it, things are much simpler if you stick to using per-request objects. Any addition of state to the helper classes could cause all sorts of subtle errors. Use the HttpContext.Current items collection and intialise it per request. A VB module would do what you want, but you must be sure not to make it stateful.
I 'v done something like this in my own app in the past and it caused all kinds of weird errors.
Every user will have access to everyone else's data in the property. Plus you could end up with one user being in the middle of using it and than getting cut off because its being requested by another user.
No there not isolated.