At what point should I call base methods of ASP.NET events? - asp.net

In ASP.NET, if I override a page lifecycle event, should I call its base method before or after doing my work? Does it even matter?
protected override void OnPreRender(EventArgs e)
{
// My code goes here
base.OnPreRender(e);
// Or here
}

Yes you should care. Let's say for a moment that you need to insert a new base class in all of those pages. To me it's easier to just go ahead and call the base methods than have to do a lot of refactoring later.
Then again, maybe you don't need to do that.
EDIT
Based on the edit to the question here's some more info:
Yes, you should care. Sometimes you want the base classes method to fire before yours (in case of constructors), and sometimes you want it to fire after yours (destructors).
It may mean the difference between whether a property or object is available or not at the time your code gets to it.

The "OnEvent" methods in the asp.net event model merely wrap the actual event calls (in this case, the "PreRender" event). So the only thing you need to decide is "do I need to call the event before or after I do my work"?

The answer is, it depends on what the code is doing as to if it should go before or after.
As another said, if it is constructor stuff it should go before. Destructor should go after. To give a more concrete example, if you have code that processes the page and loads content, fills drop downs, and fills labels and such then you would want that to happen before any code that looks at what is pre-populated and determines visibility or business rule logic that has to do with the data on the page.

I think it's a good idea to call them just on principle. It may be true that in the framework version you're currently using there's no code in the base class methods, but who knows about future versions. Also, separation of concerns would dictate that code you write that derives from Page not assume the Page class doesn't do anything but raise the PreRender event in its OnPreRender method.

There is no single rule. I can provide you an example. My ASP.net webapp uses a NHibernate transaction opened by the master page and commited/roll-backed by it when the page ends.
Well, I MUST initialize the transaction as early as possible in the OnInit method (Master has no OnPreInit like Page), otherwise user controls cannot access the transaction until Page.Load.
The same rule applies for commit. Controls may want to update objects in the last phases of their life-cycles, then I must close the transaction as latest as possible in the Unload method, or even in the disposer!
So... in my case...
void OnInit(EventArgs e) {
transaction = session.BeginTransaction();
base.OnInit(e);
}
void OnUnload(EventArgs e) {
base.OnUnload(e);
try{
transaction.Commit();
} catch {}
}
void OnError(EventArgs e) {
base.OnError();
transaction.Rollback();
}
I would suggest you a general rule: if your page's design contract involves creating and destroying resources to be used by controls between a certain event range (ie. after Load and before PreRender), init the resource as late as possible before the event is fired, and destroy it as early as possible after the final event is fired

If you're going to call the page base methods anyway, you can use
protected void Page_PreRender (object sender, EventArgs e) {...}
rather than
protected override void OnPreRender(EventArgs e) {
base.OnPreRender(e);
...
}

Related

How to prevent/stop event bubbling/propagation on page load in asp.net

I would like to know if I can prevent the event bubbling / propagation on the page load based on condition like:
protected override void OnLoad(EventArgs e)
{
// If the user press F5 from the browser
if (IsRefresh)
{
// Here I want to stop propagation/bubbling the events like OnClick of a submit button but without using the button object (I want it generic)
}
else
{
base.OnLoad(e);
}
}
Is this possible?
Prevent the event bubbling has two difficulties - detect the F5 and stop the events - i would simply use the Post/Redirect/Get-pattern:
protected void Button1_Click(object sender, System.EventArgs e)
{
// do what you need to do
// now redirect to the same page,
// then a browser-refresh via F5 won't trigger this event again
Response.Redirect(Request.Url.PathAndQuery);
}
I did once in ASP.NET WebForms project when user press on F5 it'll do something other than refresh, I done this by use jQuery keypress even for the page and call e.preventDefault(); check this
Update:
$(document).ready(){function(){
this.keydown(e){
if (e.which == 116){
e.preventDefault();
window.location.href = "http://foo.com/?IsReferesh=1";
}
};
)};
You can use the QueryString to check if user press F5 and the reflection in Code Behind. If I missed something, then I didn't fully understand your question.
Regarding the specifics of your question, how about inverting it? Maybe add a Load event listener (say, in page Init) only if the condition is not met.
Another option might be doing something like:
this.Load -= MyPageLoadMethod;
You are likely looking at the event itself, not the OnLoad method. Eitherway, I think it is possible, see some options here How to remove all event handlers from a control
There is a big "BUT" though...
Like most people here, I think you are not solving the right problem. I'm sorry the same applies for Emad's solution I think.
Tim nailed it. This answer will try to explain this option more.
The pattern Post-Get-redirect is very popular and very standard. In most of our applications, submitting the same form more than once either by re-clicking the submit button before page loading or refreshing the browser causing another POST call is wrong, so, the practice of redirect after a non-AJAX form submission has become so standard.
Everything else you may try will be no more of a dirty workaround than a proper solution.
--
Now, comes the problem of providing feedback to the user. Ruby On Rails provides a nifty helper for this called Flash helper. It's a message you can set before redirecting (or even in the same page if there is no redirect) and the next time you display it, it'll destroy itself, the next time you call it, you get nothing. so, you display nothing.
ASP.NET MVC has something like this which is TempData. TempData can be stored in many places, by default in the Session, so, if you are redirecting from an MVC action, you can set something like TempData['Message'] , and read it in the next Controller. ASP.NET MVC will handle removing it after the redirect.
So, how about Webforms? There's nothing to prevent you from doing it too. It really isn't rocket science
You can check for URL Referrer whether it is an edit page or not and display message based on that.
You can store a message in Session before redirect, and check for it in every page load, if found, you display it and delete it from Session
If Session is disabled, you can use cookies. You can check the date of the cookie before sending, so that if the redirect never happened (use network dropped or whatever) and use came to the page later in the time he doesn't see an outdated message.
You can also store in Cache (with some key related to user of course, as Cache is application wide), You can then set the Cache expiration to some short period to avoid the problem explained in cookies option
You can also google for Rails Flash-like for ASP.NET Webforms to see what reusable components other people came up with. This result for example came in my search:
http://highoncoding.com/Articles/542_Creating_Rails_Like_Flash_Feature_in__NET_The_Flash_Control.aspx
Check NuGet also maybe there's something there. Again, it's not hard to build your own anyway.
Update:
Another simple approach might be to just redirect to the same URL, this'll cause a GET request and will not run any handler, pretty close to the original implementation of Post-Get-Redirect (yours will be Post-Post-Redirect maybe, kidding), and pretty safe as well.
Something like:
Response.Redirect(Request.RawUrl);
Update 2
Just as mentioned above, if you are running after page init, say in page Load, you can always emove events in a way similar to:
this.SubmitButton.Click -= SubmitButton_Click;
You get the idea...
That's useful if what you want is stop particular events, while the previous bits of the answer were assuming you are trying to stop most of the events.
http://gurustop.net
protected override void OnLoad(EventArgs e)
{
if (!IsPostBack)
{
if (Request.UrlReferrer != null)
if (Request.UrlReferrer.PathAndQuery == Request.RawUrl)
{
// Show Message
}
}
}
protected void Button1_Click(object sender, System.EventArgs e)
{
Response.Redirect(Request.Url.PathAndQuery);
}
Note:
if (Request.UrlReferrer.PathAndQuery == Request.RawUrl) // does not work with chrome
so you can replace it with
if (Request.UrlReferrer.AbsolutePath == Request.Url.AbsolutePath)
static string REFRESH_CHECK_GUID = "REFRESH_CHECK_GUID";
protected void Page_Load(object sender, EventArgs e)
{
if (ViewState[REFRESH_CHECK_GUID] != null && !ViewState[REFRESH_CHECK_GUID].ToString().Equals(Session[REFRESH_CHECK_GUID].ToString()))
{
Response.Redirect("Login.Aspx");
}
Session[REFRESH_CHECK_GUID] = System.Guid.NewGuid().ToString();
ViewState[REFRESH_CHECK_GUID] = Session[REFRESH_CHECK_GUID];

Prevent rendering of user control

in our asp.net webforms application, we dynamically load usercontrols into placeholders. In order to retain changes across post-backs, our page-life-cycle is a little more complex than usual. We ALWAYS restore the previous control structure in pageInit in order to successfully load our viewstate. Only then do we clear the placeholder and load a new control into it.
This unfortunately means an entire life-cycle both for the old AND the new usercontrol, including server-side-processing of the old module's entire .ascx markup-file.
Now my question: Is there any possibility to minimize server-side processing of the old module, as it never gets sent back to the client (i.e. it's server-side rendering is completely unnecessary). What I'd ideally want to achieve is a sort of "light-weight" loading of a usercontrol, when it's only purpose is restoring vewstate information without it ever reaching the client.
The goal of the exercise is performance optimization.
Any hints, ideas or suggestions appreciated!
I have resolved code running in webcontrol lifecycle events of dynamically added controls by simply checking if the control was visible (http://msdn.microsoft.com/en-us/library/system.web.ui.control.visible.aspx)-
protected void Page_Load(object sender, EventArgs e)
{
if (this.Visible)
{
//Your code here
}
}
If you have any methods that aren't triggered by a page lifecycle event, and have to be triggered by a user action, such as-
protected void Button1_Click(object sender, EventArgs e)
{
//Do something
}
This can safely be left as is, the method code will not be run until the control is added to the page and the action is triggered.
Although the visibility check doesn't feel especially elegant, it's probably the best way to deal with auto wired events on dynamically loaded controls.

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.

Page_Load or Page_Init

Let's take a really simple example on using jQuery to ajaxify our page...
$.load("getOrders.aspx", {limit: 25}, function(data) {
// info as JSON is available in the data variable
});
and in the ASP.NET (HTML part) page (only one line)
<%# Page Language="C#" AutoEventWireup="true"
CodeFile="getOrders.aspx.cs" Inherits="getOrders" %>
and in the ASP.NET (Code Behind) page
public partial class getOrders : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
string lmt = Request["limit"];
List<Orders> ords = dll.GetOrders(limit);
WriteOutput( Newtonsoft.Json.JsonConvert.SerializeObject(ords) );
}
private void WriteOutput(string s)
{
Response.Clear();
Response.Write(s);
Response.Flush();
Response.End();
}
}
my question is
Should it be
protected void Page_Load(object sender, EventArgs e)
or
protected void Page_Init(object sender, EventArgs e)
So we can save some milliseconds as we don't actually need to process the events for the page, or will Page_Init lack of some sorting of a method by the time it is called?
P.S. Currently works fine in both methods, but I just want to understand the ins and outs of choosing one method over the other
Basic page life cycle will answer your question Full article : http://www.codeproject.com/KB/aspnet/ASPDOTNETPageLifecycle.aspx
check same question answer : Page.Request behaviour
Either one would work, because you're essentially throwing out the page lifecycle by calling response.Clear() and response.End(). Technically you could even go as far as putting that code in prerender and it would work. By accessing the Response object you're basically going over the head of the page and cutting it off mid-stride so that you can perform a much simpler task.
I assume you simply do not want the page lifecycle at all and simply want to return JSON from this page? If so, I highly recommend implementing it as a Generic Handler (ashx). In this case you'd simply use context.Request["limit"] and context.Response.Write in your Process method. The benefit of doing this is that you don't have all the overheads of .NET preparing the page class and starting the page lifecycle, and are instead using a file intended for the task you're doing.
It is nice to understand the page lifecycle, as shown in other answers, but realistically you're not using it at all and you'd be better off moving away from the page class entirely.
Page life-cycle only has meanings in context of page elements (controls), so i don't see any differences in your case, since you don't have any other child controls in your page - this is totally irrelevant.
But here is the real question: if you don't have any rendering of html in your page (only data serialization), why you have choose to work with regular .aspx page?
Web service is ideal candidate for this scenario. And you'll be surprised how much performance improvement you'll gain in the end.
You can very well use the Page Init method. But if you have controls in your page and want to access any property of those controls then better to use the Page load event, but in your case you don't need to use page load event.
You can go through the Asp.Net Page Life cycle here to better understand which event to use.

Where should stuff be done in an ASP.NET page?

I'm very new to ASP.NET and, after beating my head on a few problems, I'm wondering if I'm doing things wrong (I've got a bad habit of doing that). I'm interested in learning about how ASP.NET operates.
My question is: Where can I find documentation to guide me in deciding where to do what processing?
As a few specific examples (I'm interested in answers to these but I'd rather be pointed at a resource that gives more general answers):
What processing should I do in Page_Load?
What processing should I do with the Load event?
What can I do in Page_Unload?
What order do things get done in?
When is each event fired?
What is the page life-cycle?
edit: this question might also be of use to some people.
The links posted by various folks are very helpful indeed - the ASP.NET page life cycle really isn't always easy to grok and master!
On nugget of advice - I would recommend preferring the overridden methods vs. the "magically" attached methods, e.g. prefer the
protected override void OnLoad(EventArgs e)
over the
protected void Page_Load(object sender, EventArgs e)
Why? Simple: in the overridden methods, you can specify yourself if and when the base method will be called:
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
// your stuff
}
or:
protected override void OnLoad(EventArgs e)
{
// your stuff
base.OnLoad(e);
}
or even:
protected override void OnLoad(EventArgs e)
{
// some of your stuff
base.OnLoad(e);
// the rest of your stuff
}
or even:
protected override void OnLoad(EventArgs e)
{
// your stuff
// not call the base.OnLoad at all
}
You don't have that flexibility in the Page_Load() version.
Marc
The first thing you need to learn to be able to understand the the questions you just asked is: PAGE LIFE CYCLE. It is a bitch sometimes, especially the ViewState part.
•What processing should I do in Page_Load?
•What processing should I do with the Load event? = Page_load
•What can I do in Page_Unload? Clean up
•What order do things get done in? PAGE LIFE CYCLE
•When is each event fired? PAGE LIFE CYCLE
•What is the page life-cycle?
Edit: Image source: http://www.eggheadcafe.com/articles/20051227.asp
More info: http://www.codeproject.com/KB/aspnet/PageLifeCycle.aspx
Here are some good links to get you started. Understanding how the ASP.NET life-cycle fits together is critical to understanding how your code will interact with it.
ASP.NET Page Life Cycle Overview:
When an ASP.NET page runs, the page
goes through a life cycle in which it
performs a series of processing steps.
These include initialization,
instantiating controls, restoring and
maintaining state, running event
handler code, and rendering. It is
important for you to understand the
page life cycle so that you can write
code at the appropriate life-cycle
stage for the effect you intend.
Additionally, if you develop custom
controls, you must be familiar with
the page life cycle in order to
correctly initialize controls,
populate control properties with
view-state data, and run any control
behavior code. (The life cycle of a
control is based on the page life
cycle, but the page raises more events
for a control than are available for
an ASP.NET page alone.)
The ASP.NET Page Life Cycle:
When a page request is sent to the Web
server, whether through a submission
or location change, the page is run
through a series of events during its
creation and disposal. When we try to
build ASP.NET pages and this execution
cycle is not taken into account, we
can cause a lot of headaches for
ourselves. However, when used and
manipulated correctly, a page's
execution cycle can be an effective
and powerful tool. Many developers are
realizing that understanding what
happens and when it happens is crucial
to effectively writing ASP.NET pages
or user controls. So let's examine in
detail the ten events of an ASP.NET
page, from creation to disposal. We
will also see how to tap into these
events to implant our own custom code.
ASP.net page lifecycle
I would definitely recommend you reading this:
http://www.west-wind.com/presentations/howaspnetworks/howaspnetworks.asp
If you're new to asp.net you'll have some trouble getting all of that, but really, I have yet to find such a detailed document on the topic comming from ms documentation or any ms employee blog.
I did it the hard way and followed every path I could using disassembled code but that guy really took the time to write it.
Basically try and do it in Page_Load and if that doesn't work, try it in either Page_Init or Page_Render. Normally one of them works :) That's the scientific approach.

Resources