Can an ASP.NET Handler (.ashx) that implements IRequiresSessionState be reusable or will it persist its relationship with the first Session used?
Yes, it can be reusable.
Callers pass session state inside the HttpContext when they invoke the ProcessRequest method. Method parameters are only available within the scope of each method invocation, not across multiple invocations on different threads.
Ultimately, it depends on your ProcessRequest implementation, but unless you do something very unusual (like store the session in a member variable and then use it later during the method call), each request will use the correct session even though they're sharing the handler instance.
Related
I want to use SessionScope from Google Guice and before the session is destroyed I want to get data from SessionScoped object.
I try to use HttpSessionListener.sessionDestroyed() but at this moment i don't have session attributes.
Is any another method to check when the session attrubutes was destroyed?
The HttpSessionListener.sessionDestroyed(HttpSessionEvent se) parameter gives you access to the HttpSession using HttpSessionEvent.getSession().
You can then access the session attributes in the usual way.
Just be aware that there is often no associated HttpRequest when this is called.
The Working with the BeginMethod/EndMethod Pattern section of Using an Asynchronous Controller in ASP.NET MVC refers to a Sync() method. It is not linked and I am having trouble finding documentation on it through google searches since sync is too common a term. Can someone point me in the write direction?
To make sure that you have access to
the HttpContext.Current instance and
to avoid the race condition, you can
restore HttpContext.Current by calling
Sync() from the callback method.
When you spawn asynchronous operations by calling BeginXyz / EndXyz methods from within your controller action, the threads handling the asynchronous response are not under the control of ASP.NET. As such, you can't touch HttpContext, the controller instance, or any other shared state from within those threads. Calling the Sync() method basically synchronizes access to the request; it restores HttpContext.Current and grants you access to touch HttpContext, the controller, etc., but only for the duration of the Sync() call. The RegisterTask() extension method from MVC Futures attempts to make this a bit easier, as you basically pass it delegates to the target Begin and End methods, and the RegisterTask() helper will ensure that the End thread executes within an appropriate synchronization context.
If you're spawning asynchronous operations by calling XyzAsync / XyzCompleted methods from within your controller action, you don't have to worry about this, as the completed handler automatically runs within a synchronization context.
It's a method of the AsyncManager class. http://msdn.microsoft.com/en-us/library/system.web.mvc.async.asyncmanager.sync.aspx
I have written an HttpModule that adds a response filter. The filter is capturing page output and storing it in a session variable.
I am able to access HttpContext.Current.Session in my HttpModule.
The HttpModule is handling the PostAcquireRequestState event.
I am still able to access HttpContext.Current.Session in the PostAcquireRequestState event.
In the PostAcquireRequestState event, I add a custom stream that inherits from Stream to Response.Filter
HttpContext.Current.Session is null when accessed from the Stream.Write method.
Everything worked fine when using an InProc SessionState. However, I now must use StateServer. Using StateServer, the code is now broken.
Any ideas?
Have you tried passing the session-object from your HttpModule to your filters constructor and that way hold a reference?
Normally i would never rely on accessing HttpContext.Current in my filters, but pass the necessary values via constructor or setting some Properties before assigning it to Response.Filter. It decouples things and make it more maintainable.
I have a web application the relies heavily on web services. Everything with the services is done asynchronously and with AddOnPreRequestHandlerExecuteAsync. Anyhow, most of my calls work just fine, but some are returning from their asynchronous service calls to find a null HttpContext.Current.Response/Request object in the endprerequest, which of course errors the instant I try to use either. Both objects (Response and Request are available/not null on beginprerequest of failing calls and work in the endprerequest of other calls).
Anyone run into similar, or have a guess as to what might be the problem?
Update: Seem to have found a solution, if I create a variable for the HttpApplication on Init(of the HttpModule this all occurs in) the HttpContext can be accessed from that variable.
Update: Passing either HttpApplication or HttpContext.Current on the begin function has the same issue. When passed as part of the "State" of the asynchronous call, they end up null in the end function, even though they are valid in the begin function.
Update: I've added some logging and found that the Asynchronous call I am making is returning correctly, the results are there, the callback function is invoked properly.
I suspect I know the problem you're running into. The answer, almost certainly, is to replace usage of HttpWebRequest with WebClient, and to use the *Async methods of WebClient.
Here's the long explanation: there are two totally different Async programming models: the IAsyncResult Async Pattern and the Event-based Asynchronous Pattern. The IAsyncResult pattern uses BeginXXX and EndXXX methods, uses IAsyncResult instances, uses delegates for callbacks, and supports waiting for completion. The Event-based pattern uses XXXAsync methods to initiate async actions, uses XXXCompleted events instead of callbacks to handle completion, and (this is important to your case) transfers thread-specific context into every callback event handler.
In other words, if you put your callback code inside a XXXCompleted event handler (like WebClient.DownloadStringCompleted), then HttpContext.Current will be populated correctly.
If, however, you use a BeginXXX method (like HttpWebRequest.BeginGetResponse) and a delegate callback, your callback will be executed in the context of a thread that does not guarantee to have the right ASP.NET context attached.
Generally, .NET Framework library classes either use one async pattern or the other. Typically, the lower-level classes (e.g. HttpWebRequest) will use the IAsyncResult pattern, while the higher-level classes (e.g. WebClient) will use the event-based pattern. Some oddball classes (e.g. auto-generated .NET Remoting proxies) will support both patterns, but that's a rarity.
So if it's easy to do, I'd suggest moving to WebClient and event handlers instead of HttpWebRequest and callback delegates. This should solve your problem. If switching to WebClient is too hard, comment and I can probably suggest some more obscure alternatives.
Seem to have found a solution, if I create a variable for the HttpApplication on Init(of the HttpModule this all occurs in) the HttpContext can be accessed from that variable.
When writing a http handler/module, there is an interface member to implement called - bool IsReusable.
What is the significance of this member? If I set it to false (or true), what does this mean for the rest of the web app?
The normal entry point for a handler is the ProcessRequest method. However you may have code in the class constructor which puts together some instance values which are expensive to build.
If you specify Reusable to be true the application can cache the instance and reuse it in another request by simply calling its ProcessRequest method again and again, without having to reconstruct it each time.
The application will instantiate as many of these handlers as are need to handle the current load.
The downside is that if the number of instances needed is larger than the instances currently present, they cause more memory to be used. Conversely they can also reduce apparent memory uses since their instance value will survive GC cycles and do not need to be frequently re-allocated.
Another caveat is you need to be sure that at the end of the ProcessRequest execution the object state is as you would want for another request to reuse the object.
Further to AnthonyWJones's answer, if your HTTP handler returns true for IsReusable then you should ensure that it is fully thread-safe.
There's nothing in the documentation to indicate that reusable handlers can't be reused concurrently, although the current Microsoft implementations only appear to reuse them consecutively. But, at least in theory, a single handler instance could be reused simultaneously by multiple requests, so you shouldn't rely on any data which might be modified by other concurrent threads.
If you don't store any state in that instance (i.e.: you don't have any fields (aka "class variables")) then you should be safe reusing it.
It's by default false to be on the safe side.