Last week he published an advanced ASP.NET 2.0 Master Pages Tips, Tricks and Traps article that you should check out here. It goes really deep and does a great job of describing the control tree mechanics of how a master page and content page are merged together at runtime, how you can programmatically switch master pages on the fly from within a page, within a page base class, and even within an HttpModule (to enforce behavior across a site), how to build base-class "contracts" between master pages and content pages to programmatically share data or behavior semantics, how to use base-classes across your site to encapsulate common functionality (for example: meta-tags in headers), how URL re-basing works for URLs and resources, and a bunch more advanced topics.

Definitely worth checking out if you want to really push master pages hard and get the most out of them.

Hope this helps,

Scott

35 Comments

he has clearly shown that masterpages are just a controls inside the page, and i also got to know the event handling. thanks. does he have rss on his page ?

I completely and thourgh;y hate the Name Mangling when using master pages. It makes it damn near impossible... or highly impractical to create sanely named CSS outside of using themes.

This becomes twice as bad when you have developers who do the code, and designers who do the CSS, and you have a predefined Id naming conventions. The Id the designers see in the .aspx source isn't what you get in the output, obviously makeing CSS mistmatch the expectations.

I have a master page with a menu control for a user to navigate within my application.

The master page is in application root; I have a couple of sub-applications under the root application. I configured them to share the same master page. I found the urls on the menu are broken for the pages in the sub-applications. So I have to create one master page for each sub-application, only difference between them is the relative path to a page on the menu. Is there a easy way or wrok around to share one master page across applications?

One approach would be to absolutely qualify the paths. For example: / for root urls and things like /images and /stylsheets for directories immediately underneath it. This would then work regardless of which app was used.

I'm also having big problems with using master pages due to name mangling. &nbsp;I simply don't want ASP.NET to change the name/ID attributes of my form elements. &nbsp;I use the IDs in CSS, javascripts and label elements. &nbsp;It's a really ugly solution to have to change these everywhere. &nbsp;And as for switching to class based CSS styling, I really don't think that a MS tool should be dictating what CSS developers use. &nbsp;Is there a way to switch the name mangling off? &nbsp;Maybe a page directive or a method I can override somewhere.

I was having an issue with name mangling with JavaScript. &nbsp;The application I work on extensively uses custom JavaScript for AJAX functionality. &nbsp;I was very excited about implementing master pages when we moved to 2.0, until I discovered they broke ALL of our JavaScript! &nbsp;We use getElementById() to access dynamic page controls, and their nice clean name suddenly became a mile long disaster. &nbsp;Not wanting to couple the JavaScript too tightly to the master pages, I developed a solution where the master page finds all the controls on the page that implements it and generates predictable JavaScript variables for each control which store the actual client ID of the control. &nbsp;For example, a control named "ddlFilter" on the page would be warped into "_ctl0_phContent_ddlFilter" by the master page. However, the master page will generated the variable "ddFilterClientId" which stores "_ctl0_phContent_ddlFilter", and can then be used via JavaScript to access the control. It's not a perfect solution, as it doesn't do anything for CSS or label tags (or app has to be 508 compliant). Here's the code which is just placed into the Page_Load function of the master pages: &lt;code&gt; ContentPlaceHolder phContent = (ContentPlaceHolder)Page.Master.FindControl("phContent"); StringBuilder oScript = new StringBuilder(); foreach (Control ctrl in phContent.Controls) { &nbsp; string sClientId = ctrl.ClientID; &nbsp; string sOriginalId = ctrl.ID; &nbsp; oScript.Append("var "); &nbsp; oScript.Append(sOriginalId); &nbsp; oScript.Append("ClientId='"); &nbsp; oScript.Append(sClientId); &nbsp; oScript.Append("';"); } &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Page.ClientScript.RegisterStartupScript(this.GetType(), "ctrl_ids", oScript.ToString(),true); &lt;/code&gt; I hope this helps someone else having a problem with name mangling.

Hi I even got a problem with my menu control in my master page. the menu control works fine during first load, but when the page postbacks the menu hover doesnt work fine. The menu expands but doesnot close till the page postbacks once again. Is there any solution for this.

Another issue I'm having with name mangling is that id attributes starting with an underscore are being flagged as errors when I run my HTML through the w3c HTML validator. I think I'm going to have to give up on master pages. &nbsp;they don't quite seem fully baked yet.

I have a master page, and in this page is a with background image attribute. This background is supposed to change for every child page. How do I assign the image names for each pages under a single master page. Thanks a lot!!

You should be able to expose a public property on your master page for the background image's name. You can then set this property from your child page to vary on a per page basis. The advanced article listed above shows how to expose a property and set it this way using master pages.

I'm looking for a solution similar to Duane's. I have an "Web Site" as my main where my master pages containing user controls and public properties. I can make any changes to the Masterpage from a page using it as long as it's within the Website.

I have a number "ASP.Net Web Application" projects in the same solution that uses the masterpages of the main site. But I can't change anything on the masterpage because the public properties can't be seen. Any suggestions?

Am I correct in understanding that you want your Web Application Projects to reference a Master Page within a Web Site Project?

If so, then you'll probably want to create an interface or base class within a separate class library project that you have both the web-site project and the web-application projects reference. The master-page would then implement the interface, which would allow the web application projects to use the interface to get/set the property values.

I'm developing a website with a masterpage and a login.aspx as the startup content page. However, when i try to run the project, the image on the master page is not displayed. When login is successful and control is transferred to the default.aspx, the image on the masterpage is displayed.

Incidentally, if i change the "authentication=windows" instead of "forms" in web.config
the image is displayed when i ran the project.

How can I properly display images in the master page without changing the "authentication=forms" in web.config?

Background images are static html elements -- which means ASP.NET won't automatically adjust their paths for you. Instead you should look at providing a root relative path. For example: /images/foo.jpg instead of just images/foo.jpg.

Alternatively, you might want to consider using CSS and have them defined via an external .css file. Images are loaded by browsers relative to the .css file -- in which case you don't need to worry which pages references it (since the browser will fix it up for you automatically).

I am using a custom control dervied from compositecontrol class. I have a button in this control which fires an event. When I use this custom control in a normal aspx page it works fine, but in master page the event is not getting fired. Could you help?

Thanks Eric Eubank for presenting your fix to handle name mangling. Master pages are nice but we got to have a builtin way that is cleint side javascript friendly. Till then (and I am not holding my breath for MS to solve this), this will work nicely.

First of all, thanks a lot for the great info Scott.
Secondly, is Microsoft (henceforth MS) working on giving us a better way of handling the JavaScript and CSS issue with the next release of ASP.NET?
The idea behind MasterPages is great its just not practicle enaugh to convince the majority to risk their custom JavaScript and CSS integrity; perheps a way to bridge the client side it with control's actual ID in some fashion or form that when a JavaScript calls a control A, A points to ctl100_A for the correct reference.

Any updates as to if MS is working on this issue at all? Thanks in advance.

It is something we are looking at for the future (to give you more control over the ID).

Note that ID values are deterministic - so you will get consistent controlID names at runtime.

What I usually recommend is also using or elements with fixed ID names (or class attributes) that I wrap around dynamic content and use to apply my CSS rules with. This is fairly easy and works well today.

I have recently introduced a Master page to my site which i have been looking forward to for ages. It uses a CSS div layout.

The content pages that I am migrating use the RegisterStartupScript to register a block of Javascript that is used in the page. What I am finding is that the script is actually the last thing to be written to the rendered page.

As div's apparently mean that the browser can start drawing them before the whole page is loaded (despite buffer=true??????) I am getting errors now where the javascript functions are called before they are written to the page.

A typical example of this is where I have written a function to apply some kind of mouseover.

The errors are picked up in the IDE (which is nice) - and show that the page is not complete.

If I don't wazz around with the mouse and keep monk-like still until the page is loaded everything is hunky dory (because the script block is now there).

I never used to have this problem before master pages - is this because I am now using div's with their weird "loading before page is complete despite me thinking i am using a response buffer" behaviour or is something different happening with master pages about when exactly in the rendering of the page it decides to inject my javascript block??

I had the same problem with Microsoft's own controls javascript - the treeview control was freaking out about doing a mouseover before all the nodedata/page was loaded... eventually I made the div holding the navigation tree display:none and made it display:block once the page had loaded. This error happened all the time as your mouse was over the control when the new page was drawn.

I am thinking of using this technique now for the content div - however my problems would be solved in a less clunky way if I could get ASP.NET to emit my javascript block earlier in the page render.

You can use class names instead of IDs to name CSS rules. I actually recommend these since they allow you to use them with multiple elements across a site, and also work fine regardless of how deep a control is nested.

I have a calendar popup used at many a places in in my application. when i popup the calendar from a webpage which is inherited from masterpage it wont populate the textbox with date back.... can anyone help me out... same code works for a webpage which is not inherited from masterpage.