I have some WebForms, such as First.ascx.cs, Second.ascx.cs, Third.ascx.cs and so on!
Well, I'd like to call a function (let's say, startFunction()) at the PreInit stage, and another one (let's say, endFunction()) and the PreRender stage, for EACH context.
So:
startFunction();
... First.ascx.cs PageLoad execution...
endFunction();
startFunction();
... Second.ascx.cs PageLoad execution...
endFunction();
startFunction();
... Third.ascx.cs PageLoad execution...
endFunction();
without write the same start/end function and copy and paste for each context I need to control. Is there a good strategy with .NET (3.5) and WebForms?
Inheritance!
Create a basecontrol where you attach to those events and then derive from it.
MarkzzzClass .cs
public abstract class MarkzzzClass : System.Web.UI.UserControl
{
//do something
}
BaseControl.cs:
public abstract class BaseControl : MarkzzzClass
{
protected override void OnPreRender(EventArgs e)
{
EndFunction();
base.OnPreRender(e);
}
protected override void OnInit(EventArgs e)
{
StartFunction();
base.OnInit(e);
}
}
First.ascx.cs:
public partial class First : BaseControl
{
protected void Page_Load(object sender, EventArgs e)
{
}
}
Related
I'm a beginner in ASP.NET, just a question on user control events and page events, lets say I have a user control called myControl(.ascx) and a webform page my Page:
public partial class myPage: System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
...
}
}
public partial class myControl: System.Web.UI.UserControl
{
protected void Page_Load(object sender, EventArgs e)
{
...
}
}
so my question is, which Load event happen first? my control's Load or myPage'Load? My textbook says it will be a random, undetermined order, but why we can't have a standard way like: all control events get raised first, then the postback event, isn't that more sensible?
How can I add code to the Page_Load() method for every instance of System.Web.UI.Page without repeating the code?
I want, everytime a page loads, for the code
Debug.WriteLine("hello");
// other stuff here
// lots of lines of code
to run.
so I have many web pages for example
public partial class WebForm1 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
// don't want to have to repeat all that code above here
// stuff that WebForm1 does
}
}
How can I run the first snippet for each Page_Load event without repeating the code for every webform?
MasterPage.cs
-----------------
protected void Page_Load(object sender, EventArgs e)
{
Debug.WriteLine("hello");
}
I want to execute a function on Page_load event of every System.Web.UI.Page from which derives my own CustomPage class (which obviously inherits from Page class as well)
what I have done so far it that I created CustomPage class like this:
public class CustomPage : System.Web.UI.Page
{
protected virtual void Page_Load(object sender, EventArgs e)
{
CallTOTheDesiredFunction(); //this is the call to the function I want
}
}
And in the derived Page classes I am doing this:
public class DerivedPage : CustomPage
{
protected override void Page_Load(object sender, EventArgs e)
{
base.Page_Load(sender, e);
//the rest of the page load event which executes from here on
}
}
As it is obvious, this approach is working but it is not the best solution since I have to call base.Page_Load(sender, e) on every derived page.
Is there a better solution to what I am trying to achieve?
Thank you in advance
Yes. It is better to override the Onload method rather than relying on deriving classes to call the base method.
You can still hook on the Load event in every page, but use the method in the base class.
public class CustomPage : System.Web.UI.Page
{
protected override void OnLoad(EventArgs e)
{
CallTOTheDesiredFunction(); //this is the call to the function I want
base.OnLoad(e);
}
}
What is the best way to assign security logic to a method in ASP.NET WebForms? Where instead of checking under each method if the user is logged in, can't we use method attributes?
Example, instead of doing this:
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
if (!UserLoggedIn)
{
Response.Redirect("/login");
}
//Do stuff
}
I would like to do something like below. I've seen it done in ASP.NET MVC apps but I wonder if I can pull it off with webforms. And also what would be the best practice for ensuring only an authenticated user can continue and others get redirected to login page?
Ex: Desired. Where Secure is a method attribute:
[Secure]
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
//Do stuff
}
How do I go about creating such method attribute? And if that is not possible, how would you recommend I do it? I have many usercontrols that need this on page_load or oninit and I am looking for a better way to do it.
Declare your attribute
[AttributeUsage(AttributeTargets.Class)]
public class SecureAttribute: Attribute
{
}
Create custom base page class for all forms
public class PageBase: Page
{
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
var secureAttr = Attribute.GetCustomAttribute(this.GetType(), typeof (SecureAttribute));
if (secureAttr != null)
{
bool UserLoggedIn = false; // get actual state from DB or Session
if (!UserLoggedIn)
{
Response.Redirect("/login");
}
}
}
}
Inherit all your forms from the PageBase
[Secure]
public partial class Profile: PageBase
{
}
Create similar UserControlBase for user controls.
One possible Solution would be a PageBase helper class to avoid check that condition on every single pages on your ASP.NET web forms and just inherits the page-base in your aspx.cs classes. something like the code below:
for example you want to make sure that some web forms are only accessible by Admin users then you could have a AdminPageBase class to check this condition for all of your web pages.
your base class:
public class AdminPageBase : System.Web.UI.Page
{
protected void Page_Init(object sender, EventArgs e)
{
if (!Context.User.Identity.IsAuthenticated ||
!HttpContext.Current.User.IsInRole(Roles.Admin.ToString()))
{
this.RedirectToLogin();
}
}
protected void RedirectToLogin()
{
//...
Response.Redirect("~/SignIn.aspx");
}
}
Note: Roles.Admin.ToString() is an enum, but you can also use a plain string if you like
and in your web form classes you only inherits this base class like this:
e.g. AdminPage1.aspx.cs
public partial class AdminPage1: AdminPageBase
{
//....
}
e.g. AdminPage2.aspx.cs
public partial class AdminPage2: AdminPageBase
{
//....
}
and you could always do the same for all other pages in your solution.
you could also change Page_Init to Page_Load on your PageBase class but the reason I have chosen the Page_Init is because you may need Page_Load event to check other things on your page so it's a good place to check your website security.
In order to intercept method calls, I would recommend utilizing some AOP framework, e.g. PostSharp, which allows easily inject behaviors before and after method execution by declaring custom aspect:
[Serializable]
public class SecureAttribute : OnMethodBoundaryAspect
{
public override void OnEntry(MethodExecutionArgs args)
{
bool UserLoggedIn = false; // get from DB
if (!UserLoggedIn)
{
HttpContext.Current.Response.Redirect("/login");
}
}
}
And applying that attribute to any method
public partial class Profile : Page
{
[Secure]
protected void Page_Load(object sender, EventArgs e)
{
}
[Secure]
protected void Button1_Click(object sender, EventArgs e)
{
}
}
As far as I know, PostSharp incures minor performance hit, or incures no performance hit at all, as PostSharp emits MSIL instructions.
I am able to hook the event and also allowed to override load and init.., events in my aspx codebehind file. I have following questions.
public partial class Default : System.Web.UI.Page
{
public Default()
{
this.Init += Default_Init;
this.Load+=Default_Load;
}
protected void Default_Load(object sender, EventArgs e)
{ }
protected void Default_Init(object sender, EventArgs e)
{ }
protected override void OnLoad(EventArgs e)
{ }
protected override void OnInit(EventArgs e)
{ }
}
Qs:
Why such option(both virtual method and event handler) is exist in Page class?
When override methods got executed, my event handlers(Default_Load and Default_Init) are not executed. what is the reason behind?
Should i call base.OnLoad(e); in overridden OnLoad method? Why should/shouldn't I?
By default, OnInit and OnLoad are not handlers of Init and Load events. They are used to Fire Init and Load events.
When you override, you change the behavior of these methods thus, events are not fired by OnInit and OnLoad methods (unless you explicitly write base.OnInit etc.)
If you change the behavior of OnLoad and do not call base method, then you may break the page lifecycle of asp.net application. For instance, Load event will not be called.
Normally, the method OnXxx raises the event named Xxx. This is also the case in a System.Web.UI.Control like Page.
If you do:
protected override void OnLoad(EventArgs e)
{
// nothing here!
}
you change the behavior of OnLoad so that it now does nothing. Therefore, most probably, no-one will ever raise ("fire") the Load event. So its event handler is never run.
If instead you do:
protected override void OnLoad(EventArgs e)
{
// maybe add some code of your own here ...
base.OnLoad(e);
// ... or here
}
then the base call will make sure the method still raises the event.
You can only raise the event explicitly, i.e. invoke the underlying delegate, if you're in the class where the event was declared. So that's not a possibility for you. The base class where Load is defined does that like this:
// inside same class where 'Load' event is defined:
protected virtual void OnLoad(EventArgs e)
{
// maybe they put some other code here ...
var loadDelegate = Load; // gets the current underlying delegate of the event
if (loadDelegate != null)
loadDelegate(this, e);
// ... or here
}
But in most situation you shouldn't override any method at all. Just add to Load when you want some code to run when the Load event fires.