Trying to access the HttpContext.Current in a method call back so can I modify a Session variable, however I receive the exception that HttpContext.Current is null. The callback method is fired asynchronously, when the _anAgent object triggers it.
I'm still unsure of the solution to this after viewing similar questions on SO.
A simplified version of my code looks like so:
public partial class Index : System.Web.UI.Page
protected void Page_Load()
{
// aCallback is an Action<string>, triggered when a callback is received
_anAgent = new WorkAgent(...,
aCallback: Callback);
...
HttpContext.Current.Session["str_var"] = _someStrVariable;
}
protected void SendData() // Called on button click
{
...
var some_str_variable = HttpContext.Current.Session["str_var"];
// The agent sends a message to another server and waits for a call back
// which triggers a method, asynchronously.
_anAgent.DispatchMessage(some_str_variable, some_string_event)
}
// This method is triggered by the _webAgent
protected void Callback(string aStr)
{
// ** This culprit throws the null exception **
HttpContext.Current.Session["str_var"] = aStr;
}
[WebMethod(EnableSession = true)]
public static string GetSessionVar()
{
return HttpContext.Current.Session["str_var"]
}
}
Not sure if necessary but my WorkAgent class looks like so:
public class WorkAgent
{
public Action<string> OnCallbackReceived { get; private set; }
public WorkAgent(...,
Action<string> aCallback = null)
{
...
OnCallbackReceived = aCallback;
}
...
// This method is triggered when a response is received from another server
public BackendReceived(...)
{
...
OnCallbackReceived(some_string);
}
}
What happens in the code:
Clicking a button calls the SendData() method, inside this the _webAgent dispatches a message to another server and waits for reply (in the mean time the user can still interact with this page and refer to the same SessionID). Once received it calls the BackendReceived() method which, back in the .aspx.cs page calls the Callback() method.
Question:
When the WorkAgent triggers the Callback() method it tries to access HttpContext.Current which is null. Why is that the case when if I continue on, ignoring the exception, I can still obtain the same SessionID and the Session variable using the ajax returned GetSessionVar() method.
Should I be enabling the aspNetCompatibilityEnabled setting?Should I be creating some sort of asynchronous module handler? Is this related to Integrated/Classic mode?
Here's a class-based solution that is working for simple cases so far in MVC5 (MVC6 supports a DI-based context).
using System.Threading;
using System.Web;
namespace SomeNamespace.Server.ServerCommon.Utility
{
/// <summary>
/// Preserve HttpContext.Current across async/await calls.
/// Usage: Set it at beginning of request and clear at end of request.
/// </summary>
static public class HttpContextProvider
{
/// <summary>
/// Property to help ensure a non-null HttpContext.Current.
/// Accessing the property will also set the original HttpContext.Current if it was null.
/// </summary>
static public HttpContext Current => HttpContext.Current ?? (HttpContext.Current = __httpContextAsyncLocal?.Value);
/// <summary>
/// MVC5 does not preserve HttpContext across async/await calls. This can be used as a fallback when it is null.
/// It is initialzed/cleared within BeginRequest()/EndRequest()
/// MVC6 may have resolved this issue since constructor DI can pass in an HttpContextAccessor.
/// </summary>
static private AsyncLocal<HttpContext> __httpContextAsyncLocal = new AsyncLocal<HttpContext>();
/// <summary>
/// Make the current HttpContext.Current available across async/await boundaries.
/// </summary>
static public void OnBeginRequest()
{
__httpContextAsyncLocal.Value = HttpContext.Current;
}
/// <summary>
/// Stops referencing the current httpcontext
/// </summary>
static public void OnEndRequest()
{
__httpContextAsyncLocal.Value = null;
}
}
}
To use it can hook in from Global.asax.cs:
public MvcApplication() // constructor
{
PreRequestHandlerExecute += new EventHandler(OnPreRequestHandlerExecute);
EndRequest += new EventHandler(OnEndRequest);
}
protected void OnPreRequestHandlerExecute(object sender, EventArgs e)
{
HttpContextProvider.OnBeginRequest(); // preserves HttpContext.Current for use across async/await boundaries.
}
protected void OnEndRequest(object sender, EventArgs e)
{
HttpContextProvider.OnEndRequest();
}
Then can use this in place of HttpContext.Current:
HttpContextProvider.Current
There may be issues as I currently do not understand this related answer. Please comment.
Reference: AsyncLocal (requires .NET 4.6)
When using threads or an async function, HttpContext.Current is not available.
Try using:
HttpContext current;
if(HttpContext != null && HttpContext.Current != null)
{
current = HttpContext.Current;
}
else
{
current = this.CurrentContext;
//**OR** current = threadInstance.CurrentContext;
}
Once you set current with a proper instance, the rest of your code is independent, whether called from a thread or directly from a WebRequest.
Please see the following article for an explanation on why the Session variable is null, and possible work arounds
http://adventuresdotnet.blogspot.com/2010/10/httpcontextcurrent-and-threads-with.html
quoted from the from the article;
the current HttpContext is actually in thread-local storage, which explains why child threads don’t have access to it
And as a proposed work around the author says
pass a reference to it in your child thread. Include a reference to HttpContext in the “state” object of your callback method, and then you can store it to HttpContext.Current on that thread
Related
I develop download manager application that consists of two parts: 1) Duplex WCF service that performs downloading and sends downloading status data to client in real-time. 2) WPF Client that receives downloading status data from the service and displays in DataGrid. In my duplex WCF service there is a callback interface
[ServiceContract(CallbackContract = typeof(IDownloadManagerServiceCalback))]
public interface IDownloadManagerServiceCalback
{
/// <summary>
/// Returns changed downloading status to client.
/// </summary>
/// <returns>Downloading which has changed status</returns>
[OperationContract(IsOneWay = true)]
void UpdateSelectedDownload(DownloadStatus p_SelectedDownload);
}
On the client side I implement this interface:
class CallbackHandler : IDownloadManagerServiceCallback
{
/// <summary>
/// "Download status changed" event.
/// </summary>
public event EventHandler<DownloadStatusChangedEventArgs> DownloadStatusChanged;
public async Task UpdateSelectedDownload(DownloadStatus p_UpdatedDownload)
{
await Task.Run(() =>
{
// If handler was subscribed to event:
if (DownloadStatusChanged != null)
{
DownloadStatus updatedDownload = p_UpdatedDownload;
DownloadStatusChangedEventArgs updatedDownloadArgs = new DownloadStatusChangedEventArgs();
updatedDownloadArgs.Download = updatedDownload;
DownloadStatusChanged(this, updatedDownloadArgs);
}
});
}
}
When I build the solution I have the following error (text of error message i translate from Russian to English because my Visual Studio 2013 is Russianize):
DownloadManager_Client.CallbackHandler doesn’t implement member "DownloadManager_Client.DownloadManager_ServiceReference.IDownloadManagerServiceCallback.UpdateSelectedDownload(DownloadManager_Client.DownloadManager_ServiceReference.DownloadStatus)". "DownloadManager_Client.CallbackHandler.UpdateSelectedDownload(DownloadManager_Client.DownloadManager_ServiceReference.DownloadStatus)" can’t be implemented "DownloadManager_Client.DownloadManager_ServiceReference.IDownloadManagerServiceCallback.UpdateSelectedDownload(DownloadManager_Client.DownloadManager_ServiceReference.DownloadStatus)", because it doesn’t contain appropriate returned “void” type.
Here DownloadManager_Client is the name of WPF client project, DownloadManager_ServiceReference is the name of service reference to WCF service in the client project. How can I correct this error?
The interface should be defined as returning Task not void since your implementation is an async method returning a Task.
EDIT: You are in a pickle because you want to use async which require a Task to be returned however your method is marked as IsOneWay = true - you can't have both. Either IsOneWay = false and keep the async nature or keep one-way but remove the async.
Example 1 - Async method
[ServiceContract(CallbackContract = typeof(IDownloadManagerServiceCalback))]
public interface IDownloadManagerServiceCalback
{
/// <summary>
/// Returns changed downloading status to client.
/// </summary>
/// <returns>Downloading which has changed status</returns>
[OperationContract(IsOneWay = false)]
Task UpdateSelectedDownload(DownloadStatus p_SelectedDownload);
}
Then keep your original implementation returning Task
Example 2 - One-way method
[ServiceContract(CallbackContract = typeof(IDownloadManagerServiceCalback))]
public interface IDownloadManagerServiceCalback
{
/// <summary>
/// Returns changed downloading status to client.
/// </summary>
/// <returns>Downloading which has changed status</returns>
[OperationContract(IsOneWay = true)]
void UpdateSelectedDownload(DownloadStatus p_SelectedDownload);
}
In your implementation remove any await; async; tasks.
General
Async WCF methods should return Task or Task < T >. The only time you have an async void is during an event handler which is not applicable here.
As a general rule with async methods - avoid async void like the plague because an exception thrown in a try catch inside such a method can not be caught by a regular try-catch. The only exception (no pun intended is during event handlers).
Async void methods have different error-handling semantics. When an exception is thrown out of an async Task or async Task method, that exception is captured and placed on the Task object. With async void methods, there is no Task object, so any exceptions thrown out of an async void method will be raised directly on the SynchronizationContext that was active when the async void method started. More...
Would you like to know more?
Best Practices in Asynchronous Programming
So I'm working on a client that consumes a web service. I used the WSDL and XSD files from the service to generate the proxy class, and all of the synchronous functions work fine. However, given their synchronous nature, making any of the calls causes the UI to stop responding until the call is finished. Classic reason for using async methods, right?
Problem is, I'm still in school for my degree and know little about asynchronous programming. I've tried to read up on it online (my employer even has a Books 24x7 subscription) but I'm having a hard time grasping how I should make the calls and how to handle the response. Here's what I have:
/// <remarks/>
[System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://localhost:8080/getRecords", RequestNamespace="http://www.<redacted>.com/ws/schemas", ResponseNamespace="http://www.<redacted>.com/ws/schemas", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]
[return: System.Xml.Serialization.XmlArrayAttribute("records", Form=System.Xml.Schema.XmlSchemaForm.Unqualified, IsNullable=true)]
[return: System.Xml.Serialization.XmlArrayItemAttribute("list", Form=System.Xml.Schema.XmlSchemaForm.Unqualified, IsNullable=false)]
public record[] getRecords([System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, IsNullable=true)] string username, [System.Xml.Serialization.XmlArrayAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, IsNullable=true)] [System.Xml.Serialization.XmlArrayItemAttribute("list", Form=System.Xml.Schema.XmlSchemaForm.Unqualified, DataType="integer", IsNullable=false)] string[] ids) {
object[] results = this.Invoke("getRecords", new object[] {
username,
ids});
return ((record[])(results[0]));
}
/// <remarks/>
public void getRecordsAsync(string username, string[] ids) {
this.getRecordsAsync(username, ids, null);
}
/// <remarks/>
public void getRecordsAsync(string username, string[] ids, object userState) {
if ((this.getRecordsOperationCompleted == null)) {
this.getRecordsOperationCompleted = new System.Threading.SendOrPostCallback(this.OngetRecordsOperationCompleted);
}
this.InvokeAsync("getRecords", new object[] {
username,
ids}, this.getRecordsOperationCompleted, userState);
}
private void OngetRecordsOperationCompleted(object arg) {
if ((this.getRecordsCompleted != null)) {
System.Web.Services.Protocols.InvokeCompletedEventArgs invokeArgs = ((System.Web.Services.Protocols.InvokeCompletedEventArgs)(arg));
this.getRecordsCompleted(this, new getRecordsCompletedEventArgs(invokeArgs.Results, invokeArgs.Error, invokeArgs.Cancelled, invokeArgs.UserState));
}
}
There's also this:
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.1")]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
public partial class getRecordsCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs {
private object[] results;
internal getRecordsCompletedEventArgs(object[] results, System.Exception exception, bool cancelled, object userState) :
base(exception, cancelled, userState) {
this.results = results;
}
/// <remarks/>
public record[] Result {
get {
this.RaiseExceptionIfNecessary();
return ((record[])(this.results[0]));
}
}
}
and this:
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.1")]
public delegate void getRecordsCompletedEventHandler(object sender, getRecordsCompletedEventArgs e);
I chose this example because the synchronous call has a return type and the async does not--at least not in the function call itself. I understand that the getRecordsCompletedEventArgs class has the proper return type, and that that is how I will get the data back from the call. What I can't seem to figure out is how to actually do that.
Let's say that I replace my current call to getRecords with getRecordsAsync:
How do I set up the client to respond when the async call completes? I need to drop the XML into a file using a LINQ procedure I've already written, I need to log the operation's success or failure, and I need to notify the user that the operation completed.
How can I ensure that making the call actually happens asynchronously? I remember reading at one point that simply invoking an asynchronous SOAP method doesn't actually happen asynchronously with regard to the current thread unless you do something else first. Any tips?
Are there any other major considerations that I'm missing? (Such as: "If you forget to do this, it'll blow up your program!")
These are all questions that I haven't been able to find convincingly firm answers to so far. Thank you in advance for any help you all can offer.
You need to handle the getRecordsCompleted event on the proxy which was auto-generated for you, like so:
private void Button_Click(object sender, EventArgs e)
{
var proxy = new WebServiceProxy();
// Tell the proxy object that when the web service
// call completes we want it to invoke our custom
// handler which will process the result for us.
proxy.getRecordsCompleted += this.HandleGetRecordsCompleted;
// Make the async call. The UI thread will not wait for
// the web service call to complete. This method will
// return almost immediately while the web service
// call is happening in the background.
// Think of it as "scheduling" a web service
// call as opposed to actually waiting for it
// to finish before this method can progress.
proxy.getRecordsAsync("USERNAME", new[] { 1, 2, 3, 4 });
this.Button.Enabled = false;
}
/// <summary>
/// Handler for when the web service call returns.
/// </summary>
private void HandleGetRecordsCompleted(object sender, getRecordsCompletedEventArgs e)
{
if (e.Error != null)
{
MessageBox.Show(e.Error.ToString());
}
else
{
record[] result = e.Result;
// Run your LINQ code on the result here.
}
this.Button.Enabled = true;
}
If you use an auto-generated method on the proxy which ends with Async, the call will be made asynchronously - and that's it. What it sounds to me that you need to prove is that the call is non-blocking (that is, the UI thread does not have to wait for it to complete), and that's a bit tricky as you can't really inject custom logic into the auto-generated code.
A synchronous call made from a UI thread will block the UI and your application will become unresponsive. If that's not happening and your UI still responds to button clicks, keyboard events etc while the web service is running, you can be sure that the call is non-blocking. Obviously this will be tricky to prove if your web service call returns quickly.
You're not showing any client code so it's hard to say if you're missing anything.
For point 1
I think you are missing something on the code you are showing. Maybe the definition of getRecordsCompleted? It may be of type event I suppose, so you can attach a handler of type getRecordsCompletedEventHandler to your event so you can do something with the result of your asynchronous call.
Let's say your client proxy class name is RecordCleint
RecordClient client = new RecordClient();
//attaching an event handler
client.getRecordsCompleted += onGetRecordsCompleted;
//calling the web service asynchronously
client.getRecordsAsync("username", [ids]);
//definition of onGetRecordsCompleted of type getRecordsCompletedEventHandler
private void onGetRecordsCompleted(object sender, getRecordsCompletedEventArgs e)
{
if(e.Error != null)
{
record[] data = e.Result;
//do something with your data
}
else
{
//handle error
}
}
[Edit]
For point 2
If you are generating your client proxy with svcutil (Visual Studio > add Service reference) you can trust in it :) or you can watch the involved Threads with the Visual Studio Thread window.
For point 3
You might have some Thread synchronization problems, for example if you update some UI components in another Thread than the UI thread where they belong to. So you may need to do some extra work (dispatch).
Windows Forms (BeginInvoke or Dispatcher)
WPF (Dispatcher)
I am working on a WPF application in which a user may initiate a process by pushing a button on the UI. The user may then be prompted with a sequence of actions that they must carry out to complete the process. The view is responsible for passing the initial request to initiate the process down to the domain. The view is also responsible for DISPLAYING the steps that the user must perform to complete the process.
The domain, on the other hand, is squarely response for working out WHAT steps must be carried out by the user. The domain is also capable of detecting when a user has completed the requested step.
If a user initiates a process, and that process requires them to perform some physical action, then I would like a box to pop-up with a message describing what they must do. When the action has been completed, it is detected by the domain, and the window should automatically close.
Passing requests from the View down to the Domain is simple. I do this using the wpf ICommand pattern. It is passing information back the other way that I am finding challenging. I am aware of bindings and the INotifyProperyChanged interface, but I do not feel that this is a good fit for what I am trying to do.
So, here is my initial attempt...
This interface is implemented by the View and consumed by the Domain. It allows the domain to communicate with the user;
public interface IUserRequestMedium
{
/// <summary>
/// Ask the user to perform an action. User does
/// not need to provide any feedback via the user
/// interface, since it is possible for the
/// application to detect when the action has been
/// carried out by the user. The dialog will be closed
/// when either the requested action has been detected,
/// or the user aborts.
/// </summary>
/// <param name="message">
/// Request to be displayed to the user.
/// </param>
/// <param name="userAbortCallback">
/// Callback invoked by the view when the user cancels
/// the request.
/// </param>
/// <param name="actionDetectedCallback">
/// Callback invoked by the domain to confirm the
/// that the requested action has been completed.
/// </param>
void AskUserToPerformDetectableAction(
string message, Action userAbortCallback,
out Action actionDetectedCallback);
}
Here is the View code-behind. Some of this code was taken from tutorials (and subsequently mangled) on the web. It's not working, but I hopefully it communicates my intent.
public partial class MainWindow : Window, IUserRequestMedium
{
// Constructor and other stuff...
public void AskUserToPerformDetectableAction(
string message, Action userAbortCallback,
out Action actionDetectedCallback)
{
Action closeWindow;
NewWindowThread(
() => new ActionRequestBox(message, userAbortCallback),
out closeWindow);
actionDetectedCallback = closeWindow;
}
private Window newWindow;
private void NewWindowThread(
Func<Window> construction,
out Action closeWindow)
{
var thread = new Thread(() =>
{
newWindow = construction();
newWindow.Show();
newWindow.Closed += (sender, e) => newWindow.Dispatcher.InvokeShutdown();
System.Windows.Threading.Dispatcher.Run();
});
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
Window rememberedWindow = newWindow;
closeWindow = () =>
{
if (rememberedWindow != null)
rememberedWindow.Dispatcher.Invoke(
System.Windows.Threading.DispatcherPriority.Normal,
new Action(Close));
};
}
}
And here's a usage example from the domain;
public class SomeDomainClass
{
IUserRequestMedium userRequestMedium; // assume this has been assigned in constructor
private Action notifyUserOfActionDetected;
public void PerformSomeProcess()
{
bool processCannotBeCompletedWithoutPowerCycle = ...; // some logic
if (processCannotBeCompletedWithoutPowerCycle)
{
userRequestMedium.AskUserToPerformDetectableAction(
"Please cycle the power on the external device",
CancelProcess,
out notifyUserOfActionDetected);
}
}
public void CancelProcess()
{
// User doesn't want to perform the required action
// so process must be aborted...
}
private void OnPowerCycleDetected()
{
notifyUserOfActionDetected();
}
}
How can I make this work? It is the cross-threading aspect that I am getting caught on. I have not been successful in making the window automatically close when the action is detected by the domain.
Or, taking a step backward, is there a better approach to solve this problem?
After learning a little about Dispatcher.Invoke, this is what I ended up with. So far it seems to be working pretty well.
private Window activeRequestBox;
// invoked on domain thread
public void AskUserToPerformDetectableAction(
string message, Action userAbortCallback,
out Action actionDetectedCallback)
{
OpenDetectableActionRequestBox(message, userAbortCallback);
actionDetectedCallback = CloseRequestBox;
}
private void OpenDetectableActionRequestBox(
string message, Action userAbortCallback)
{
Action openWindow =
() =>
{
activeRequestBox = new DetectableActionRequestBox(
message, userAbortCallback);
activeRequestBox.Closed += RequestBoxClosedHandler;
activeRequestBox.Show();
};
this.Dispatcher.Invoke(openWindow);
}
// invoked on request box thread
private void RequestBoxClosedHandler(object sender, EventArgs e)
{
activeRequestBox = null;
}
// invoked on domain thread
private void CloseRequestBox()
{
if (activeRequestBox != null)
{
Action closeWindow =
() => activeRequestBox.Close();
this.Dispatcher.Invoke(closeWindow);
}
}
I use the following, static class to access the data context in my application
public static class DataContext
{
internal const string _contextDataKey = "dataContext";
/// <summary>
/// Returns a unique data context that lives for the duration of the request, which can be from ASP.NET or a WCF service
/// </summary>
/// <returns>The entity data model context for the current request</returns>
public static EntityDataModelContext GetDataContext()
{
IPersistanceContainer state;
if (HttpContext.Current != null)
{
state = new AspNetPersistanceContainer();
}
else if (OperationContext.Current != null)
{
state = new WcfPersistanceContainer();
}
else
{
state = new StaticPersistanceContainer(); // this container is thread-unsafe.
}
EntityDataModelContext edm = state.Get<EntityDataModelContext>(_contextDataKey);
if (edm == null)
{
edm = new EntityDataModelContext();
state.Store(_contextDataKey, edm);
}
return edm;
}
}
Forget about the other containers, which are for WCF and Console application simple-tests respectively, here's the ASP.NET container:
internal class AspNetPersistanceContainer : IPersistanceContainer
{
public T Get<T>(string key) where T : class
{
if (HttpContext.Current.Items.Contains(key))
return (T)HttpContext.Current.Items[key];
return null;
}
public void Store(string key, object value)
{
HttpContext.Current.Items[key] = value;
}
}
When I need to access the context I just invoke DataContext.GetDataContext() and do my DB-accessing, I never add any using statements.
If I add a using statement, the context is good for one use, and the next time I try to use it, it's disposed of. Raising an exception.
If I don't, like right now, it makes me kind of unhappy, I feel like it's not the right thing to do either, not disposing of it.
So I was wondering what would be the correct thing to do here.
Is this design flawed, and should I abandon it altogether?
Should I just figure out a way to re-create the context whenever it's disposed of?
Should I just leave the design as is, and that's fine?
Maybe the design is "fine enough", are there any books that you'd recommend I read on the subject? I feel like my skills on back-end architecture are rather on the lacking side.
In an asp.net application one solution can be like this :
Create your context when a request begins
Dispose it when the request ends
Here's an article that discuss this approach (for NHibernate session management but it's almost the same for EF )
I am experimenting with creating my own custom HTTP Context:
CustomHttpContext : HttpContextBase
{
public override HttpRequestBase Request { }
}
One thing i can't figure out is how to initialize the base class with
System.Web.HttpContext.Current
Does anyone have any ideas how i can initialise the custom context first with the Current Http then override certain Methods/Properties to serve my own purpose?
The simple answer is no, it's not possible. Also note that HttpContext does not inherit from HttpContextBase, instead, they both implement IServiceProvider. Finally, HttpContext is sealed, suggesting that the authors did not want people to do anything other than consume this class.
As you are no doubt annoyed by HttpContextBase has a parameterless constructor so does not even give you the option of instantiating it from the current request and response like HttpContext!
Let's use a 'decompiler' to take a look at the implementation of HttpContext.Current:
// System.Web.HttpContext
/// <summary>Gets or sets the <see cref="T:System.Web.HttpContext" /> object for the current HTTP request.</summary>
/// <returns>The <see cref="T:System.Web.HttpContext" /> for the current HTTP request.</returns>
public static HttpContext Current
{
get
{
return ContextBase.Current as HttpContext;
}
set
{
ContextBase.Current = value;
}
}
If we take a look at ContextBase.Current (from System.Web.Hosting.ContextBase):
// System.Web.Hosting.ContextBase
internal static object Current
{
get
{
return CallContext.HostContext;
}
[SecurityPermission(SecurityAction.Demand, Unrestricted = true)]
set
{
CallContext.HostContext = value;
}
}
and CallContext (in System.Runtime.Messaging):
// System.Runtime.Remoting.Messaging.CallContext
/// <summary>Gets or sets the host context associated with the current thread.</summary>
/// <returns>The host context associated with the current thread.</returns>
/// <exception cref="T:System.Security.SecurityException">The immediate caller does not have infrastructure permission. </exception>
public static object HostContext
{
[SecurityCritical]
get
{
IllogicalCallContext illogicalCallContext = Thread.CurrentThread.GetIllogicalCallContext();
object hostContext = illogicalCallContext.HostContext;
if (hostContext == null)
{
LogicalCallContext logicalCallContext = CallContext.GetLogicalCallContext();
hostContext = logicalCallContext.HostContext;
}
return hostContext;
}
[SecurityCritical]
set
{
if (value is ILogicalThreadAffinative)
{
IllogicalCallContext illogicalCallContext = Thread.CurrentThread.GetIllogicalCallContext();
illogicalCallContext.HostContext = null;
LogicalCallContext logicalCallContext = CallContext.GetLogicalCallContext();
logicalCallContext.HostContext = value;
return;
}
LogicalCallContext logicalCallContext2 = CallContext.GetLogicalCallContext();
logicalCallContext2.HostContext = null;
IllogicalCallContext illogicalCallContext2 = Thread.CurrentThread.GetIllogicalCallContext();
illogicalCallContext2.HostContext = value;
}
}
We start to get a feel for how the HttpContext is being retrieved. It's being packaged in with the thread the current user started when they visted the website (which makes perfect sense!). Delving further we can see it also gets recreated per request (see below).
We can also see, at the interface layer, HttpContext.Current cannot be changed to point at your own HttpContext as the property is not virtual. It also uses many BCL classes that are private or internal so you can't simply copy most of the implementation.
What would be easier, and also less prone to any other issues would be to simply wrap HttpContext with your own CustomContext object. You could simply wrap HttpContext.Current in a BaseContext property, then have your own properties on the class (and use whatever session, database, or request based state storage mechanism you want to store and retrieve your own properties).
Personally, I'd use my own class for storing my own information, as it belongs to my application and user etc and isn't really anything to do with the http pipeline or request/response processing.
See also:
ASP.NET MVC : How to create own HttpContext
How is HttpContext being maintained over request-response
Just to add on a bit to dash's answer, you can also use the [ThreadStatic] attribute with some static property. Initialize it on BeginRequest, either by using global.cs or by writing your own HttpModule/HttpHandler.
How to create a web module:
http://msdn.microsoft.com/en-us/library/ms227673(v=vs.100).aspx
Thread static:
http://msdn.microsoft.com/en-us/library/system.threadstaticattribute.aspx