All about the Strategy, Design, Customisation, Deployment and Development of SharePoint and its related Technologies

  Administration   All Me!! Baby!!   BDC   Book Review   Business   CKS   Conferences   CQWP   Development   Duffer Moments   Email   Errors   Family   Fixes   General   Groove   How To   How To Code   InfoPath   iPhone   IRM   Longhorn   Lotus Notes   Migration   Mobility   Office System 2007   Personal Projects   Powershell   Records Management   Search Server   Security   SharePoint   Silverlight   SQL   Tech Ed 2008   Testing   Vista   VSTO   WSS   XSL

[09/05/2007] MOSS2007 - "HttpModule" Investigation
 
Categories: Development, Office System 2007, SharePoint
 

I have recently been trying to develop an “HttpHandler” that will change the “Master Page” for the portal and sites on the fly based on various parameters. I am hoping that I will be able to validate the user and the zone they are coming from and display different master pages accordingly. My first idea was to create a new class library and override the “PageBaseType” within the “Web.Config”. This would have worked except that any pages that already have “Inherits” statements don’t work. This solution would involve having to change the “inherits” for each and every page in the site, something I am not about to do. My next approach was to create an “HttpHandler” that simply would override the “Page_PreInit” method and change the master page. I read various articles to work out what the code would be and also the best approach to doing this.

http://ryanfarley.com/blog/archive/2004/06/16/788.aspx

 

http://weblogs.asp.net/soever/archive/2006/11/14/SharePoint-2007_3A00_-using-the-masterpage-from-your-site-in-custom-_5F00_layouts-pages.aspx

 

http://www.lnbogen.com/OverrideOnPreInitOnAPageWithMasterPage.aspx

 

http://msdn.microsoft.com/msdnmag/issues/04/06/ASPNET20MasterPages

 

http://staff.develop.com/ballen/blog/PermaLink.aspx?guid=09befce7-f48e-4555-891c-13818fd75a56

 

http://odetocode.com/Articles/450.aspx

 

http://www.sharepointblogs.com/dwise/archive/2007/01/08/SingleMasterPage.aspx

 

After reading the articles above I decided to structure the code as follows:

public void Init(HttpApplication context)

{

context.PreRequestHandlerExecute += new EventHandler(context_PreRequestHandlerExecute);

}

void context_PreRequestHandlerExecute(object sender, EventArgs e)

{

HttpApplication httpApp = sender as HttpApplication;

 

if (httpApp != null)

{

Page page = httpApp.Context.CurrentHandler as Page;

               

if (page != null)

{

page.PreInit += new EventHandler(page_PreInit);

}

}

}

void page_PreInit(object sender, EventArgs e)

{

Page page = sender as Page;

if (page != null)

{

if (page.MasterPageFile.Contains("application.master"))

{

page.MasterPageFile = "~/_layouts/CustomApp.master";

}

else

{

page.MasterPageFile = "/_catalogs/masterpage/Custom.master";

}

}

}

 

public void Dispose()

{

}

This code simply hooked into the “PreInit” method of the page and changed the master page. If it was a page that was rendered from the “_layouts” directory it rendered using a different page. If it was a normal page it should render using my Custom.Master page. So now I had my code, so time to test. To test it I took the following steps:

1.  Copy DLL to GAC

2.  Add following lines to “Web.Config” for Web Application

 

<add name ="CustomHttpModule" type="HttpModule080507.CustomHttpModule, HttpModule080507, Version=1.0.0.0, Culture=neutral, PublicKeyToken=13494ee1574dcc83" />

 

3.  IISRESET

4.  Launch Portal Home page in Browser

5.  Attach Visual Studio to w3wp.exe process for the portal and then step through the code

I added break points to the following lines of code:

1.  context.PreRequestHandlerExecute += new EventHandler(context_PreRequestHandlerExecute);

2.  page.PreInit += new EventHandler(page_PreInit);

3.  if (page.MasterPageFile.Contains("application.master"))

4.  page.MasterPageFile = "~/_layouts/application1.master";

5.  page.MasterPageFile = "/_catalogs/masterpage/BlueBand.master";

After some initial testing I noticed some very perculiar behaviour. I undertook the following tests.

1.       Launch the portal main page

I expected the master page to change to my Custom.master. It did not

2.       Press Site Actions, Site Settings then Modify All Site Settings

I expected the master page to change to my CustomApp.master page. It did

3.       Select “Document Center” from top navigation

I expected the master page to change to my CustomApp.master page. It did

4.       Select “News”, “Reports”, “Search”, “Sites” from the top navigation

I expected the master page to change to my Custom.master page. They did not

5.       Created new Team Site and accessed this

I expected the master page to change to my Custom.master page. It did

As you can see I got very different results depending on where I was trying to access within the MOSS2007 platform. The pages that did not render the new master page didn’t seem to call my “page_PreInit” method at all. The debug window did show it hit the line to add the override method but that was it.

When I ran the test on the pages that did work the following took place.

As of yet I have not found a solution. I am still working on resolving this and once I have will continue with the rest of the code. If anyone has any ideas on this it would be much appreciated. I don’t profess to be a hard core developer so could use some guidance.

 

 
3 Comments
 

Comments

Tuesday, 30 Oct 2007 08:43 by bgeoffro
Great article. Of the scenarios you've listed, I've been able to apply custom master pages for all the "custom.master" scenarios that you had been unable to address. Use feature stapling to associate new themes/master pages with site definitions so that new sites will use themes/master pages of your choosing. After that, all you have to worry about are the _layouts pages, which you seem to have solved... I had to resort to the methods in KB944105 (released yesterday) to brand the pages that use application.master and simple.master. Your solution looks much cleaner - have you had an opportunity to load test it to determine any impact on performance?

Monday, 17 Dec 2007 02:49 by Liam Cleary
Hey Brett, Hope you are well. Just read through your posts!! Fantastic!! I have only done some minor testing for performance but nothing major. Looks like you have done some great work. Gonna book mark your pages now!! :-) Liam

Friday, 11 Apr 2008 09:48 by Brett
Thought you might be interested: I took your approach, but put my application.master into the _catalogs/masterpage directory of my site. I modified your code to call this page. That way: I don't have to touch the filesystem to make changes to this file; it's saved with the file template; easily edited with SPD; and you can have a custom application.master for each sub-site, etc - as flexible as your custom master pages for content pages. Just completed it so haven't tested it fully, nor do I know what the performance implications are yet. But, it works... :) Thanks for your post.

Name:

URL:

Email:

Comments: