A Base page in ASP.NET - asp.net

Do you recommend from every web site created in Visual Studio, that you should create a Base page that serves as the parent class?
What are the exact benefits/drawbacks?

If you want to override the way something in ASP.NET works, it can be more efficient to build it into a base class rather than including the code in every page. Two specific instances where I've done this are:
IsPostback
Little-known fact: it's quite feasible to craft a request that, to ASP.NET, looks like a postback but is submitted with a GET request. Who does this? Hackers, that's who. A call to IsPostback in this case will return true, but it shoud really return false. To get round this, build a base class that overrides IsPostBack:
Public Class MyBase
Inherits System.Web.UI.Page
<DebuggerStepThrough()> _
Public Shadows Function IsPostback() As Boolean
'Check the built-in IsPostback and make sure this is a HTTP POST
Return (Page.IsPostBack AndAlso Request.HttpMethod.ToUpper = "POST")
End Function
End Class
Error Handling
In Beginning ASP.NET Security, Blowdart talks about the fact that if you use ASP.NET's error handling to redirect the client to a custom error page, hackers (again) can detect the redirection and flag it as an error that may be exploitable. A more secure pattern is to handle the Page's Error event and do a Server.Transfer (which doesn't send anything to the client). Again, doing this in a base class means you only write the code once:
public partial MyBase : System.Web.UI.Page
{
protected void Page_Error (object sender, EventArgs e)
{
Exception ex = Server.GetLastError();
// Do something with the exception e.g. log it
...
Server.Transfer("~/mycustomerrorpage.aspx");
}
}

Yes, I do.
But please remember that the purpose of a base page is totally different from the purpose of a master page.
Let me explain.
Master pages
are layout elements used to share the same graphical features and part of the webforms behaviour (think a login/logout box with code-behind) across all pages that are associated to the master. Your final page classes will include a reference to the master page so the final result will appear as the master page including your page (check the source code to tell who contains whom)
Base pages
are (abstract? at least not sealed!) classes from which all your pages inherit from the code-behind view. Unless you explicitly and programmatically add controls to the basae page, ie. in the constructor via LoadControl method, all pages will look blank from the very beginning until you add code.
But often they are useful. If you want to override some of the base class methods, you can have the overriden behaviour shared across all pages. Or, you may want to expose application-specific objects to the children pages (a reference to a data access layer, a logger or whatever). An example is overriding UICulture property to retrieve the user-preferred language from cookies.
Both can be combined
Depending on your goals, you may combine master pages with base pages.
I suggest you to always create a base page class, since if your application's requirements change over time and you already created lots of pages, you can try to modify the base class to have the modifications propagated to all pages, according to the level of complexity of them.

Check out masterpages this is their primary purpose.
Here's a link: http://msdn.microsoft.com/en-us/library/wtxbf3hh.aspx
This will serve as the template for your site. You would add a content section that would make up the body of your site. You can reference the master page is your subpages to have a consistent layout, menu, etc. for you site.
Also, like the others have noted. If you are running any commond code, just create a class a reference it from wherever you need it.

It depends on the size and complexity of your project. For small websites with minimal functionality, a base page might be overkill. That said, I would typically use it for site-wide functionality, such as security. I tend to keep functionality in the master pages to a minimum since their primary purpose is to organize your layout and factor out common display areas from you content pages to avoid duplication and ease maintenance.
To create a base page for use in a master page scenario, you could use the following syntax:
Master Page:
<%# Master Language="C#" AutoEventWireup="true" CodeBehind="MyProject.master.cs"
Inherits="MyProject.MasterPages.MyProject" %>
<asp:ContentPlaceHolder ID="ContentPlaceHolder1" runat="server">
</asp:ContentPlaceHolder>
Base Page:
<%# Page Title="" Language="C#" MasterPageFile="~/MasterPages/MyProject.Master"
AutoEventWireup="true" CodeBehind="BasePage.aspx.cs"
Inherits="MyProject.BasePage" %>
<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1"
runat="server">
</asp:Content>
Content Page:
<%# Page Title="MyProject - Home" Language="C#"
MasterPageFile="~/MasterPages/MyProject.Master" AutoEventWireup="true"
CodeFileBaseClass="MyProject.BasePage" CodeFile="Default.aspx.cs"
Inherits="MyProject.Default"
Meta_Description="Code Snippet: Master Page and Base Page"
Meta_Keywords="master, base, content" Theme="Style" %>
<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1"
runat="server">
</asp:Content>

If you need common functionality on all your pages that belongs to the page class, create a common base class.
If you don't need such common functionality on all your pages, don't create a common base class.
If you can't decide, having a base class isn't going to hurt anybody, so you might as well have one (I'd say you more often end up needing some common functionality than not)

Related

How are custom controls instantiated in asp.net?

My understanding is that when a component or custom control is defined in an aspx page using the <%Register%> tag, it is declared in an auto-generated designer.cs (C#) file by the compiler. If this custom control is never used in the aspx page, does this still happen in the designer.cs file?
Assuming the control is used in the aspx page, what mechanism then instantiates this control, how is it new-ed up behind the scenes? The designer file only declares it. Thanks much, and if there are good articles out there discussing this I’d be happy to read them.
This may not answer all your questions, but some of them. Rick Strahl wrote a great article a while back on compilation and deployment that describes how it works:
Compilation and Deployment in ASP.NET 2.0
I added part of the article that I think relates most to your question below:
Referencing other Pages and Controls
Remember that page and control compilation happens on a per directory basis! So referencing other pages and controls becomes a little more tricky for ASP.NET 2.0, because you can no longer assume that a CodeBeside class from another page or control is available in the current assembly. At best all pages and controls in the same directory end up in the same assembly, at worst each page or control gets its own assembly and they know nothing about each other.
If you need to reference another page from a control or another page you need to explicitly import it with the #Reference directive. Again this is different than ASP.NET 1.1 where all CodeBehind classes were immediately available to your entire Web application. In ASP.NET 2.0 an explicit assembly reference is required to load it.
Assume for a minute that you have the DataEntry.aspx page I showed earlier and you want to create a second page that uses the same CodeBeside class so you can reuse the page logic, but change the page layout in DataEntry2.aspx by changing a few colors and moving around the controls of the page. In essence you want to have two ASPX pages reference the same CodeBeside file.
Here’s how to do this:
<%# Reference Page="~/DataEntry.aspx" %>
<%# Page Language="C#" AutoEventWireup="true" Inherits="DataEntry" %>
I’m leaving out the CodeFile attribute reference the CodeBeside class of the DataEntry page, and add the #Reference tag to the page to force the CodeBeside class to be imported.
The same is true with any User Control definitions. To import a user control you need to use the #Register tag, which imports the assembly that the control lives in. ASP.NET is smart during compilation and figures out exactly where related assemblies live based on how the project is compiled. If the control or page lives in the same assembly no reference is actually added. But if it is external – in another directory for example, then the assembly reference is added.
Referencing problems
If you can explicitly reference other pages and controls in your markup pages, then all works well and as expected. But if you dynamically load controls or reference pages dynamically in your code, things get a lot more complicated.
The most common problem I run into is dynamic loading of controls. In ASP.NET 1.x you might have run code like this for dynamically loading controls into a page:
public partial class DynamicControlLoading : System.Web.UI.Page
{
protected CustomUserControl MessageDisplay = null;
protected void Page_Load(object sender, EventArgs e)
{
MessageDisplay = this.LoadControl( "~/UserControls/CustomUserControl.ascx") as CustomUserControl;
this.Controls.Add(MessageDisplay);
}
protected void btnSay_Click(object sender, EventArgs e)
{
this.MessageDisplay.ShowMessage(this.txtMessage.Text);
}
}
CustomUserControl in this case is a simple User Control that lives in another directory and is loaded dynamically at runtime. Further assume that you truly dynamically want to load this control so you may have a choice of several controls, or the end-user might even create a custom control that gets dropped into place instead.
If you run the code above in ASP.NET 2.0 it will likely fail. I say likely because there are some inconsistencies that will sometimes pick up control references automatically, for example if the user control lives in the same directory and gets compiled into the same assembly as the page, or if another page has the control referenced.
It should and usually will fail. Why? Because ASP.NET compiles on a directory level and the CustomUserControl lives in a separate directory and so goes into a separate assembly. It’s not visible to page class to get a strongly typed reference. Intellisense will show a big, fat and red exclamation point or nothing at all for the MessageDisplay control. When you run the page it will bomb.
You can reference the control as the Control type of course, but if you need to access any custom properties on the user control beyond Control properties you can’t unless you resort to Reflection. As far as I know there’s no way to add a reference to another user control or page programmatically because the reference needs to be available way earlier at compile time before your code ever runs.
Alternatives are to not load controls dynamically or at least provide some mechanism to load up any user controls beforehand on a page with the appropriate #Register tags. But that’s not always possible. The other option is to create a user control base class in APP_CODE and expose the public interface there. The main problem with this is that this base class will not have access to any internal controls of the user control and so the base class would have to use FindControl to reference any embedded controls. So this is inefficient as hell, and cumbersome to boot.
I’ve run into similar situations with inheritance scenarios. For example, inheriting one master page off another’s CodeBeside class. All works well, but the ASP.NET compiler complains that the Profile object is being overridden illegally (a compiler warning). Running with the inherited master page works, but there are quirks. User Controls added to the master page often fail with type conflicts as ASP.NET treats the user control added to the base page as a different type than the user control added to the second page.
It’s inconsistencies like these that deal with referencing other types that have made me waste an incredible amount of time, thinking I had something fixed only to find out later that it didn’t actually work consistently when I changed a completely different page. Worse you have to really understand the model to get your head around what might be wrong.
Bottom line: The overall ASP.NET 2.0 compilation model is internally complex. Most of the time you don’t need to understand it, but when you run into these boundary scenarios, you really DO have to understand what goes on behind the scenes to be able to work around the quirks.

Call master page function from user control?

After searching Google I found one way to call a master page function from a user control:
Create an interface that includes your method.
Implement the interface in your master page
From your control, reference this.Page.Master via the interface type.
Call your method.
This is a good approach, but I don't know that can I call a master page static function in this way.
Another approach is :
// this is also good.
((MyMaster)this.Page.Master).MyFunction();
But I heard that this can also be done through an event.
1) Could someone show me how I could call a master page function from a user control through an event?
2) Also, how can I call a master page static function through a common interface way which I explained above.
I think it'd be better to have your user control raise an event and have your page listen for the event and then call the master page function. Controls shouldn't have any knowledge of the things that implement them - including whether or not the page has a master page.
In your content page, use the MasterType directive to generate the Master type. Then you can use the exposed Master property in the content page without casting. If you want to call a static function in the master from the content, you need to call it using the name of the master's code-behind class (since it is static)
content page:
<%# Page MasterPageFile="~/dir1/master1.master" ....... %>
<%# MasterType VirtualPath="~/dir1/master1.master" %> <!--This technique might change between .net versions. This is testing on 3.5-->
content page.cs
this.Master.nonStaticFunc();
dir1_master1.staticFunc();

Are ASP.net Content Web Forms able to access variables declared in the Code Behind section of it's Master Page?

I have a Master Page which controls the styling of my site. In the Code Behind, there are a few class instances instantiated as well as variables. These classes validate user access and then create user objects
I have a few Web Content Forms which carries out instructions based on the user objects. So far it seems that on each Web Content Form I have to create new instances of the classes found on the Master Page. This is doubling my work for every Web Content Form.
Is there anyway I can inhereit Classes and objects instantiated in the Master Page Code Behind?
Expose the objects (and even controls) as public properties (get only for controls) on the Master page. Then, in each aspx page you want access to these objects, add the following declaration at the top:
<%# MasterType VirtualPath="~/MyMasterPage.master" %>
As #Kristof points out, simply access your properties like Master.PropertyName
Also, you can determine if it makes sense to store the objects in the users Session (don't forget that they must be serializable if you use DB for session state). I do this often and control access to them via properties in a base Page class that all my pages inherit from. Actually, I have a base master, page, and usercontrol so I have access to the same properties (for me it's CurrentUser) everywhere.
I believe you can if you make the properties public.
Then in your child-page you can make the call something like this:
SiteMaster master = (SiteMaster)this.Master;
master.MyProperty = 0;
Where SiteMaster is the class for your master page. (SiteMaster is the default for the app templates)
Though my mind can deceive me, I haven't done it for a while...

master page menus

I want to create a master page for my already developed project.Since the project contains many forms it is quite difficult to include the master page in each form...Is there any possibilities to include the master page in any other simplest way...
Please give some suggestions..
Thanks in advance...
As far as I know, there is no easy way to do this.
You'll have to manually add the masterpage to the page directive
<%# Page MasterPageFile="~/Masterpage.master" ... %>
add the relevant content sections around your pages markup:
<asp:Content ID="Content1" ContentPlaceHolderID="ContentPlaceHolder1" runat="server">
</asp:Content>
and remove the <html>, <head>, <body> and <form> tags from every page.
Update
Here is an article (and source code) by Bob Powell describing a way to automatically convert html files to aspx files and add a master page. I'm sure you could adapt it to your needs.
This transition is not an easy one to make, as #geoff indicates. It is possible though if you have enough time and patience. The first step is to take all common elements (layout, menu, header, footer, whatever is common) and develop a master page structure. You'll likely need more than 1 depending on the differing layouts of forms in your application. Develop a user control for each of these common sections and make sure the master pages use these controls. Then systematically go through each page of your site and begin implementing the master pages.
As an assistance mechanism, you'll also probably want to have a page baseclass that is capable of communicating through the master page to the contained user controls. In our group we have a standard for setting a property on UserControls and MasterPages called ParentForm that is of type of our primary base page class, and this property is set during the Init of any page or control so that at any time, the developer has access (through Intellisense) to page itself. This is especially helpful since the parent of most controls is a container whose parent is a container whose parent ... you get the idea. For our controls it's just this.ParentForm.
It will be a long process, but MasterPages were really intended to be a "ground up" architectural decision rather than an "employ later" concept.

ASP.NET MVC - Code Behind of Master Pages

I am newbie for ASP.NET MVC 1.0. I am converting from a classic application built up with VS2008 .NET3.5. I created a master page, and the menu must be read from the database. Now the code that generate the HTML into the appropriate menu div in classic ASP.NET3.5 VS2008 was in the code behind of the master page.
I cannot understand now where the code beind of the master page is in ASP.NET MVC 1.0?
Anyone has examples?
Thanks
In MVC there are no longer Code-Behind classes. What you want is a Partial.
You'd use it like so:
<% Html.RenderPartial("MainMenu.ascx", ViewData["Menu"]); %>
If this Menu is going to be in all of your pages you can make your controllers subclass a custom controller class that always fills the Menu data first.
If messing with the MVC inheritance hierarchy is overkill you can also make a MenuController class and use the RenderAction in your view/master:
<% Html.RenderAction<MenuController>(x => x.MainMenu()); %>
You can still have code behind if you want. In your .master file put:
<%# Master Language="C#" AutoEventWireup="true"
Inherits="Site_Master" CodeFile="Site.Master.cs" %>
Then in your .master.cs:
public partial class Site_Master : ViewMasterPage
{
protected void Page_Load(object sender, EventArgs e)
{
}
}
Your master page is now a View, and Views should be passive. In other words, they shouldn't go look up things themselves.
It would be a much more correct approach (within the context of ASP.NET MVC) to pull the required data from the Model.
Take a look at this SO question for a related discussion.
There is a great tutorial on the ASP.NET site that shows how to do exactly this.
Briefly, you pass the data to the master page through the ViewData collection. To get the data into ViewData, create an application level controller. Have the page controllers inherit from the application controller instead of the base MVC controller.
Also, if you need to do things on your master page in reaction to the page being displayed, through this application controller you can tie into the ActionExecuting event. That will provide you information about the context of the page request currently being process.
Personally, I prefer using strongly typed views and ViewModels. If your master page requires data, then create a ViewModel for it. Ensure that every page's ViewModel inherits from this base ViewModel. Similarly, create a base controller that every other controller inherits from. Using Action Filters will allow you to ensure that the master ViewModel is populated implicitly. See this for an example.

Resources