Although not officially supported, MCMS 2002 SP2 works fine with Web Parts as I outlined earlier.
A couple of weeks ago Ali Mazaheri, a collegue from Microsoft Consulting Services contacted me to get some tips as he had to create a proof of concept for using ASP.NET Web Parts on MCMS template files.
The requirements were as follows:
- Allowing Changes to the layout and content of the Master pages through CMS Authoring tools and Publishing API(PAPI).
- Allowing the editor(s) to add new content and apply changes to the existing content by leveraging CMS workflow functionality to Save, Approve and finally Publish the content to the production Website through the CMS Channels and Templates.
- Providing fully customizable and personalizable pages by leveraging ASP.NET Web Parts and built-in support for personalization on CMS Template files.
- Store Serialized Web Controls and Personalization data on CMS data store through CMS PAPI library.
When implementing this proof of concept he identified the following challenges
- By default, changes to Web Part’s layout or its properties ([Personalizable()]) will take effect immediately on production website and are not included in the MCMS approval workflow.
- Personalization info being maintained automatically through Web Part Manager (Personalization class) and stored on an independend SQL db by default.
- Revisions are not supported through this model.
ASP.NET web parts make use of a Personalization Provider to persist user specific settings in a database. On the other hand MCMS uses placeholder controls as front ends to save the data entered by a user into placeholder objects in the MCMS repository.
The problem here is that the SavePersonalizationBlob method of the personalization provider fires ealier than the SavePlaceholderContent method of a placeholder control. In addition it can also fire multiple times before the user decides to save the current posting. And even worse: if the user decides to use the cancel button the changes need to be thrown away and the original content needs to be active again.
So the challenge here was to persist the changes done through the Webpart Manager and then to save the current state when the user clicked on the Save button in Web Author.
There would have been different ways to persist the data in the overridden SavePersonalizationBlob method. E.g. to register a hidden form field. My collegue decided to use the HttpContext.Current.Profile collection of ASP.NET 2.0 to persist the data. The HttpContext.Current.Items collection could not be used as the state has to be persisted through multiple postbacks.
To ensure that the content is stored in a placeholder in the MCMS repository a custom placeholder control was implemented which did not have any user interface. It’s only purpose was to ensure that it’s SavePlaceholderContent method got fired. Inside this method the content of the HttpContext.Current.Profile collection was read, serialized and then stored inside the underlaying XmlPlaceholder object.
A good thing would have been if the LoadPlaceholderContent method of this placeholder control could be used to load the personalization data again from the placeholder object. But this did not work as the personalization providers LoadBlobFromXML method tries to load the data before the LoadPlaceholderContent method of the placeholder control fires. So a different approach needs to be implemented: the custom personalization provider needs to read the content of the placeholder directly.
As there is a need to allow the personalization provider to find the placeholder object used to store the personalization data different approaches could have been used. E.g. hard coding the name of the placeholder definition, adding an entry to the AppSettings section of the web.config or to hard code the name of the placeholder control, to use the FindControl method of the HttpHandler and then to read the name of the PlaceholderToBind property of the placeholder control to get the name of the placeholder that holds the personalization data.
I personally would have used the first or second approach while my collegue decided to use the third approach.
So with a combination of a custom placeholder control and a custom personalization provider it is possible to get all the benefits of MCMS and ASP.NET 2.0 Web Parts.
Ali: Thanks for providing the code and the related material for this!