Great New Advanced Article on ASP.NET 2.0 Master Pages

K. Scott Allen has an awesome blog and regularly publishes great articles on .NET topics (I've linked to a lot of them in the past).

Last year he published a great ASP.NET 2.0 Master Pages Introduction that you can read here

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.



    It's why we're not using master pages at all.

  • Hi Chris,



    The naming for server-control IDs is hierarchical -- but consistent. So it is possible to-do ID based CSS styling if you want (the IDs won't change on you as you are building your pages).



    What I typically recommend, though, is to do class based CSS styling instead. That allows your CSS styles to be re-used across pages/elements more easily.



    Alternatively, you can also just use static html container elements with IDs to style things. For example:



    <div id="myelement">

    // some stuff here...

    </div>



    Hope this helps,



    Scott

  • Great Links Scott. Thanks. I've practically learned ASP.NET using all these blogs and links provided by You.

  • Scott,

    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?





    Thank you

    Hua

  • Hi Hua,



    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.



    Hope this helps,



    Scott

  • he has highlightede the common problems developers face with master pages, and provide tips and tricks to use master pages.thanks.It was very helpful to know those concepts.

  • I'm also having big problems with using master pages due to name mangling.  I simply don't want ASP.NET to change the name/ID attributes of my form elements.  I use the IDs in CSS, javascripts and label elements.  It's a really ugly solution to have to change these everywhere.  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.  Is there a way to switch the name mangling off?  Maybe a page directive or a method I can override somewhere.

  • I was having an issue with name mangling with JavaScript.  The application I work on extensively uses custom JavaScript for AJAX functionality.  I was very excited about implementing master pages when we moved to 2.0, until I discovered they broke ALL of our JavaScript!  We use getElementById() to access dynamic page controls, and their nice clean name suddenly became a mile long disaster.  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.  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: <code> ContentPlaceHolder phContent = (ContentPlaceHolder)Page.Master.FindControl("phContent"); StringBuilder oScript = new StringBuilder(); foreach (Control ctrl in phContent.Controls) {   string sClientId = ctrl.ClientID;   string sOriginalId = ctrl.ID;   oScript.Append("var ");   oScript.Append(sOriginalId);   oScript.Append("ClientId='");   oScript.Append(sClientId);   oScript.Append("';"); }          Page.ClientScript.RegisterStartupScript(this.GetType(), "ctrl_ids", oScript.ToString(),true); </code> 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.

  • Hi Jaya,

    Any chance you can post your question in this forum here: http://forums.asp.net/139/ShowForum.aspx

    There are a lot of experts that hang out there who should be able to help.

    Thanks,

    Scott

  • I spent a while looking for a good way to access a server control from javascript and finally found this:

    document.getElementById('<%= myControlID.ClientID %>')



    It may not be optimal but it is probably the easiest way to get the client id of a control.

  • 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.  they don't quite seem fully baked yet.

  • Hi Ben,

    Master Pages are fully XHTML compliant. What is the ID that you are using, and what validator are you running that is flagging an error?

    Thanks,

    Scott

  • I am getting the same underscore in the generated code for the ID.  Any idea what is causing it?

  • Hi David,

    Can you post or send me email with the markup you are getting?

    Thanks,

    Scott

  • Martin followed up his post above with some details on why he was getting the leading underscore in the control names used in masterpages.

    His site had been migrated from VS 2003, and had the XHTML compliance switch turned off within the web.config file:

    It's alright I've found the problem eventually! The conversion wizard left the following tag in my web.config



    Removing that setting caused all the controls to be prefixed with ctl0 and not _ctl0.

    Hope this helps,

    Scott

  • Hi Scott,

    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!!

  • Hi Duane,

    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.

    Hope this helps,

    Scott

  • Scott,

    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?

  • Hi Duane,

    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.

    Hope this helps,

    Scott

  • I had the same problem and I tried the following syntax and it works fine:
    document.getElementById('')

  • Hi Scott,

    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?

    Hope you can help me.

    Thanks.

    Ricky

  • Hi Ricky,

    I believe you are running into this issue because you are using the built-in VS 2005 Web Server: http://weblogs.asp.net/scottgu/archive/2006/01/31/437027.aspx

    The above article describes how to fix it. :-)

    Hope this helps,

    Scott

  • Hi Ricky,

    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).

    Hope this helps,

    Scott

  • Hi,

    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.

  • Hi Scott,
    I have acase as follows: Default.aspx defines its master page as SubMaster.master, which defines its master as SiteMaster.master.

    SiteMseter.master contains an image control with id img01, SubMaster.master contains another image control with id img02.

    In Default.aspx.cs's Page_Load, I need to set the image URL for img02 (the submaster image).

    Master.FindControl("img02")

    returns null, whereas

    Master.Master.FindControl("img01")

    does return the proper control. i.e.I can access controls in the main master but not in the sub-master page. Where did I go wrong?
    Thanks...

  • 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.

  • Hi Haider,

    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.

    Hope this helps,

    Scott

  • Hi Scott

    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.

    Any ideas?

  • I have a masterpage that I am working on with multiple menus and I want to be able to find the ID at runtime, so I can perform some other action, when that particular menu is in use.

    Server side how do I get a list of the menu id's at runtime in C# ?

    Is there some foreach construct and collection I can enumerate within a masterpage class to obtain all the menu id's ?

    Thanks in advance.

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

    Very true. But, isn't that deterministic name based on control depth and order? The minute those change, the ids are changed, and your CSS is hosed.

    And from a practical standpoint, deterministic still doesn't mean 'sensical for a designer not involved in the programming the project'...

    As far as always using classes...that isn't always possible either. Sometimes you need to work around CSS specificity issues where thing need to be applied to a moer specific #id rather than .class.

    I'll always be the official bad guy broken record that proclaims master pages and control id futzing bad for separation of code from content.

  • Hi Chris,

    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.

    Hope this helps,

    Scott

  • 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.

Comments have been disabled for this content.