I recently switched some AJAX queries to use ashx files instead of aspx, having discovered that Response.End is no longer in vogue. In the case I'm looking at now, the submission of a purchase order is handled by the ashx. The user clicks the Submit button on the PO and the ashx file records the time and the user in a database table. An object with the current user's data (including their primary key) is stored in the Session and is recorded there by a custom Profile Provider. I have added IReadOnlySessionState in order to be able to access the Session, but it appears that, unless another .net page has been accessed, the Profile Provider doesn't run and the Session has no values. (verified by stepping through the code.)
I tried IRequiresSessionState, but the same results.
I'm assuming that the System.Web.UI.Page HttpHandler instantiates the custom Profile if it hasn't been already and that I'll need to add that to my custom HttpHandler.
I looked briefly at HttpModules, but I don't think that's what I want because they load for each request.
What is the value of HttpContext.Current.Profile? The Profile property is populated during the AcquireRequestState stage of the Request lifecycle by the built in HttpModule ProfileModule.
There is great info here http://odetocode.com/articles/440.aspx on how the internals work.
Related
I am working on a multi developer web app. I am trying to sort out an issue that came up with one dev not being able to access session variables in his custom classes.
I synced his changes, and the same issue happens on my dev machine. (I.e., its not IIS specific)
Upon further inspection, the session object completely disappears (there is no session, nto even an empty session with a session ID. Any attempt to access HttpContext.Current.Session throws a null reference exception.
Running the page code again after setting some session variables, shows the variable are all saved and acting normal in the session that I can access from the page itself . (The session object behaves as it normally does)
So to be clear, in the same process, debugging from page through to custom class, the session object is accessible in the page, not existing in custom class, and when returning to the page, its available again.
I have tried setting just a normal string session var to eliminate possible problems with my variable (object) stored in the session. The same issue persists.
Any ideas?
Alrighty then.. always helps to bounce it off a wall :-)
We were using a textbox autocomplete extender that was referencing our own custom webmethod, (inside our app in a custom class). It seem the webmethod decoration forced it to operate stateless... hence no session.
We moved this webmethod decorated function into our page-codebehind page, and it now calls the other custom classes "with" session object availability.
Actually i want to send a object from controller action to webform load method.
I don't like to use Session or QueryString.
As I understand your question, you want to use some object that you create in the MVC request in a later Webforms request.
In addition to using a Session variable or the QueryString, you can also store the object data in a cookie and retrieve it in the WebForm.
Each of the options has its advantages:
Session-variable: Object can be stored as is, no need to reload, e.g. from database. Decreases scalability because server memory is used per user.
Query String: data is visible, only viable for short strings.
Cookie: data is stored on the client and can be tampered with. Transferred between server and client several times. Size restrictions apply. Cookies might be disabled.
Handling a huge amount of data:
In the comments you mention that the data is huge. Therefore, I'd suggest to store the data once it is generated on the MVC part, e.g. in the database (or even the file system) and just transfer the id that is needed to retrieve the data on the Webforms end via one of the methods above. You might also need to erase the prepared data once they have been used or after some time in order to clean up left-over data.
Recreating the data in the Webform:
If you do not want to store the data in some kind of cache (database, file, server cache) and if you can recreate the data in the Webforms request (obviously you are able to create the huge amount of data in the MVC request), you can also choose to transfer only that bit of data to the Webform that is required to recreate the data. Bad in sense of performance, but good in that the user is always presented up-to-date information and you don't have to clean the cache if the data is not needed anymore.
In order to be able to share the functionality to create the data between the MVC controller and the Webform, you should move that to a dedicated class that is used in both web front ends.
If both the pages are in different domains -
From the MVC controller action make a HttpWebRequest to the webform page, in the Request body of HttpWebRequest send the data you want to send. On the retrieving side you can use Request object and read the data.
If both the pages are in same domain -
You can use Cache (server side), Cookies (client side), Hiddenfields (for Form Post from MVC controller to ASPX Page)
I don't know how (and this is what I want to know).
I have an HttpHandler which implements IReadonlySessionState marker interface. My idea was not to update the Session variables in the handler. But we accidentally call code which is saving data in a session and somehow the session is saving data.
Then we moved our project to Azure and decided to use Azure Cache. Because of the change of SessionStateProvider, now the session is not saving the data (and it should not because the handler is readonly).
I want to know if there is any bug in default session provider which is causing the session to be persisted even when manipulated in Readonly Http Handler.
IReadOnlySessionState tells the session state provider that this handler doesn't need to save session state.
The handler is not obligated to refuse to save anything.
The default handler doesn't have any reason to not save session state (since it's in-process), so it always saves.
I'm trying to prevent output cached page from being ejected from my asp.net output cache unless another one can replace it. In other words, if a page has expired (based on Duration property of OutputCache profile) but accessing the page now results in an exception, I just want to serve the old, outdated page. I was hoping the custom cache providers in ASP.NET 4 would help my situation but they don't get far enough up the pipeline.
Here's what I know:
System.Web.Caching.OutputCache is really hard to read through
A custom cache provider hooks in after all dependencies and is fed a CachedVary object.
The utcExpiry date passed into the custom cache provider's Add and Set methods is just DateTime.Max
The actual expiration of the cache item happens higher up in the pipeline
Even for expired items, the custom cache provider's Get method is still called. It returns the cached CachedVary object and then my controller's action method is called. After this, the Add method is called with the CachedVary object and Set method is passed an actual cached page data object.
Can someone with more experience hacking outputcache steer my in a direction here? Can I accomplish what I'm looking for with ASP.NET outputcache? Must I roll my own?
i ended up blogging about how i accomplished this here: http://statichippo.com/blog/archive/2011/09/25/graceful-degradation-via-asp-net-outputcacheprovider.aspx
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;
}