I'm still running into problems with trying to get 'templated' master pages to work. The page/control inheritance is still getting in the way.
Here's what I'm doing (recap):
- I have a custom directory App_Templates
- Sub directories for each theme
- In each sub there are copies of all the Master Pages
Each of these master pages can now be templated. There's a little logic in the Page base class that picks up a 'template' master page and routes the MasterPage assignment in PreInit() to a specific master page that is theme adjusted. The idea is that you can create multiple master pages for each theme that essentially contain the same controls (well in reality they could contain different controls).
As described in the previous post this approach works rather well, except now I'm finding a big problem when using User Controls on the page.
In short here's what's happening: There's one 'master' template directory that actually hosts the code for the page class. So the there's one MASTER master page and then related inherited master pages in each of the Theme subdirectories.
So the first try to make this work is this:
<%@ Master Language="C#" AutoEventWireup="true"
CodeFile="~/App_Templates/Standard/WebStoreMaster.master.cs"
Inherits="Westwind.WebStore.WebStoreMaster" %>
Now this appears to work, until you need to cast the MasterPage to a specific class type consistently. Something like this:
((WebStoreMaster) this.Master).PageTitle = ItemEntity.Descript.TrimEnd();
The problem is that the main class that has the code actually is WebStoreMaster. The second class is named something like:
ASP.app_templates_earth_webstoremaster_master'
and it can't be cast to WebStoreMaster despite the inherits clause above. Strike 1.
So in theory you should just be able to use the inherits attribute without the CodeFile, which is really what I want anyway – I want one codebehind class for all the master pages. So I add a reference to the original page, which is what I showed in a previous post. This is what this looks like for a satellite master page:
<%@ Reference VirtualPath="~/App_Templates/Standard/WebStoreMaster.master" %>
<%@ Master Language="C#" AutoEventWireup="true"
Inherits="Westwind.WebStore.WebStoreMaster" %>
<%@ Register Src="~/CategoryList.ascx" TagName="CategoryList" TagPrefix="ww" %>
Note that the @Reference tag is required so that the main master page's Code class can be imported into the assembly of the second master page. Since these pages live in different directories they actually end up living in separate assemblies.
It works. That is as long as you don't add any User Controls to the page. <g>
In my example the master page contains a user control CategoryList.ascx:
<ww:CategoryList ID="CategoryList" runat="server" />
which sits on both pages and renders a sidebar. ASP.NET is not happy with that at all though:
Parser Error Message: The base class includes the field 'CategoryList', but its type (ASP.categorylist_ascx) is not compatible with the type of control (ASP.categorylist_ascx).
Cool error message, huh? <s>
I'm not really sure why this is happening. The two master pages live in different assemblies, but I'm not quite sure why the CategoryList.ascx file is getting parsed as a different type. Apparently ASP.NET compiles the user control into each of the assemblies and treats them as different types with the same exact name. If this is the case – Ouch.
So now I'm stuck. I can't figure out how to get controls to work on both master pages.
I was thinking aobut using a Master base class in APP_CODE and attaching the control properties at this base class. Unfortunately that also doesn't quite work because you can't get use the CodeFileBaseClass attribute if the there's no CodeBehind file for a class/master, so the control properties don't get updated in the base. Damn it. <g>
The easiest solution would be to use Web Application Projects which makes this inheritance mess go away with all pages, controls and masters being able to properly reference each other. Unfortunately with WAP being an add-on and this being an application that is given out to users I don't really want to require installing anything additional beyond my tools.
The more I think about all of this the more I'm starting to REALLY dislike the ASP.NET 2.0 stock project model. I've wasted more time working around crap like this than anything else. I've said on many occasions that I think most of these issues are annoyances, but once you run into one of these they can suck a ton of time and some instances there is no workable workaround solution at all. And even if there is it's often so completely convoluted that you lose all perspective of the problem in the first place. Aggravating.
Maybe somebody sees something I'm overlooking here…
Other Posts you might also like