HTTPHandler : IRequiresSessionState halts execution of pages - asp.net

I have ASHX HTTPHandler which implements IRequiresSessionState. When I call this handler, and call aspx page of same application in another window, aspx page does not start processing until ashx page finishes processing. Even call to same ashx page from two different windows show that page which gets called first executes and then the next one.
When I do not implement IRequiresSessionState, pages load asynchronously without waiting for other page to complete.
This could be serious bottleneck for end user, who would like to work in multiple windows.
Session have user specific data. If above approach does not work, need alternative way to store user specific data for session, which can be used in HTTPHandler.
Other Info:
- Am using ashx handler to process and send file which needs Session internally.

session state access requires that the aspx pages, and handler, run sequentially. Each page/handler may read from and write to the session state. To handle this without creating any errors in the session state .net will only run one at a time.
As Darin suggested, running with the read only session state will improve the situation. Asp.net will allow multiple handlers to run at the same time if they require only read access. However, the page will require write access to the session, so no handlers will run when the aspx page itself is running. This is the standard multi-reader single-writer locking pattern. You can have multiple readers at the same time, but only a single writer.
The only way to make this work is to have the handlers not require session state so that they run at the same time that t he aspx page is running.
You can work around this, by finding another way to store this data instead of using session state. You can implement your own shared cache/data structure, but you will need to provide similar locking (multi-reader/single writer) for that structure as well.

In addition to the points made by #Mike about IRequiresSessionState forcing each "user" (session) to only process one request at a time, there is good for another reason to want this.
Suppose you have an ajax service (implemented with a Generic Handler - *.ashx) which performs an "update" for a specific user based on the posted data. Let's say the update is heavy (around 250ms) and involves a "read/merge/write" process to the database (again data is isolated to an individual user). The client (app, website etc.) however can perform multiple calls in quick succession which the server has no control of.
By implementing IRequiresSessionState (simply including it as an inteface to your Generic Handler) ASP.NET will ensure that for a given user/session requests are handled serially. Multiple users however can still make calls to the update in parallel. This can allow us to avoid the "lost update problem" as the 2nd request won't retrieve a copy of the data until the 1st request has finished updating it.
public class SaveDataHandler : IHttpHandler, IRequiresSessionState
{
public void ProcessRequest(HttpContext context)
{
// Read request parameters
// Read database (user specific data)
// Process
// Write back to database (user specific data)
}
public bool IsReusable => false;
}

Related

Could we save and load the ASP.NET InProc session (hence releasing the lock) around long running external calls

In ASP.NET when you have 2 AJAX requests on the same web page calling 2 controller actions, if they use the session then one will lock out the other
You can get readonly access to the session which can help, but not if you want to write to the session
You can override the session class, e.g.
https://www.red-gate.com/simple-talk/dotnet/asp-net/single-asp-net-client-makes-concurrent-requests-writeable-session-variables/, but this doesn't really help for the same reason
In my case the controller action calls a long running external server call. While this is happening ideally the session would be released and saved back to memory, and then when the call is finished the session would be read back in, possibly being blocked if another call is still proceeding
NB Whether or not the external server call is called in an async manner makes no difference unfortunately
Is there any way of doing this? Possibly by overriding some internal classes?

Calling method Asyncronously from aspx

i am using .net4.0 framework
i am working on Web Project using c#
i want to make some request which will populate some items in cache beforehand.
Ex.
user comes to the home page of application.
[ i will write some code in Home Page(.ASPX) which will call some method which will read some files from disk and put them into cache though i don't need this cache on home page... at this point as reading files from disk is going to be somewhat lengthy operation... i would to load home page completely without waiting for response from method(which is going to read files from disk)]
Something like
function page_load{
CacheGenerator.CreateCache();//this is going to be heavy operation..i don't want to wait for this operation to complete
repose.write("Hello world:); // this statement should run moment after above function is called
}
and one more thing can we do this without using threading.
Anything asynchronous is "using threading" in one way or another.
More importantly, you should not start any async operation from a page. The page only exists in memory for the duration of the request. Your async operation may complete after the page no longer exists in memory.
You may be able to use the Task class to start an async operation from the Application_Start event in global.asax.

.NET page caching but still receive query string

Is it possible to cache a page render on an iis web server, but still receive and write query string values (that don't affect output) to the database? So that the page render does not have to wait for the database trip to execute in order to serve the page? If possible, how do I implement?
For example, we track various affiliate and search marketing data via query strings, and in the master page code behind, we write the given query string data to the database. The output of the page doesn't change at all for the user (however we may set a cookie based off the qs parameter).
My understanding is that the page render has to wait for the database trip to fully execute in order to render the page. Is that even true?
Yes in general though it can depend on how one handles the caching.
First, you should move that tracking stuff to where it belongs -- a HttpModule. Page need not concern itself. Second, what you probably want to look into is some sort of fire and forget service call or message queueing. This makes the database write a non-blocking operation rather than a blocking operation.
Some options for making the operation non-blocking:
if you are actually writing to a web service, there is an underappreciated [OperationContract(IsOneWay = true)] decoration. Tells the generated proxy to fire and forget the call, will not wait for a response.
Another option would be to use the Asynchronous ADO.NET bits, especially BeginExecuteNonQuery. If you don't handle the callback this should just execute off your thread.
You could always just spawn a thread and deal with it in a non-blocking manner yourself. Just be real careful about handling errors on this thread -- unhandled exceptions will take out the app domain.

ASP.NET concurrency

I have an ASP.NET application that starts a long running operation during the Event Handler phase in the ASP.NET Page life cycle. This occurs when the end user pushes a button a bunch of queries are made to a database, a bunch of maps are generated, and then a movie is made from jpeg images of the maps. This process can take over a minute to complete.
Here's a link to the application
http://maxim.ucsd.edu/mapmaker/cbeo.aspx
I've tried using a thread from the threadpool, creating and launching my own thread and using AsyncCallback framework. The problem is that the new thread is run under a different userid. I assume the main thread is run under ASPNET, the new thread is run under AD\MAXIM$ where MAXIM is the hostname. I know this because there is an error when it tries to connect to the database.
Why is the new thread under a different userid?
If I can figure out the userid issue, what I'd like to do is check if the movie making process has finished by examining a Session variable in a Page_Load method, then add a link to the page to access the movie.
Does anyone have any good examples of using concurrency in a ASP.NET application that uses or creates threads in an EventHandler callback?
Thanks,
Matt
Did you read this?: http://msdn.microsoft.com/en-us/magazine/cc163725.aspx
Quoting one relevant portion from that link (you should read the whole thing):
A final point to keep in mind as you build asynchronous pages is that you should not launch asynchronous operations that borrow from the same thread pool that ASP.NET uses.
Not addressing the specific problem you asked about, but this is likely to come up soon:
At what point is this video used?
If it's displayed in the page or downloaded by the user, what does the generated html that the browser uses to get the video look like? The browser has to call that video somewhere using a separate http request, and you might do better by creating a separate http handler (*.ashx file) to handle that request, and just writing the url for that handler in your page.
If it's for storage or view elsewhere you should consider just saving the information needed to create the video at this point and deferring the actual work until the video is finally requested.
The problem is that the new thread is run under a different userid. I assume the main thread is run under ASPNET, the new thread is run under AD\MAXIM$ where MAXIM is the hostname.
ASPNET is a local account, when the request travels over a network it will use the computer's credentials (AD\MAXIM$).
What may be happening, is that you're running under impersonation in the request - and without in the ThreadPool. If that's the case, you might be able to store the current WindowsIdentity for the request, and then impersonate that identity in the ThreadPool.
Or, just let the ThreadPool hit the DB with Sql Authentication (username and password).

Custom Windows Workflow activity that executes an asynchronous operation - redone using generic service

I am writing a custom Windows Workflow Foundation activity, that starts some process asynchronously, and then should wake up when an async event arrives.
All the samples I’ve found (e.g. this one by Kirk Evans) involve a custom workflow service, that does most of the work, and then posts an event to the activity-created queue. The main reason for that seems to be that the only method to post an event [that works from a non-WF thread] is WorkflowInstance.EnqueueItem, and the activities don’t have access to workflow instances, so they can't post events (from non-WF thread where I receive the result of async operation).
I don't like this design, as this splits functionality into two pieces, and requires adding a service to a host when a new activity type is added. Ugly.
So I wrote the following generic service that I call from the activity’s async event handler, and that can reused by various async activities (error handling omitted):
class WorkflowEnqueuerService : WorkflowRuntimeService
{
public void EnqueueItem(Guid workflowInstanceId, IComparable queueId, object item)
{
this.Runtime.GetWorkflow(workflowInstanceId).EnqueueItem(queueId, item, null, null);
}
}
Now in the activity code, I can obtain and store a reference to this service, start my async operation, an when it completes, use this service to post an event to my queue. The benefits of this - I keep all the activity-specific code inside activity, and I don't have to add new services for each activity types.
But seeing the official and internet samples doing it will specialized non-reusable services, I would like to check if this approach is OK, or I’m creating some problems here?
There is a potential problem here with regard to workflow persistence.
If you create long running worklfows that are persisted in a database to the runtime will be able to restart these workflows are not reloaded into memory until there is some external event that reloads them. As there they are responsible for triggering the event themselves but cannot until they are reloaded. And we have a catch 22 :-(
The proper way to do this is using an external service. And while this might feel like dividing the code into two places it really isn't. The reason is that the workflow is responsible for the big picture, IE what should be done. And the runtime service is responsible for the actual implementation or how it should be done. That way you can change the how without changing the why and when part.
A followup - regardless of all the reasons, why it "should be done" using a service, this will be directly supported by .NET 4.0, which provides a clean way for an activity to start an asynchronous work, while suspending the persistence of the activity.
See
http://msdn.microsoft.com/en-us/library/system.activities.codeactivitycontext.setupasyncoperationblock(VS.100).aspx
for details.

Resources