In implementing a means of dynamically adjusting the MasterTemplate via an HttpModule (from a conversation on the forum), I encountered a bit of a hiccup with Umbraco.
Though I am able to "dynamically" inject my PreInit event handler for all pages using the module, it seems that navigating to the pages of the hosted site always hits a "default.aspx" Page that then manually renders the requested page. However, because of this, I am unable to set the MasterTemplate as I do not have access to the Page instance of the page that will be rendered to the end user: instead, I always have the UmbracoDefault page. Is there any way at all to access the "real" Page object so I can set MasterPageTemplateFile?
My module is as follows:
public class DynamicMasterModule : IHttpModule { public void Init(HttpApplication context) { context.PreRequestHandlerExecute += new EventHandler(context_PreRequestHandlerExecute); }
Additional clarification: I'm still desperately seeking a way to dynamically swap in a new Master template programmatically.
I've tried (1) building an IHTTP module -- this wont work as page generation does not follow the typical ASP.NET workflow and umbraco does not appear to provide hooks into the generation process, (2) providing code-behind for the template in question -- this wont work as all umbraco templates must be masters (attempting to use the <%@ Page ... %> directive results in an error) and MasterPage does not support the PreInit event.
I'm out of ideas :( We're desperate for this functionality (it has to be achivable dynamically) and so ANY ideas or workarounds would be *hugely* helpful.
That's a great idea. Just to clarify, I would create a new class extending UmbracoDefault and overriding "Page_onPreInit" (the event in which the master template can be altered). I would first invoke the parent's Page_onPreInit (to make sure umbraco can prepare the page for rendering), and then subsequently set "Page.MasterTemplateFile" to the appropriate master template. This seems like it should do the trick.
The second problem is finding a "clean" way of implementing this. Do I need the Umbraco source to make this work? Or is it sufficient to build this against the "production" distribution of umbraco simply by setting Default.aspx's codebehind to point to my custom class and storing that code somewhere in the umbraco directory?
Also, is this an extremely hacky solution that will likely break with future releases of Umbraco?
Clean Implementation - You're right, it's a bit hacky. You don't need the source. I would create the class in your C# solution and put it in the bin as normal. I would then copy the Default.aspx into your C# solution and copy it over the Umbraco Default.aspx on project build.
If you 'copy' such hacky Umbraco changes on solution build then it should eleviate some of the upgrade problems you'll face..... hopefully!
Overriding UmbracoDefault did the trick. However, there were a few small changes to the flight plan necessary to get everything working. Unfortunately, it turns out that Page_PreInit has private visibility. As a result, we cannot properly override it (and we cannot invoke the parent event directly).
Instead, we overide OnPreInit within the subclass, immediately invoke the superclass's OnPreInit (to trigger the preinit event) and finally set this.MasterPageFile as appropriate. This appears to work.
As regards deployment, the codebehind file is xcopy'd from the solution to the IIS website directory so that it can be referenced by default.aspx.
Not the nicest solution, but definitely workable. Thanks Chris for all of the help and direction!
IHttpModule and Umbraco
Hi all,
In implementing a means of dynamically adjusting the MasterTemplate via an HttpModule (from a conversation on the forum), I encountered a bit of a hiccup with Umbraco.
Though I am able to "dynamically" inject my PreInit event handler for all pages using the module, it seems that navigating to the pages of the hosted site always hits a "default.aspx" Page that then manually renders the requested page. However, because of this, I am unable to set the MasterTemplate as I do not have access to the Page instance of the page that will be rendered to the end user: instead, I always have the UmbracoDefault page. Is there any way at all to access the "real" Page object so I can set MasterPageTemplateFile?
My module is as follows:
Thank you very much!
Additional clarification: I'm still desperately seeking a way to dynamically swap in a new Master template programmatically.
I've tried (1) building an IHTTP module -- this wont work as page generation does not follow the typical ASP.NET workflow and umbraco does not appear to provide hooks into the generation process, (2) providing code-behind for the template in question -- this wont work as all umbraco templates must be masters (attempting to use the <%@ Page ... %> directive results in an error) and MasterPage does not support the PreInit event.
I'm out of ideas :( We're desperate for this functionality (it has to be achivable dynamically) and so ANY ideas or workarounds would be *hugely* helpful.
You could create a class that inherits DefaultPage. then change the Default.aspx to point to your new class.
The you would have access to all the Page properties
Hi Chris,
That's a great idea. Just to clarify, I would create a new class extending UmbracoDefault and overriding "Page_onPreInit" (the event in which the master template can be altered). I would first invoke the parent's Page_onPreInit (to make sure umbraco can prepare the page for rendering), and then subsequently set "Page.MasterTemplateFile" to the appropriate master template. This seems like it should do the trick.
The second problem is finding a "clean" way of implementing this. Do I need the Umbraco source to make this work? Or is it sufficient to build this against the "production" distribution of umbraco simply by setting Default.aspx's codebehind to point to my custom class and storing that code somewhere in the umbraco directory?
Also, is this an extremely hacky solution that will likely break with future releases of Umbraco?
Thanks again for the suggestion :)!
Your right with your 'Just to clarify'
Clean Implementation - You're right, it's a bit hacky. You don't need the source. I would create the class in your C# solution and put it in the bin as normal. I would then copy the Default.aspx into your C# solution and copy it over the Umbraco Default.aspx on project build.
If you 'copy' such hacky Umbraco changes on solution build then it should eleviate some of the upgrade problems you'll face..... hopefully!
This assumes you have a development environment as described here http://our.umbraco.org/forum/core/general/3619-Source-control-and-multiple-developers
Overriding UmbracoDefault did the trick. However, there were a few small changes to the flight plan necessary to get everything working. Unfortunately, it turns out that Page_PreInit has private visibility. As a result, we cannot properly override it (and we cannot invoke the parent event directly).
Instead, we overide OnPreInit within the subclass, immediately invoke the superclass's OnPreInit (to trigger the preinit event) and finally set this.MasterPageFile as appropriate. This appears to work.
As regards deployment, the codebehind file is xcopy'd from the solution to the IIS website directory so that it can be referenced by default.aspx.
Not the nicest solution, but definitely workable. Thanks Chris for all of the help and direction!
We're trying to do the same thing. theevilgeek, could you give any more details about how you set this up? ++ for code samples.
is working on a reply...