HTTPContext across threads - c#

I need to instantiate a singleton object per web request, so that the data is processed once and is valid throughout the request, I was using HttpContext.Current.Items to share data during HTTP request, everything was fine until we needed the singleton object instance across multiple threads, the first thing that I came up with was to pass the HttpContext instance to the new thread:
HttpContext context = HttpContext.Current;
ThreadPool.QueueUserWorkItem(callback =>
{
HttpContext.Current = context;
// blah blah
});
Which I don't think is a thread-safe approach as noted here.
Using Reflector I figured HttpContext.Current.Items actually uses CallContext to store objects in each logical thread. So I changed the singleton interface to this:
public static SingletonType SingletonInstance
{
get { return CallContext.GetData(key) as SingletonType; }
set { CallContext.SetData(key, value); }
}
And simply overwrite SingletonInstance when starting any new thread! The code works fine, however it seems that somehow under heavy load, CallContext.GetData(key) returns null and the application crashes with with a null reference exception!
I was thinking, if CallContext.GetData is atomic? But it just doesn't seem right, the CallContext is thread specific data storage and must be atomic or I am missing the point!
My other guess is that setting the SingletonInstance (CallContext.SetData) happens in one thread while CallContext.GetData executes in another as noted here but I don't know how/why?
update:
We are keeping an instance of each online user in an array on the server. The singleton object is actually a reference to the object representing current user. Current user must be unique and available in each thread for database querying, logging, error handling and more, this is how it is done:
public static ApplicationUser CurrentUser
{
get { return CallContext.GetData("ApplicationUser") as ApplicationUser ; }
set { CallContext.SetData("ApplicationUser", value); }
}

ASP.NET may migrate request between threads if it's under load. Once request is received page constructor may execute on one thread and page load on another. In this thread switch CallContext and ThreadStatic are not migrated, but luckaly HttpContext is.
This may be misleading as HttpContext is call context, but this is a little quirk in ASP.NET, probably due to cutting corners to improve performance.
You'll have to remove dependencies to CallContext and use HttpContext entire way through.
You can read more details in this terrific blog post by Piers7.

This was resolved during a chat session.
In essence it involves long-running tasks and a suggestion of using an external service (Web, or regular Windows Service) was decided as the best solution to the problem.

Thread-safing your second method is the best approach.
This is thread-safe version of your singletone:
public sealed class SingletonType
{
#region thread-safe singletone
private static object _lock = new object();
private SingletonType() { }
public static SingletonType SingletonInstance
{
get
{
if (CallContext.GetData(key) == null)
{
lock (_lock)
{
if (CallContext.GetData(key) == null)
CallContext.SetData(key, new SingletonType());
}
}
return CallContext.GetData(key) as SingletonType;
}
}
#endregion
//
//
// SingletoneType members
//
//
}
NOTE : using a lock { } block is the key.

Related

Worker queue and user context

We have a worker queue that a user can add work to. When the worker item is added the context is the users (HttpContext). But its a background thread that polls the queue and executes the items one by one in order.
I cant just store the User because when the HttpContext is disposed so will the Principal object
The code that can run in the worker needs the Principal to be correct for stuff like PrincipalPermissions etc.
Also, Lifetime management (IoC) uses the HttpContext for InRequest scopes, is it possible to recreate a HttpContext with the correct principal etc.
edit:
Faking HttpContext is just a nice to have feature for Life time management, this I can work around.
But our backend code heavily depends on having the correct user principal for the thread since we use this to validate if user has access to that part of the system. I would mark as answer if someone can answer how to store a user principal with identity, roles and IsAuthenticated state and later use that on another thread
Your best practice for consuming stateful data from the HttpContext is to create your own application specific context which accepts an HttpContext in the constructor (Dependency Injected).
Your business logic should never be dependent on an HttpContext but rather your new application specific context (which may have been created using info from an HttpContext).
This will not only solve your above problems, but also increase testability of your code.
Example:
public class MyApplicationContext
{
public IPrincipal ContextPrincipal { get; set; }
public MyApplicationContext(HttpContext httpContext)
{
// Store the current user principal & identity
ContextPrincipal = httpContext.User;
// Need to grab anything else from the HttpContext? Do it here!
// That could be cookies, Http request header values, query string
// parameters, session state variables, etc.
//
// Once you gather up any other stateful data, store it here in
// your application context object as the HttpRequest can't be passed
// to another thread.
}
}
public class MyHttpHandler : IHttpHandler
{
#region IHttpHandler Members
public bool IsReusable
{
// Return false in case your Managed Handler cannot be reused for another request.
// Usually this would be false in case you have some state information preserved per request.
get { return true; }
}
public void ProcessRequest(HttpContext context)
{
// Do some work on another thread using the ThreadPool
ThreadPool.QueueUserWorkItem(new WaitCallback(DoWork), new MyApplicationContext(context));
}
public void DoWork(object state)
{
// Grab our state info which should be an instance of an
// MyApplicationContext.
MyApplicationContext context = (MyApplicationContext) state;
// Assign this ThreadPool thread's current principal according
// to our passed in application context.
Thread.CurrentPrincipal = context.ContextPrincipal;
// Check if this user is authenticated.
if (context.ContextPrincipal.Identity.IsAuthenticated)
{
var userName = context.ContextPrincipal.Identity.Name;
}
// Check if this user is an administrator.
if (context.ContextPrincipal.IsInRole("Administrator"))
{
}
// Do some long-ish process that we need to do on the threadpool
// after the HttpRequest has already been responded to earlier.
//
// This would normally be some fancy calculation/math, data
// operation or file routines.
for (int i = 0; i < 30; i++)
{
Thread.Sleep(1000);
}
}
#endregion
}
Neither the IPrincipal nor IIdentity interface explicitly offer a dispose method. So they should both be ok to keep a reference to them. However, I haven't tested the above code, I wrote it just for this question.
If by some poor design they actually do depend on an underlying database connection to query the roles membership, you'd simply have to evaluate that earlier in the constructor of your application context while the HttpContext and asp.net forms authentication provider are still non disposed/closed.
You can always take apart the principal and identity and recreate a new instance of GenericPrincipal and GenericIdentity or even create your application Identity class which implements IIdentity. There is lots of room for customization/extension here.
public void TestMethod1()
{
System.Net.WebClient client = new System.Net.WebClient();
client.BaseAddress = "http://www.teejoo.com";
//Invoke your function here
client.OpenReadAsync(new Uri("http://www.teejoo.com/YourLogicalPage.aspx"));
//Pur your logical in your page, so you can use httpContext
client.OpenReadCompleted += new System.Net.OpenReadCompletedEventHandler(client_OpenReadCompleted);
}
void client_OpenReadCompleted(object sender, System.Net.OpenReadCompletedEventArgs e)
{
//to Check the response HERE
}
Why don't you use an auxiliar class to hold the information you need? You can create it during the web request with the appropriate values and pass it down as an argument to the background worker.
Cloning the HTTPContext object is not possible because of the internal server session state. Even if it were possible, using it outside of a real HTTP request just to check for values doesn't seem like a good solution.

C# Class Library - Singleton Design Pattern

Background/Question:
I'm fairly new to the singleton design pattern. I've used it once in a web application (with the help of the SO community):
public static AppGlobal Instance
{
get
{
if (HttpContext.Current.Session != null)
{
HttpSessionState session = HttpContext.Current.Session;
if (session["AppGlobalInstance"] == null)
{
session["AppGlobalInstance"] = new AppGlobal();
}
return (AppGlobal)session["AppGlobalInstance"];
}
else
{
return null;
}
}
}
The above implementation makes sense to me because the instance of the AppGlobal is stored in the session. When the session dies, AppGlobal dies. What happens if I use the same design pattern in a class library that is called by a web application? For example, the users requests a page that calls methods in a DLL that doesn't know about the session. Will the data stored in the singleton instance be persisted through multiple calls?
private static readonly Singleton instance = new Singleton();
private Singleton() { }
public static Singleton Instance
{
get
{
return instance;
}
}
Additional Information:
Here's what I'm trying to accomplish: I have a web application that is going to receive XML requests from a third party application. This XML will tell my web application to do one of three things (or all three of them). I would like to have a singleton instance of a class that stores data that can be accessed by multiple classes. I want the singleton instance to DIE after each request. If the above doesn't accomplish this, what's the best way to accomplish it?
Note: This web application runs on a single server and will never run on a farm.
EDIT 1:
Based on the suggestion below, I've used System.Web.HttpContext.Current.Session to store my class instance. Does this look like the correct approach for a singleton that will be unique to each session (remember I'm in a class library)?
public static Ariba Instance
{
get
{
if (HttpContext.Current.Session != null)
{
HttpSessionState session = HttpContext.Current.Session;
if (session["AribaInstance"] == null)
{
session["AribaInstance"] = new Ariba();
}
return (Ariba)session["AribaInstance"];
}
else
{
return null;
}
}
}
It will be persisted through multiple calls, but there is one caveat. The static variables are scoped to the AppDomain, so any time the IIS worker process is recycled, any data stored in a static variable will be lost. The same is true of session data, if you're storing it "in proc."
If you want an object that will only exist for the duration of the HTTP request, you can use the HttpContext.Items property.
Because the singleton is static, your data will be available for all the requests in your web application, so it will not be available only for the session.
But in ASP.NET applications, you should avoid using Singletons. Instead you should use the Application object. Main reason for that is that if you will use a web farm then your singleton is no longer singelton for the application scope but only on the machine.
Oh!
If you want to use the instance PER REQUEST, why don't you pass it as a parameter to the methods you are calling or as a constructor parameter for the classes that requires the xml. This will be the best design approach, I think.

Passing session and response objects to a class - overhead?

I was wondering if anyone could help me understand if what I am doing is a lot of overhead or not. It is currently working but I am not sure if this could slow down the site or not.
I have a workflowobj class in which i set all the session variables. This class in instantiated on the pages that need it:
WorkFlowObj wfo = new WorkFlowObj(this.Session, this.Response);
wfo.VendorRedirect();
I need this because I need to be able to keep track of session variables and at the same time be able to keep track of a more complicated page workflow in one place. This solution already already works for me, but the only problem is that I am not sure if passing around the session and the response objects creates a lot of OVERHEAD. Can anyone tell me if this is terribly inefficient?? Below is the code for the workflowobj class.
public class WorkFlowObj
{
private System.Web.SessionState.HttpSessionState _pagesession;
private HttpResponse _HttpResponse;
private int _userid;
private string _vendorname;
///private other vars here
}
public int UserID
{
get
{
return _userid;
}
}
public WorkFlowObj(System.Web.SessionState.HttpSessionState pagesession, HttpResponse _response)
{
_pagesession = pagesession;
_HttpResponse = _response;
Initialize();
}
private void Initialize()
{
//initialize variables from session
_userid=_pagesession["userid"].ToString();
}
public void VendorRedirect()
{
switch (this._vendorname)
{
case "1":
this._HttpResponse.Redirect(page1);
break;
case "2":
this._HttpResponse.Redirect(page2);
break;
//etc
default:
//dostuff;
break;
}
}
}
As Rick says, I wouldn't create dependencies to System.Web in your middle-tier objects if you can avoid it.
But if you can't avoid it, you can avoid passing around the Session object by using the static System.Web.HttpContext class. This lets you do something like:
userid = (String)System.Web.HttpContext.Current.Session["userid"];
As long as it's executing on the same thread (and therefore in the same context) as the request from the browser.
I would not create dependencies to System.Web in your workflow objects, just pass the variables that the workflow objects need to make decision and execute business logic. There is no overhead passing objects around, they are just pointers under the hood.
One issue I could see happening is accidental use of statics in another layer that get tied to your Page state, thus not allowing the GC to clean up ie: classic out of memory exception or app pool recycle.

Access the current InstanceContext in a WCF UsernamePasswordValidator

I have a WCF service that is using a custom UsernamePasswordValidator. The validator needs to access my entity framework context.
I would like to create one ObjectContext for the entire service call and then destroy/dispose it at the end of the call. So I created a singleton static class that provided this functionality, however, what's happening now is that if two service calls happen concurrently, one of the calls disposes the singleton.
I either keep a local reference to the ObjectContext, in which case the second service to use it sees it as disposed and throws and error, or, I put a wrapper property around the Singleton class wherever I need it and then all my changes get thrown away because I'm getting a new instance of the object if another call has disposed it.
So basically my question is how do I instantiate an ObjectContext per service call?
NOTE: The instance needs to be accesible in both the service code AND the custom UsernamePasswordValidator code.
I can't just do it in the constructor or use a using statement because then the custom UsernamePasswordValidator doesn't have access to it. Is there a way to have a static class per call? It does sound impossible, but what's the way around this? Should I be caching the object in a session?
My service is hosted in IIS.
UPDATE:
So I've nailed this down to storing state in the InstanceContext using an IExtension object. But How do I access the current InstanceContext in a UsernamePasswordValidator?
Ok, so in the end I solved it by using the following static class and relying on ASP.NET to cache the context for me.
I'm not sure if this is the best way to do things, but this allows me to use one ObjectContext per request so I'm not spinning up too many and this also means I don't have to use a lock on the object which would become a nightmare if many users were using the service.
public static class MyContextProvider
{
public static MyModel Context
{
get
{
if (HttpContext.Current.Items["context"].IsNull())
{
HttpContext.Current.Items["context"] = new MyModel();
}
return HttpContext.Current.Items["context"] as MyModel;
}
}
}
Then wherever I need an ObjectContext in the app I just call
var context = MyContextProvider.Context;
You have one instance per call, you also have 1 call per instance.
So it should be very simple, use a using () { } block in the toplevel of your OperationContract method.
Ok, here is the class with thread-safe static method that provides single ObjectContext entity model object for any WCF service call and automatically dispose it at the end of call:
public static class EntityModelProvider
{
private static readonly Dictionary<OperationContext, MyEntityModel> _entityModels = new Dictionary<OperationContext, MyEntityModel>();
public static MyEntityModel GetEntityModel()
{
if (OperationContext.Current == null)
throw new Exception("OperationContext is missing");
lock (_entityModels)
{
if (!_entityModels.ContainsKey(OperationContext.Current))
{
_entityModels[OperationContext.Current] = new MyEntityModel();
OperationContext.Current.OperationCompleted += delegate
{
lock (_entityModels)
{
_entityModels[OperationContext.Current].Dispose();
_entityModels.Remove(OperationContext.Current);
}
};
}
return _entityModels[OperationContext.Current];
}
}
For your service, you can specify a service behaviour which details the instance mode of the service:
[ServiceBehaviour(InstanceContextMode = InstanceContextMode.PerCall)]
public class MyService : IMyService {
ObjectContext context;
}
A cleaner way may be to use the ServiceAuthenticationManager, which is in .NET 4.
http://msdn.microsoft.com/en-us/library/system.servicemodel.serviceauthenticationmanager.aspx
From the Authenticate method (which you'll override) you can access the Message object and set properties on it. I've not used it in anger, so YMMV :)
EDIT the problem with this approach is that you don't have the Username and Password, so will still need the custom Authentication.
Take a look at the UsernameSecurityTokenAuthenticator...
http://msdn.microsoft.com/en-us/library/system.identitymodel.selectors.usernamesecuritytokenauthenticator(v=vs.90).aspx
Further reading from my research:
Answers to this question gives some hints about how to use it:
Custom WCF authentication with System.ServiceModel.ServiceAuthenticationManager?
If you can read (or ignore) the Russian, I found useful hints at:
http://www.sql.ru/forum/actualthread.aspx?tid=799046
This rather good CodeProject article goes further (encryption and compression as well as custom authorization)
http://www.codeproject.com/Articles/165844/WCF-Client-Server-Application-with-Custom-Authenti
Why not pass in the context into your CustomValidator when you assign to the service - store your object context in your validator, and in the overridden validation method new it up if need be. Then you still have access to the object through the Services CutomUserNameValidator ..
Depending on what you are asking :
Create your separate ObjectContext class as a dynamic object - add that as a property to you CustomValidator.
In your custom Validator - you can now check if the object is disposed and create the object again if need be.
Otherwise if this is not what you are after - just store the Context in the validator - you still have access on server side.
The code here is just generalized idea - I am just posting it as a frame of reference so you can have an idea of what I talking about.
public DynamicObjectContextObjectClass
{
ObjectContext internalObjectContext;
}
public class ServiceUserNamePasswordValidator : UserNamePasswordValidator
{
public DynamicObjectContextObjectClass dynamiccontext;
public override void Validate(string userName, string password)
{
if(dynamiccontext.internalObjectContext.isdisposed)
{
dynamiccontext.internalObjectContext = new Context;
}
try
{
if (string.IsNullOrEmpty(userName) || password == null)
{
//throw new ArgumentNullException();
throw new FaultException("Username cannot be null or empty; Password cannot be null and should not be empty");
}
}
}
}

Implementing Singleton across requests to HttpHandler

I am attempting to create a singleton service that is used to process incoming requests to an HttpHandler. At the moment the service is being instantiated on every request. I make a call to the static class that holds an instance of the service, implemented as a singleton as below:
public static class ServerApplication {
static Service instance = null;
static readonly object padlock = new object();
/// <summary>
/// Service singleton.
/// </summary>
public static Service Service {
get {
lock (padlock) {
if (instance == null) {
instance = new Service();
}
return instance;
}
}
}
And access it using a call as below in the HttpHandler:
ServerApplication.Service.Process(request);
I have set a breakpoint on the instance = new Service(); line and with multiple requests the
breakpoint is triggered per request.
My aim is a service that exists across requests as it loads and caches lots of data from files and databases that is reused with most requests.
Can anyone see what is going wrong?
A couple of things:
If it's a multiprocessor box, technically, you should mark the shared service instance with the "volatile" keyword or use a call to MemoryBarrier (see http://blogs.msdn.com/brada/archive/2004/05/12/130935.aspx). You didn't specify architecture, so hard to say if this is really the issue, but better safe than sorry.
You should implement a double-check lock (eg, check for null both before and after acquiring the lock on "padlock"). This way you're doing a much cheaper comparison instead of acquiring a lock on all the subsequent reads.
That should cover you on the concurrency fronts. It's also possible (though less likely) that your AppDomain is being unloaded between requests (ie, you wrote a file inside the web directory causing ASP.NET to think your app is stale), which would cause the statics to be reset.
HTTP is designed to make several concurrent connections, I don't know that you'd want to break this, unless you make very few connections on page loads. That said, perhaps you could keep the HttpHandler in the Session?
Generally speaking, if you want a singleton - cannot see if its necessary i usually implement it this way: http://www.vikingworks.dk/page/Creating-a-Singleton-Pattern-i-C.aspx

Categories