I have used static variable which I hope it will persist in IIS. But for sometimes, it is cleared. Is that possible that IIS will clear the static variable?
public partial class Main : CustomPage
{
public static bool cachedCurrentYearDataInFile = false;
static variables live though the application cycle. If the application ends (chech application pool settings like idle and recycle) a new instance is generated and you would lose all static information of the now non-existant one. If you want persistence you should consider, actual persistence like file/database.
Related
I am working within a solution that has a static logging object in a library that is shared among the projects. This is how it is structured:
public class AppLog
{
private static string _logFile;
private static string _appName;
public static string AppName
{
get { return _appName; }
set
{
_appName = value;
InitLogFilePath(); // initializes _logFile according to _appName
}
}
public static Write(string msg)
{
// writes to _logFile
}
}
It works fine for the various Windows apps and Windows services: They can initialize AppLog.AppName upon startup and AppLog.Write can be called throughout the code. Shared modules write to a file named according to the initialization of AppName.
The problem I have is using this within WCF web services. The web services are configured for InstanceContextMode.PerCall. AppLog.AppName is being initialized according to ServiceHostBase.Description.Name. But since multiple web services run within the same AppDomain this static data is shared. So one ws call sets AppLog.AppName and it is changed by the next call, which may have a different ServiceHostBase.Description.Name.
How can this be restructured so that AppLog.Write can still be used throughout the projects in my solution but handle the naming differently for each web service?
If could tell whether the code is running within a web service, and if I could retrieve the ServiceHostBase.Description of the service, then I could maintain a lookup for the appropriate file name. But I have not yet found a way to do this.
Given the way your logging is structured there is not a good solution.
Most logging libraries are structured so that you create an instance of the logger, pass the instance any application specific data (like AppName), and then store that instance in a private static member. The static storage is in the application, not the logging library. This avoids the sharing conflict that you have and still only creates a small fixed number of logger instances.
To illustrate the point, here's a standard log4net example from CodeProject log4net tutorial. This code passes the current class name to the instance of the logger.
private static readonly log4net.ILog log = log4net.LogManager.GetLogger
(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
My suggestion is to look at changing to log4net or any of the other logging packages available on NuGet.
Given your situation, AppName is not where is should be. You need a per-webservice logging facade that hold the AppName and pass the core "Write" logic down to your current AppLog. Then each of the web service has its own LogFacade instance.
class LogFacade
{
public string AppName {get; private set;}
LogFacade(string appName)
{
AppName = appName;
}
public void Write(string msg)
{
AppLog.Write(string.format("[{0}]{1}", AppName, msg));
}
}
Or as ErnieL said, take a look at log4net.
I am trying to access global.asax application variable from WCF, that's my goal at least. I've tried many type of solutions, but the one that I am trying now is using static variables.
I've created a StaticVariable.cs class like so:
public static class StaticVariables
{
private static string _Key = "name1";
public static Object someInfo
{
get
{
return HttpContext.Current.Application[_Key];
}
}
}
The Application["name1"] is initialized in the global.asax.cs. I can read it when I access my webservice but not in my WCF service.
In my WCF I call the StaticVariables someInfo to retrieve the data, but I get:
System.Web.HttpContext.Current is null error
My WCF is running asynchronously and its called from within a webservice using Task<int>.Factory.FromAsync. So I assume that the problem is that the WCF runs not on the main thread, but I am not sure.
So it seems that the Static class doesn't work in my case and I wanted to know how to solve this. Thanks
Why don't you simply use static variables ?
HttpContext is dependent on ASP.NET pipeline. In a host-agnostic model (OWIN or self-hosted) you don't have access to it.
Application storage in HttpApplicationState is only useful if you need to access the current HttpContext. If it's not necessary, you should simply use static properties.
Moreover, HttpApplicationState was initially created for backward compatibility with classic ASP.
public static class StaticVariables
{
public static object SomeInfo { get; set; }
}
See also Singleton and HttpApplicationState and http://forums.asp.net/t/1574797.aspx
What is the lifecycle of a static field in C# MVC:
private static InventoryMgmtContext _dbContext = new InventoryMgmtContext();
public ManageWorkOrdersAppServ()
: base(new WorkOrderHeaderRepository(_dbContext ))
{
_workOrderHeaderRepository = new WorkOrderHeaderRepository(_dbContext);
_workOrderDetailRepository = new WorkOrderDetailRepository(_dbContext);
}
In this case when does the _dbContext die?
This is a follow up to my other question that I haven't been able to get clarification on.
Static fields live for as long as the AppDomain in which the type is loaded lives. That's true regardless of environment.
Now in a web environment, IIS will recycle the AppDomain in some situations - so you shouldn't rely on it being the same forever.
If that's really a database context though, I don't think it should be in a static field at all. Typically you create a database context for a single "unit of work".
I have some WCF services. These services run in ASP.NET. I want these services to be able to access a static variable. My problem is, I'm not sure where the appropriate server level storage mechanism is. I don't want to use the database because of speed. But, I want the static variables to stay in memory as long as possible. In fact, I'd like it to stay until I restart my server if it all possible.
Can anyone provide me with any ideas?
You could use static variables in WCF but you must properly synchronize the access to them because they can potentially be accessed from multiple threads concurrently. The values stored in static variables are accessible from everywhere in the AppDomain and remain in memory until the server is restarted.
You could have something like this
public static class StaticVariables
{
private static string _variable1Key = "variable1";
public static Object Variable1
{
get
{
return Application[_variable1Key];
}
set
{
Application[_variable1Key] = value;
}
}
}
The Application collection itself is thread safe but the stuff you add to it might not be; so keep that in mind.
If all the services are in a single ServiceContract and if all the member variables in your service can be shared across all sessions, then you could set the ServiceBehavior to have a single instance.
[ServiceBehavior( InstanceContextMode = InstanceContextMode.Single )]
public class MyService : IMyServiceContract
{
}
I have a question about Singletons running within IIS (6,7,7.5) and an ASP.NET 4.0 Web Application (MVC3 app to be specific).
I have a singleton object in my project that is accessed and used in the global.ascx, on the application_start, as well as a few other places within the application.
My concern is, this singleton needs to be accessable at a per instance scenario. However, since IIS is essentially the hosting process, is the singleton going to be the same object across all instances of the application?
If I use the [ThreadStatic] keyword, does it seperate at the Application Pool level?
Finally, is there a way, I can assure a singleton is only a singleton per instance of my application. i.e. if I run my application on 1 website, but inside 5 virtual directories, there is 5 instances of the singleton or if I run my website on 5 different websites within the same application pool.
Hopefully that's clear enough, incase you wanted to see the singleton object, I pasted the general idea of it below.
public sealed class Singleton : IDisposable
{
[ThreadStatic]
private static volatile Singleton _instance;
[ThreadStatic]
private static readonly object _syncRoot = new object();
public bool IsReleased { get; private set; }
public Singleton()
{
IsReleased = false;
}
public static Singleton Instance
{
get
{
if (_instance == null)
{
lock (_syncRoot)
{
if (_instance == null)
_instance = new Singleton();
}
}
return _instance;
}
}
public void Dispose()
{
IsReleased = true;
Singleton._instance = null;
}
}
A static value should be static across a particular instance of your web application, so each instance of your application will have its own instance that will be shared across all threads on that instance.
For further reading, see http://msdn.microsoft.com/en-us/library/2bh4z9hs(v=vs.71).aspx
Oh, and the ThreadStatic attribute will cause the static value to only be static across a particular thread, so every request would have its own version of that field. It doesn't sound like this is what you're going for.
With IIS, you have no control over the thread that your request runs on. If you really need this kind of application instance level locking, you may want to look into the heavier locking objects (Mutex, Monitor, etc) and create one for each application.
If you absolutely want to ensure that they are separate, you could run each one in it's own Application Pool. That way you'd get a WP for each virtual directory.