What does AutoEventWireUp page property mean? - asp.net

I don't understand what the AutoEventWireUp page property is responsible for.
I've read through this article, but even that I don't understand.

When a Page is requested, it raises various events which are considered to be part of it's lifecycle. I keep the visual representation created by Peter Bromberg handy with me.
The AutoEventWireUp property when True, automatically wires up some of these built-in events in the Page life cycle to their handlers. This means that you do not need to explicitly attach these events (using the Handles keyword, for instance, in VB).
Examples of these built-in events would be Page_Init and Page_Load.
If you set AutoEventWireUp to True and provide explicit wiring up of the EventHandlers, you will find them being executed twice! This is one reason why Visual Studio keeps this attribute set to false by default.
Edit: (after Chester89's comment)
It is useful to note that the default value of the AutoEventWireUp attribute of the Page is true, while the default value of the AutoEventWireUp property of the Page class is false

To add to previous answers; the automatic hooks are applied from TemplateControl.HookUpAutomaticHandlers. This method calls into TemplateControl.GetDelegateInformationWithNoAssert which contains which methods are considered as event handlers.
These are, in System.Web, version 2.0:
On all classes deriving from Page: Page_PreInit, Page_PreLoad, Page_LoadComplete, Page_PreRenderComplete, Page_InitComplete, Page_SaveStateComplete.
On all classes deriving from TemplateControl: Page_Init, Page_Load, Page_DataBind, Page_PreRender, Page_UnLoad, Page_Error.`
Transaction support for all classes deriving from TemplateControl:
Page_AbortTransaction, or if it does not exist, OnTransactionAbort
Page_CommitTransaction, or if it does not exist, OnTransactionCommit
System.Web, version 4.0, introduced a Page_PreRenderCompleteAsync for all classes derived from Page. That method, if present, will be registered using Page.RegisterAsyncTask and executed automatically "just before the PreRenderComplete event" (source: Page.ExecuteRegisteredAsyncTasks). This method seems very undocumented which suggest that it would be prefered to just call Page.RegisterAsyncTask with your own method instead.

As mentioned in the article, if you have AutoEventWireUp turned on, asp.net will automatically recognize you have a method with the page_load syntax and call it automatically:
private void Page_Load(object sender, System.EventArgs e)
{
}
This gives you a cleaner code behind at the expense of some (very) small overhead. Notice that if you don't specify it you must explicitly tell asp.net you want to handle the page load event:
this.Load += new System.EventHandler(this.Page_Load);
Note that this applies to other events in the page, as it uses a naming convention as Page_Event.

Related

Performance-impact of empty Page_Load() methods

When adding a new page or user control to an ASP.NET webforms application, the code-behind class contains an empty Page_Load() event handler:
public partial class Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
}
I have an existing web app, where many pages and controls still contain these empty event handlers (they are not used).
Question: Is there any performance impact due to these empty event handlers and should they therefore be removed from all pages and controls?
Please note: I'm not mainly (or not only) concerned about any runtime-overhead, due to the empty event handler being called. I also wonder about any overhead while the page (markup) is JIT-compiled (because the event handlers have to be wired up to the events - probably using some reflection code).
Update: there was no real answer so far, so I can't accept any of them.
AutoEventWireup is not done at the compile time. When it set to true, the runtime has to look for each of the page event handlers using Delegate.CreateDelegate method for this. Here is a great article which describes this behaviour: Inside AutoEventWireup.
There is a similar question here: What is the performance cost of autoeventwireup?
While the stack frame must be adjusted to enter and leave your method (and doing nothing) as opposed to simply calling the base implementation (in this case System.Web.UI.Page
), the performance impact is incredibly small and most likely unmeasurable so you should be fine.
I'm fairly certain Page_Load occurs whether it's there or not. Much like PreRender occurs, or Page_Init.
Removing it will do nothing for performance.

When in the page lifecycle is the ViewState collection available?

When exactly is the view state accessible from the .Viewstate property of a control? From my observations, the closest event is on the Page.PreLoad event (at Page.InitComplete, Viewstate is still unavailable).
However, for controls that implement the IPostBackEventHandler interface the LoadValue() method is called and the .Viewstate collection is available (this occurs after Page.InitComplete and before Page.PreLoad).
Does anyone know of any additional events that can be used to know when Viewstate is available? Or any tricks (not excluding reflection on private/protected/internal members) that can be used to know if the Viewstate has loaded or not?
When exactly is the view state accessible from the .Viewstate property of a control?
After the LoadViewState method has been run.
Normally this means after the Init phase and before the Load and Handlers (e.g. "OnClick") phase. But ViewState is really complicated, so I highly recommend reading this excellent article to truly understand ViewState.
Since you can override the LoadViewState method, this makes a good place to put any of the kind of tricks you mention:
protected override void LoadViewState(object savedState)
{
base.LoadViewState(savedState);
this.ViewStateLoaded = true; // or you could fire an event or something
UpdatePanelVisibility();
}
Of course, this does assume that you are using your own implementations of controls, which is not always the case.

Why do WebControl events have the prefix of "On"?

I'm trying to fully understand the WebForm event model (not the page lifecycle, but how the events are wired up when specified declaratively in the .aspx or .ascx files.
Take the Button control for example. It has a Click event that you can wire to in the code-behind, but it has an "OnClick" event in the .aspx/.ascx file.
I used the .NET Reflector and the Button control has a PROTECTED OnClick method, but that shouldn't be available to be assigned by the .aspx/.ascx. Unless I'm missing something.
Does anyone know why the "On" prefix is added?
Just to clarify a bit: I understand the naming convention works. I'd like to know how the "OnClick" in the .aspx/.ascx gets translated into .Click += new EventHandler(blahName); I.e. if I create a ControlChanged EventHandler, do I need to do anything special to get the OnControlChanged to show up validly in the .aspx/.ascx file?
Those store references to the delegates that the calling code will be wiring up using events; in order to distinguish between the event itself, and the delegate.
It's more than a naming convention because events in user controls automatically get the "On" prefix in the declarative syntax.
For example, I have a UserControl that declares a ProjectSelected event. To add a handler declaratively, I set the OnProjectSelected attribute.
UserControl:
public event EventHandler<ProjectSelectedEventArgs> ProjectSelected;
Adding handler declaratively:
<user:ProjectList id="uxProjectList" runat="server"
OnProjectSelected="uxProjectList_ProjectSelected" />
Adding handler in code behind:
uxProjectList.ProjectSelected += uxProjectList_ProjectSelected;
This confused the hell out of me twice, once when I couldn't figure out why the event wasn't available declaratively, and again when I named the event "OnProjectSelected" and the attribute became "OnOnProjectSelected".
It's just a naming convention used when raising events. OnSomethingHappened ... OnClick, OnChange, OnClose. I don't think there is anything magical or sinister, it's just a convention.
Semantically it is basically an old throwback to VB traditions where event listeners were generally called OnWhatever. Old habits die hard.

When extending a asp.net web control, at which event should additional web controls be injected?

I'm trying to avoid a composite control or using and ASCX by extending an existing control. However, I'm having trouble with getting the controls added to the inherited control and keep their view-state/post-back integrity. Whenever I add the controls during pre-render, the controls show up, but the post-back throws a viewstate exception. I tried adding them both there and during LoadViewState (which of course was a long-shot silly). Init is not available from the control which I'm extending.
The exception is
Sys.WebForms.PageRequestManagerServerErrorException:
Failed to load viewsstate. The control
tree into which viewstate is being
loaded must match the control tree
that was used to save viewstate during
the previous request. For example,
when adding controls dynamically, the
controls added during a post-back must
match the type and position of the
controls added during the initial
request
Actually, microsoft says you should override the CreateChildControls method.
You can call the base class method before or after you add the controls, I'm not sure if there is a convention there.
protected override void CreateChildControls(){
Controls.Add(someControl);
base.CreateChildControls();
}
Hope that helps!
You should add them in OnInit or in CreateChildControls. Anyway, to avoid having troubles with ViewState, read this GREAT article. Possibly, sample "4. Initializing child controls programmatically" is your case.

Dynamically added controls in Asp.Net

I'm trying to wrap my head around asp.net. I have a background as a long time php developer, but I'm now facing the task of learning asp.net and I'm having some trouble with it. It might very well be because I'm trying to force the framework into something it is not intended for - so I'd like to learn how to do it "the right way". :-)
My problem is how to add controls to a page programmatically at runtime. As far as I can figure out you need to create the controls at page_init as they otherwise disappears at the next PostBack. But many times I'm facing the problem that I don't know which controls to add in page_init as it is dependent on values from at previous PostBack.
A simple scenario could be a form with a dropdown control added in the designer. The dropdown is set to AutoPostBack. When the PostBack occur I need to render one or more controls denepending on the selected value from the dropdown control and preferably have those controls act as if they had been added by the design (as in "when posted back, behave "properly").
Am I going down the wrong path here?
I agree with the other points made here "If you can get out of creating controls dynamically, then do so..." (by #Jesper Blad Jenson aka) but here is a trick I worked out with dynamically created controls in the past.
The problem becomes chicken and the egg. You need your ViewState to create the control tree and you need your control tree created to get at your ViewState. Well, that's almost correct. There is a way to get at your ViewState values just before the rest of the tree is populated. That is by overriding LoadViewState(...) and SaveViewState(...).
In SaveViewState store the control you wish to create:
protected override object SaveViewState()
{
object[] myState = new object[2];
myState[0] = base.SaveViewState();
myState[1] = controlPickerDropDown.SelectedValue;
return myState
}
When the framework calls your "LoadViewState" override you'll get back the exact object you returned from "SaveViewState":
protected override void LoadViewState(object savedState)
{
object[] myState = (object[])savedState;
// Here is the trick, use the value you saved here to create your control tree.
CreateControlBasedOnDropDownValue(myState[1]);
// Call the base method to ensure everything works correctly.
base.LoadViewState(myState[0]);
}
I've used this successfully to create ASP.Net pages where a DataSet was serialised to the ViewState to store changes to an entire grid of data allowing the user to make multiple edits with PostBacks and finally commit all their changes in a single "Save" operation.
You must add your control inside OnInit event and viewstate will be preserved. Don't use if(ispostback), because controls must be added every time, event in postback!
(De)Serialization of viewstate happens after OnInit and before OnLoad, so your viewstate persistence provider will see dynamically added controls if they are added in OnInit.
But in scenario you're describing, probably multiview or simple hide/show (visible property) will be better solution.
It's because in OnInit event, when you must read dropdown and add new controls, viewstate isn't read (deserialized) yet and you don't know what did user choose! (you can do request.form(), but that feels kinda wrong)
After having wrestled with this problem for at while I have come up with these groundrules which seems to work, but YMMV.
Use declarative controls whenever possible
Use databinding where possible
Understand how ViewState works
The Visibilty property can go a long way
If you must use add controls in an event handler use Aydsman's tip and recreate the controls in an overridden LoadViewState.
TRULY Understanding ViewState is a must-read.
Understanding Dynamic Controls By Example shows some techniques on how to use databinding instead of dynamic controls.
TRULY Understanding Dynamic Controls also clarifies techniques which can be used to avoid dynamic controls.
Hope this helps others with same problems.
If you truly need to use dynamic controls, the following should work:
In OnInit, recreate the exact same control hierarchy that was on the page when the previous request was fulfilled. (If this isn't the initial request, of course)
After OnInit, the framework will load the viewstate from the previous request and all your controls should be in a stable state now.
In OnLoad, remove the controls that are not required and add the necessary ones. You will also have to somehow save the current control tree at this point, to be used in the first step during the following request. You could use a session variable that dictates how the dynamic control tree was created. I even stored the whole Controls collection in the session once (put aside your pitchforks, it was just for a demo).
Re-adding the "stale" controls that you will not need and will be removed at OnLoad anyway seems a bit quirky, but Asp.Net was not really designed with dynamic control creation in mind. If the exact same control hierarchy is not preserved during viewstate loading, all kinds of hard-to find bugs begin lurking in the page, because states of older controls are loaded into newly added ones.
Read up on Asp.Net page life cycle and especially on how the viewstate works and it will become clear.
Edit: This is a very good article about how viewstate behaves and what you should consider while dealing with dynamic controls: <Link>
Well. If you can get out of creating controls dynamicly, then do so - otherwise, what i whould do is to use Page_Load instead of Page_Init, but instead of placing stuff inside the If Not IsPostBack, then set i just directly in the method.
Ah, that's the problem with the leaky abstraction of ASP.NET web forms.
Maybe you'll be interested to look at ASP.NET MVC, which was used for the creation of this stackoverflow.com web site? That should be an easier fit for you, coming from a PHP (thus, pedal-to-the-metal when it comes to HTML and Javascript) background.
I think the answer here is in the MultiView control, so that for example the dropdown switches between different views in the multi-view.
You can probably even data-bind the current view property of the multiview to the value of the dropdown!
The only correct answer was given by Aydsman. LoadViewState is the only place to add dynamic controls where their viewstate values will be restored when recreated and you can access the viewstate in order to determine which controls to add.
I ran across this in the book "Pro ASP.NET 3.5 in C# 2008" under the section Dynamic Control Creation:
If you need to re-create a control multiple times, you should perform the control creation in the Page.Load event handler. This has the additional benefit of allowing you to use view state with your dynamic control. Even though view state is normally restored before the Page.Load event, if you create a control in the handler for the Page.Load event, ASP.NET will apply any view state information that it has after the Page.Load event handler ends. This process is automatic.
I have not tested this, but you might look into it.

Resources