I have a WebForm with many controls, including a large number of grids. I added some callback functions on these grids to refresh their DataSource and to update some global variables in a public static class after each refresh.
Normally I would add some method calls in the PageLoadComplete Event Handler, but the callbacks get raised after that. I also tried using the OnPrerender, OnPrerenderComplete and OnSaveStateComplete method overrides, but these don't seem to work with callbacks. (I can't use the OnUnload override since I need to use the Request object.)
And here is the Actual Question:
Is there any event handler I can use? Or can I create an event and raise it after everything else has finished?
I want it to execute as the last step in every callback/post-back of any kind (but before page unload so i can still use the Response and Request objects).
The grids are DevExpress's ASPxGridViews.
UPDATE
After searching for a while, I found out that the PreRender event is fired during async Postbacks of asp:UpdatePanels but not during DevExpress's Callbacks (it is normal behavior).
So, what would really help is finding/creating an event which I can use. I'm also thinking of grabbing the data I want from the Request Object during the PageLoad execution and using them later at Unload.
What are the pros and cons of each approach? Is there anything important that I need to know before making a decision, or is there anything I might be overlooking? I'm concerned about going with the second option since I'd have to declare some class variables and I feel like there are already too many of them.
Given the fact that the PreRender,PreRenderComplete and SaveStateComplete method overrides aren't executed during DevExpress's CallBacks, I found an alternative way to use the OnUnload Method.
First on the Page_Load Method, After some checks using the Request Object, and if the conditions are met, a Handler is attached to the Unload Event, and using a Lambda expression arguments are passed to this sub.
Protected Sub Page_Load(sender As Object, e As System.EventArgs) Handles Me.Load
'//Some Code//
If Request.Params("__CALLBACKPARAM").Contains("REFRESH") Then
AddHandler Me.Unload, Sub() Page_Unload(sender,e,Request)
End If
End Sub
This way the Page_Unload sub will be executed only when needed, with all the arguments it needs, while successfully avoiding the addition of more global variables.
Protected Sub Page_Unload(sender As Object, e as System.EventArgs, req As HttpRequest)
'//Some Code//
End Sub
The only problem is that i cant remove this handler, but it is no big deal, since on every request to the server the objects are recreated.
Related
Partial Class Preferences_MyPreferences
Inherits System.Web.UI.Page
Dim userID As String = Session("UserID")
This is just a page in asp.net. I want to be able to grab the Session("UserID") but every time I try, I get this error:
Session state can only be used when enableSessionState is set to true, either in a configuration file or in the Page directive. Please also make sure that System.Web.SessionStateModule or a custom session state module is included in the \\ section in the application configuration.
If I put that Dim userID inside say the Page_Load Event, then it works fine. Why does it have to be inside an event? I want to dim it once, and use it throughout the page.
Consider wrapping your call to the Session in a property in your code behind?
Public ReadOnly Property UserID() As String
Get
Return Session("UserID")
End Get
End Property
If you declare it as you have there, the variable is initialized and the session variable is expected to be ready for usage, but it is too early in the page life cycle to allow that. The preferred method would be as #p.campbell has suggested and wrap it in a Property or similar method. To answer the question though, the exception is generated because you are attempting to use session before it is available.
You need to read up on ASP.NET Page Lifecycles. The Session object doesn't become available until a certain point in the page lifecycle; if you want to grab the UserID once, you need to do it after the session becomes available.
The reason it doesn't work in your example is that the constructor for your Preferences_MyPreferences page is executed before the request object is available to the page. You should instead load it during the Page_Init or Page_Load event.
In doing a lot of ASP.NET pages (.NET 2.0), my codebehind is typically packed with event handlers on page objects. GridView_RowCommand, Button_Click, etc. All the usual suspects. One thing all EventHandler derived things have in common is that their first argument is an object, typically labeled "sender".
In ASP.NET codebehind, I really don't see the point of it. If I have GridCustomers_RowCommand and I need to do something to GridCustomers, I can just access it from the codebehind instead of worrying about casting sender to a gridview and then working with it.
I feel like I must be missing a very important design consideration here. Am I doing something stinky to my code? I kind of can see that using direct references this way is falling prey to global objects, but that's just how ASP.NET works! What am I not seeing here? Is there some superb book or tutorial that shows how to use ASP.NET the "right way?" The clean, agile, "real coder" way?
You might have one event handler for DRY coding, yet 20 things that use that event, for example:
protected void AddClass(object sender, EventArgs e) {
((WebControl)sender).CssClass += " myNewClass";
}
In this case you're writing the code once, but it can be used by many WebControls (this is an example, the point is not specific to WebControls at all).
Disclaimer: Do I use sender every day? no not even close, is it useful? yes it can be :)
Yes, if you have an event handler that is called by several controls, and you need to know which control called the event handler.
It seems like a backwards way to do it, but it can eliminate repeated code if the event handler is the same for most controls, except for a few minor differences.
That said, I've only ever seen it in real code once, and I thought it hurt readability. I like to have one event handler per control/event.
The sender parameter of an event signature is provided so that you can establish the context of the event.
This is useful say, if you have several nested controls in an ASP.NET control hierarchy, whereby they are all executing the same event handler for a specific event, the sender parameter allows you to distinguish between the different controls.
Sometimes, the subclassed EventArgs parameter provides the context for you in a neater fashion, sender is still useful for abstract event handlers.
I need to find a way to detect if a request is a callback when the Application_BeginRequest method is called.
Sub Application_BeginRequest(ByVal sender As Object, ByVal e As EventArgs)<br />
Dim _isCallBack As Boolean = False
' Code to set _isCallBack is True or False Here
If Not _isCallBack Then
'... Some Code
End If
End Sub
I need to know what to replace "[Code to set _isCallBack is True or False Here]" with.
This may help you:
http://msdn.microsoft.com/en-us/magazine/cc163941.aspx
Search for the word __CALLBACKID:
To determine the callback mode, the ASP.NET runtime looks for a __CALLBACKID entry in the Request collection. If such an entry is found, the runtime concludes that a callback invocation is being made.
We needed to do this from within an app_code file where access to the Page.xxxx objects was not available. This is the code I ended up using:
If Not IsNothing(HttpContext.Current.Request("__CALLBACKID")) Then
'The request is a callback
Else
'The request is not a callback
End If
Maybe not the prettiest solution, but it does the job. We were using Array.IndexOf for a while, but it seems that sometimes that form parameter arrives back as lowercase parameter (not sure why or how), and Array.IndexOf is a case sensitive search.
Be careful looking for these kinds of __XXXX request keys. I remember reading somewhere that it's not a good idea to "shortcut" to these elements since their names could change in some future version of .net. Just keep that in mind!
I needed something similar and, following on Dean L's answer, figured .NET itself must know what to do. Looking in the HttpResponse.Redirect method with Reflector, you see code like this:
Page handler = Context.Handler as Page;
if (handler != null && handler.IsCallback)
{
//Code...
}
Seems to work fine in Global.asax.
Depends on the context of your question. I see you are talking about ASP.NET in the tags, using VB.NET. You can probably use:
If Not Request.IsPostback Then
' Your code here
End If
This has been bugging me for a while but when I databind a control using with a Session variable as the parameter which has not been initialized there is an exception thrown which I can't seem to catch anywhere.
Ideally if the session varaible is not set I would just like to redirect but I can't seem to figure out where I need to check for this instance.
You must check the session object on page_init event.
Check it in your page load.
Sub Page_Load()
if Not Page.ispostback()
if session("Value") <>"" then
me.hiddenfield.value = Session("ValueName")
Else
Response.redirect("PAge.aspx")
End if
End if
End Sub
I tend to add some hidden fields as sessions eventually time out
then make the datasource use the hidden control for its reference
I've been given the thrilling task of re-writing our exception handling system. Whilst I will state that handling exceptions from an application-wide point of view isn't something we want, typically it's unavoidable when our team are understaffed for the sheer amount of work we need to push out the door, so please, no flaming the globalised solution to exception handling here :)
I've had a good hunt to see what common solutions exist. At the moment we use Global.asax with the Application_Error event to do Server.GetLastError() which is placed in Session state then a redirect is called to another page where the session data is then retrieved and output in a human readable format. The redirect also calls a sproc which will carefully audit the error information which is a) e-mailed to the developers and b) viewed from a web page only viewable by developers.
The new way I've seen of doing things is using the IHttpModule interface using a class in App_Code to do something along these lines (this is my quick implementation)
Imports Microsoft.VisualBasic
Public Class ErrorModule : Implements IHttpModule
Public Sub Dispose() Implements System.Web.IHttpModule.Dispose
' Not used
End Sub
Public Sub Init(ByVal context As System.Web.HttpApplication) Implements System.Web.IHttpModule.Init
AddHandler context.Error, AddressOf context_Error
End Sub
Public Sub context_Error(ByVal sender As Object, ByVal e As EventArgs)
Dim ex As Exception = HttpContext.Current.Server.GetLastError
' do something with the error
' call the stored procedure
' redirect the user to the error page
HttpContext.Current.Server.ClearError()
HttpContext.Current.Response.Redirect("index.htm")
End Sub
End Class
My question is, what is the benefit of this solution over using Global.asax events? Additionally, what is the best way to hand the data to an error page?
EDIT: The code above does work by the way ;)
EDIT: Also, how does the HttpModule work behind the scenes? Does it just register the Error event to that particular function on application start?
UPDATE:
Upon much further investigation it seems grabbing session data is really, really messy when it comes to using IHttpModule interface. I don't think MS have matured HttpModule enough for it to be used in our particular scenario - until there are events specific to session data it's too dangerous for us to use.
Using a module has the advantage of being easily removable, all you need to do to disable it is to remove it from <httpModules> in your config.
As far as your data goes, try going with Server.Transfer or Server.RewritePath - that will keep all the current data (including the last server error).
If for some reason it clears the last error, you can save the error to HttpContext.Items before the transfer/rewrite and then retrieve it afterwards.
Edit: In response to your edit, an IHttpModule attaches to any appropriate events in it's IHttpModule.Init implementation.
HttpModule basically does the same thing as Global.asax. It's designed as a more reusable and self-contained module for event handling.