Fog Creek Software
Discussion Board

Welcome! and rules

Joel on Software

Superclasses for ASPX Pages

I have some code that is repeated across various ASPX pages so I thought I would create a superclass for these pages that is a subclass of Page.

Is that possible?  I find that if I override Page_Load in the parent class still only the Page_Load in the subclass is called.  The constructor in the parent class IS called so I know that I have set up the inheritance correctly but something about the way Page_Load works means this doesn't seem to hang together right.

And then there's the issue of the ASPX pages themselves (rather than the CodeBehing aspx.cs files) -- can the abstract parent class have one?

Thomas David Baker
Sunday, September 28, 2003

I guess you are talking about Visual Inheritance. Google for it. Or if that's not what you have in mind, then maybe you can encapsulate the common code as a web user control (ASCX).

Sunday, September 28, 2003

Regarding overriding Page_Load...

Have you tried overriding OnLoad in your super class? 

I assume you're using VS.NET.  If you look in the OnInit section of an ASPX page, you'll notice that the automatically generated code attaches Page_Load as the event handler for the Load event.  If your base class has a Page_Load method, it won't get called because the your generated overrides the Page_Load method.

The only way you'll get your base class's Page_Load method to call is to call base.Page_Load() in your class, or REMOVE the Page_Load method so that the OnInit attaches to your base class's Page_Load method.  Still with me?

Another option is to override the OnLoad method in your base class.

Sunday, September 28, 2003

Page_Load doesn't work through overriding.  It's a predefined name that the ASP.NET runtime (by default) looks for to automatically hook up the Load event.  This behavior only occurs in Pages defined in aspx files (as opposed to those defined in cs files) and can be turned off if AutoEventWireup is set to false in the @Page directive. 

If you want Page_Load to be called from the base class, you have to add Page_Load to the Load event handlers.  Just add this line of code to the constructor of the base class:

    Load += new EventHandler(Page_Load);

VS.NET does this as a two step process for some reason.  It sets an Init event handler in the constructor and then sets up the Load and controls event handlers in a function called from the Init event handler. 

Sunday, September 28, 2003

I should add that I usually prefer ecapsulating these sort of things in a user control as BillyBill suggested rather than a base class (when possible). 

Sunday, September 28, 2003

Thanks for all that guys.

I can put some of the form stuff into an ASCX.  But stuff like checking the login at the "top" of every page and a method to access the User object created by login surely belong in a superclass?

What's my best way of writing the "check there is a logged in user in the Session and if not redirect to login page" in one place and one place only for use in many (but not all) of the ASPX pages in the app?

Thanks for your help.

Thomas David Baker
Tuesday, September 30, 2003

Consider using Forms Authentication (described here ). 

You can configure pages that require login via the web.config file.  If the user is not authenticated, they are redirected to your login page.  When they authenticate, you can call a method to set them as authenticated.

Tuesday, September 30, 2003

Sticking authorization stuff in a base class is acceptable.  I've seen a few examples where someone defines a SecurePage class that handles authorization and then inherits any pages needing authorization from that. 

The big problem with this is what happens if you want to encapsulate other behaviors in a similar manner?  .NET doesn't support multiple inheritance so you end up either making a chain of derivation that doesn't make sense such as YourPage -> RandomSurveyPage -> SecurePage -> DBConnectedPage -> VisualLayoutPage -> Page or (more likely) you stick everything in a single monolithic base class invariably named [insert your company name here]Page. 

If this isn't a worry of yours, feel free to use a base class.  I've used this on a project with great success to share page layout and authorization across an internal site.  One way of doing this without a base class is using web.config like haacked mentioned (if applicable).  You could also stick with the control idea -- it would be a control that renders nothing.  The trick with this is getting the order of events right so that your control has an opportunity to redirect (if needed) before the main page's Page_Load gets called.  The designers of the .NET Framework seem to like using attributes for things like this though I've never seen anyone try to use custom attributes for authorization. 

Tuesday, September 30, 2003

The problem I have with versions that do not involve a superclass is that the login cannot be made to happen without some code in the subclass page.  Basically I want login to be checked at the "top" of the page for every secure page without having to write any code at all in those pages.

I definitely see what you are saying about multiple superclasses though - the last Java project I did kept it down to three but I could see a bigger project needing more.

Perhaps the best thing is to make the visual stuff into ASCXs and just keep the invisible stuff in the superclass(es).  Or is that the worst of both worlds?

Also, how do you guys put the same header and footer on to each page without repeating yourselves?

Thomas David Baker
Wednesday, October 1, 2003

You can have controls do the invisible stuff for you.  At the top of every page you’d have something like <yourTag:AuthRequired runat="server" />.  AuthRequired would simply hook into Page_Load (or some other event) and call Response.Redirect if needed.  If a page requires authorization, you just drag n’ drop the control from the toolbox to the aspx page, maybe fill in a Roles property (if desired), and you’re set.  Another approach would be handling authorization in an Application level event (i.e. global.asax) having the advantages of taking place early in the pipeline and being usable for non-Page HTTP handlers such as .ashx or.asmx files.  ASP.NET uses something like this for the built-in authorization features through HttpModules.  The best approach depends on the specific requirements of a given project.  The common base class approach *can* work fine (I've used it) but it makes it easy to paint yourself into a corner. 

As far as putting the same header and footer on each page, now you’ve really opened a can of worms!  There are a variety of approaches and there have been some massive discussions at places such as the ASP.NET (that’s the URL) forum about this. 

With the common base class approach, you can override Render and do something like:

  writer.Write( … header HTML … )
  writer.Write( … footer HTML … )

The disadvantages of this (besides the monolithic base class problem) are the need to convert HTML to something you can stick in a Write call and the lack of designer support.  If the page layout is simple and going to change very rarely (or never), these aren't big issues. 

Another approach is called MasterPages (supposedly similar to what the ASP.NET team is working on for version 2.0).  Paul Wilson extended this with some useful features such as designer compatibility.  Check out this page for more information on this approach:

Wednesday, October 1, 2003

*  Recent Topics

*  Fog Creek Home