<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Maxime Bombardier - SharePoint Architecture &amp; Development : Web Content Management</title><link>http://blogs.msdn.com/maximeb/archive/tags/Web+Content+Management/default.aspx</link><description>Tags: Web Content Management</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>BlobCache, Style Library, and anonymous users</title><link>http://blogs.msdn.com/maximeb/archive/2009/08/11/blobcache-style-library-and-anonymous-users.aspx</link><pubDate>Tue, 11 Aug 2009 14:36:24 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9864226</guid><dc:creator>MaximeB</dc:creator><slash:comments>3</slash:comments><comments>http://blogs.msdn.com/maximeb/comments/9864226.aspx</comments><wfw:commentRss>http://blogs.msdn.com/maximeb/commentrss.aspx?PostID=9864226</wfw:commentRss><description>&lt;p&gt;As a follow-up to Chris O’Brien’s posts regarding BlobCache and 304s, which can be found &lt;a href="http://www.sharepointnutsandbolts.com/2009/05/more-on-optimization-http-304s-etc.html"&gt;here&lt;/a&gt; and &lt;a href="http://www.sharepointnutsandbolts.com/2009/05/optimization-blob-caching-and-http-304s.html"&gt;here&lt;/a&gt;, I wanted to clarify the situation as to when you may have 304s.&lt;/p&gt;  &lt;p&gt;By default, the Style Library (and Master Pages gallery for that matter) is breaking permission inheritance.&amp;#160; However, during its creation, the &lt;a href="http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.splist.alloweveryoneviewitems.aspx"&gt;SPList.AllowEveryoneViewItems&lt;/a&gt; property is set to true – thus giving anonymous users access – remember, the list is created before anonymous access is given, this property thus simplifies giving access to everyone during creation. &lt;/p&gt;  &lt;p&gt;If you enable anonymous access (i.e.: Entire Web Site) on the root permission, and you access the site anonymously, you will not be prompted for credentials.&amp;#160; However, when the BlobCache goes through the list’s permissions, it doesn’t find anonymous access and will not serve the request.&lt;/p&gt;  &lt;p&gt;As a result, while the file is saved in the BlobCache directory but not served to the user from &lt;em&gt;that&lt;/em&gt; cache, the cache-control Http Header will still contain “private, max-age=0”.&amp;#160; At the next user request, the browser will validate its cache against the file on the server and return a 304.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h4&gt;Workaround&lt;/h4&gt;  &lt;p&gt;The workaround is simple, the first step is to explicitly &lt;strong&gt;give anonymous access to the Style Library&lt;/strong&gt; – either by resetting to inherit from parent or by giving anonymous access.&amp;#160; The 2nd step is to &lt;strong&gt;clear the BlobCache on &lt;u&gt;all&lt;/u&gt; zones and &lt;u&gt;all&lt;/u&gt; servers&lt;/strong&gt;.&amp;#160; &lt;/p&gt;  &lt;p&gt;The ‘Clear BlobCache’ checkbox in the ‘Object Cache’ page will only clear it for &lt;em&gt;that&lt;/em&gt; zone for &lt;em&gt;that &lt;/em&gt;server – you should clear it either through the &lt;a href="http://blogs.msdn.com/maximeb/archive/2008/08/13/how-to-really-clear-the-blobcache-on-all-servers-in-the-farm.aspx"&gt;web application property&lt;/a&gt;.&amp;#160; Changing the BlobCache directory (in the web.config of all servers for all zones) the BlobCache will also work.&lt;/p&gt;  &lt;p&gt;While Chris’ last post regarding this did essentially provide the workaround, there was some confusion due to the nature of the tests (which can bring false positive or false negative results if you don’t follow steps rigorously), and the cache clearing that may be inaccurate if you do it on the wrong zone/server.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h4&gt;Final note&lt;/h4&gt;  &lt;p&gt;If your WCM portal use files from the Style Library (or any other list you created and set the AllowEveryoneViewItems property) and allows anonymous access, make sure you update the list’s permission and clear the BlobCache on all zones/servers.&amp;#160; This will allow user to cache the files and reduce the server impact (i.e.: the 304s) considerably.&amp;#160; This should be part of your “provide anonymous access” procedure.&lt;/p&gt;  &lt;p&gt;A correctly configured BlobCache is essential to a high performing web site.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9864226" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/maximeb/archive/tags/SharePoint/default.aspx">SharePoint</category><category domain="http://blogs.msdn.com/maximeb/archive/tags/Web+Content+Management/default.aspx">Web Content Management</category></item><item><title>Experiences on using a single farm for developers (WCM)</title><link>http://blogs.msdn.com/maximeb/archive/2009/07/06/experiences-on-using-a-single-farm-for-developers-wcm.aspx</link><pubDate>Mon, 06 Jul 2009 22:42:34 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9820480</guid><dc:creator>MaximeB</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/maximeb/comments/9820480.aspx</comments><wfw:commentRss>http://blogs.msdn.com/maximeb/commentrss.aspx?PostID=9820480</wfw:commentRss><description>&lt;h4&gt;Scenario:&lt;/h4&gt;  &lt;ul&gt;   &lt;li&gt;5-8 developers &lt;/li&gt;    &lt;li&gt;WCM portal with lots of sites (SPWeb) and pages, but not a large database &lt;/li&gt;    &lt;li&gt;Development is focused on Fields, Content Types, Layouts, Web Parts, Controls, HttpModules &lt;/li&gt; &lt;/ul&gt;  &lt;h4&gt;Typical environments:&lt;/h4&gt;  &lt;p&gt;The general recommendation is for developers to have their own virtual machine (or physical machine) that contains a complete SharePoint installation.&amp;#160; There’s a variant where the SQL Server is shared but it will still be several SharePoint farms with a single server in each.&lt;/p&gt;  &lt;p&gt;The problem with these is that you end up with multiple farms to manage.&amp;#160; This can work good for the first deployment but will be difficult for incremental releases.&amp;#160; It can also be good for developers working for different production environments.&amp;#160; &lt;/p&gt;  &lt;p&gt;However, when developers are working for a single production environment, other requirements will come in:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Download content artefacts from Production to Development (especially for WCM or light collaboration scenarios) &lt;/li&gt;    &lt;li&gt;Update all developer environments with new artefacts &lt;/li&gt;    &lt;li&gt;Update all developer environments with new or updated layouts &amp;amp; styles &lt;/li&gt;    &lt;li&gt;Update all environments with a new CU or service pack &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Developers already had those requirements without impacting anyone else:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Update file system files in the web folder (web.config, browser file, etc.) &lt;/li&gt;    &lt;li&gt;Execute an IISRESET &lt;/li&gt;    &lt;li&gt;Update assemblies &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h4&gt;What impact would a single farm have for development?&lt;/h4&gt;  &lt;p&gt;After living with multiple farms using shared resources, I implemented a single farm at a customer.&amp;#160; While there are identifiable caveats, it also bring a lot of value while diminishing overall time spent on maintenance and on bug due to non-synchronized environments.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;For WCM, you will have 2 types of development : 1) content related and 2) pure development artefact.&amp;#160; The first is easy to handle, your web designer can simply work like before and it will &lt;u&gt;generally&lt;/u&gt; not impact anyone else, in fact, it’s beneficial since page layouts will be updated for everyone at the same time.&lt;/p&gt;  &lt;p&gt;The only drawback is that I’ve often seen web designers doing check-ins or publishing layouts to test them.&amp;#160; This isn’t optimal for anyone as it uses more resources on SharePoint and if the layout has a display issue, everyone will have it.&amp;#160; Therefore, some assistance (how-to’s) should be planned to ensure that web designers are working optimal for everyone.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;For Development artefact, it can be a little bit more complicated depending on what type of artefact.&amp;#160; For example, if you are developing a custom SharePoint Field, results will be inconsistent if you add a new field instance to a content type that is used for everyone.&amp;#160; In the same fashion as the previous case, working on a separate site collection (or at least content type) might be a more manageable solution for the few times when you are developing those artefacts.&lt;/p&gt;  &lt;p&gt;In fact, for most cases, it’s the visibility that is more important than the actual change.&amp;#160; The reason for this is that a single developer working on a custom Field or a Web Part will only work on his development machine for obvious reason.&amp;#160; If the farm + web application + site collection are shared, then we may have to create an unused sub-site for testing purposes during the development.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;While this may seem cumbersome, at least on “paper”, it’s actually quite simple and is much simpler to manage than multiple environments.&amp;#160; This allows to have less requirements on the development workstations and resources are shared – the database/disk/backups footprint is lessen.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h4&gt;Mixed topology&lt;/h4&gt;  &lt;p&gt;At the next level, you can have the bulk of your development done in a single shared farm but this doesn’t mean you cannot have 1 or 2 other farms for specific development artefacts if they prove too cumbersome.&amp;#160; For example, you may want to have a specific farm (with content) used for various special operations such as testing new CU/Service Packs, 3rd party tools and solutions, etc.&amp;#160; All without affecting your standard integrated testing environment – it’s still easier to maintain 2 farms than 8-10.&lt;/p&gt;  &lt;p&gt;I had a scenario where we created a development farm for support.&amp;#160; It’s purpose was to test anything else that wasn’t in the standard development line.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h4&gt;Conclusion&lt;/h4&gt;  &lt;p&gt;So far, I’ve had good success with the single farm topology.&amp;#160; There is some added governance to be done while implementing – primarily for developers and web designers – but this ensures that you have a good definition of what type of work is being done and which one you wishes to support.&lt;/p&gt;  &lt;p&gt;On a daily basis, developers didn’t have a negative impact due to improper updates by someone else.&amp;#160; On a longer basis, management was much easier, especially with content updates and patches – we are now 100% positive that everyone sees the same thing.&lt;/p&gt;  &lt;p&gt;While this may not be ideal for some situations, it certainly proved to be working well for WCM development.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9820480" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/maximeb/archive/tags/SharePoint/default.aspx">SharePoint</category><category domain="http://blogs.msdn.com/maximeb/archive/tags/Web+Content+Management/default.aspx">Web Content Management</category><category domain="http://blogs.msdn.com/maximeb/archive/tags/SharePoint+Architecture+_2600_+Design/default.aspx">SharePoint Architecture &amp; Design</category></item><item><title>Fixing absolute URLs for all Alternate Access Mappings (AAM) of Content Editor Web Part with a Control Adapter</title><link>http://blogs.msdn.com/maximeb/archive/2008/12/23/fixing-absolute-urls-for-all-alternate-access-mappings-aam-of-content-editor-web-part-with-a-control-adapter.aspx</link><pubDate>Tue, 23 Dec 2008 16:56:21 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9250044</guid><dc:creator>MaximeB</dc:creator><slash:comments>5</slash:comments><comments>http://blogs.msdn.com/maximeb/comments/9250044.aspx</comments><wfw:commentRss>http://blogs.msdn.com/maximeb/commentrss.aspx?PostID=9250044</wfw:commentRss><description>&lt;p&gt;Hi everyone and sorry for the no-post for several months.&amp;#160; My ‘Draft’ list keeps piling but I didn’t take the time to unpile it much.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Anyhow, I came across this problem again last week with the out of the box Content Editor Web Part (CEWP).&amp;#160; Basically, if you use the rich html text editing capability, all URLs are absolute.&amp;#160; &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;I came across a similar issue last year while using the HtmlField and Content Deployment where the URLs were still pointing to the authoring web site.&amp;#160; The CEWP was also renowned to have the same issue.&amp;#160; Back then, we had fixed the general issue with a quick HttpModule installing an HttpFilter which was essentially rewriting URLs.&amp;#160; In terms of architecture, I didn’t like the idea but it was a quick fix done in the early hours.&amp;#160; It did the job.&amp;#160; Since then, we removed Content Deployment so we didn’t have the issue anymore, thus we removed the HttpModule.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;While adding new Alternate Access Mappings URLs to the web site, we noticed some link errors with only the CEWP this time.&amp;#160; I looked at past support cases to see if the issue had been resolved in any Cumulative Update (up to December 2008) but no, it’s not.&amp;#160; Apparently, the fix involves so many changes in the source code that it’s too high a risk.&amp;#160; As of right now, it’s not scheduled to be fixed.&amp;#160; The official solutions were :&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Update your CEWP for Publishing Html Fields.&amp;#160; Anyone doing publishing knows that it’s not possible in all scenarios.&amp;#160; If you know all the Html content types, using Html fields is better and recommended, however, in most landing pages, it’s difficult to do. &lt;/li&gt;    &lt;li&gt;After using the Rich Editing capability, go in the source code and update all the links manually.&amp;#160; This is beyond practical that I won’t discuss it. &lt;/li&gt;    &lt;li&gt;Look at 3rd party components.&amp;#160; The only one I found that was readily SharePoint enabled was the one from Telerik : &lt;a href="http://www.telerik.com/products/aspnet-ajax/sharepoint.aspx"&gt;RadEditor&lt;/a&gt;.&amp;#160; It’s a great control that I would recommend for whatever else it does or if you start a new web site.&amp;#160; Unfortunately, the Lite (and free) edition doesn’t seem to support the properties StripAbsoluteAnchorPaths and StripAbsoluteImagesPaths.&amp;#160; The complete version allows you to use these and it’s 1,000$ USD per developer. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;While I’d definitely recommend the RadEditor control, it wasn’t fixing my currently existing pages that uses the CEWP.&amp;#160; My next thought was back to the HttpModule but then I remembered looking at ASP.NET Control Adapters.&amp;#160; &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;ASP.NET Control Adapters is basically a way to modify the Render of a control.&amp;#160; It’s a little bit like inheritance but only for Render AND it allows to inherit Sealed class such as the ContentEditorWebPart class.&amp;#160; Since I was a bit rusted with Control Adapters, I typed in a search for “ContentEditorWebPart ASP.NET Control Adapter” and came across &lt;a href="http://blog.mastykarz.nl/inconvenient-content-editor-web-part/"&gt;this post from Waldek Mastykarz&lt;/a&gt;.&amp;#160; He lays out most of the essential but he essentially strips all absolute URLs and this was impractical in my scenario.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;In most scenario, you’ll want to strip a list of URLs.&amp;#160; In the case of Content Deployment, you’ll want to supply the list of AAMs from the authoring environment (if it’s in the same farm, you could do this programmatically much like what I’m doing in this code but you supply a different URL to the SPWebApplication.Lookup method, if it’s a different farm, supply the list in a config file).&amp;#160; In the case of a single site with multiple AAMs, this code will work great:&lt;/p&gt;  &lt;div style="border-bottom: gray 1px solid; border-left: gray 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: gray 1px solid; cursor: text; border-right: gray 1px solid; padding-top: 4px"&gt;   &lt;div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;     &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;using&lt;/span&gt; System;&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   2:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;using&lt;/span&gt; System.Collections.Generic;&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   3:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;using&lt;/span&gt; System.Text;&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   4:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;using&lt;/span&gt; System.Web;&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   5:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;using&lt;/span&gt; System.Web.UI;&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   6:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;using&lt;/span&gt; System.Web.UI.WebControls;&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   7:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;using&lt;/span&gt; System.Web.UI.Adapters;&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   8:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;using&lt;/span&gt; System.IO;&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   9:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;using&lt;/span&gt; System.Text.RegularExpressions;&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  10:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;using&lt;/span&gt; Microsoft.SharePoint.Administration;&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  11:&lt;/span&gt;&amp;#160; &lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  12:&lt;/span&gt;&amp;#160; &lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  13:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;namespace&lt;/span&gt; MaximeBBlog&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  14:&lt;/span&gt; {&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  15:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; ContentEditorWebPartAdapter : ControlAdapter&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  16:&lt;/span&gt;     {&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  17:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;protected&lt;/span&gt; &lt;span style="color: #0000ff"&gt;override&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; Render(System.Web.UI.HtmlTextWriter writer)&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  18:&lt;/span&gt;         {&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  19:&lt;/span&gt;             StringBuilder sb = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; StringBuilder();&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  20:&lt;/span&gt;             HtmlTextWriter htw = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; HtmlTextWriter(&lt;span style="color: #0000ff"&gt;new&lt;/span&gt; StringWriter(sb));&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  21:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;base&lt;/span&gt;.Render(htw);&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  22:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; output = sb.ToString();&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  23:&lt;/span&gt;&amp;#160; &lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  24:&lt;/span&gt;             List&amp;lt;Uri&amp;gt; alternateUrls = GetAlternateUrls();&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  25:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;foreach&lt;/span&gt; (Uri alternateUrl &lt;span style="color: #0000ff"&gt;in&lt;/span&gt; alternateUrls)&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  26:&lt;/span&gt;             {&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  27:&lt;/span&gt;                 output = output.Replace(alternateUrl.ToString(), &lt;span style="color: #006080"&gt;&amp;quot;/&amp;quot;&lt;/span&gt;);&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  28:&lt;/span&gt;             }&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  29:&lt;/span&gt;&amp;#160; &lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  30:&lt;/span&gt;             writer.Write(output);&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  31:&lt;/span&gt;         }&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  32:&lt;/span&gt;&amp;#160; &lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  33:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; List&amp;lt;Uri&amp;gt; GetAlternateUrls()&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  34:&lt;/span&gt;         {&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  35:&lt;/span&gt;             List&amp;lt;Uri&amp;gt; alternateUrls = (List&amp;lt;Uri&amp;gt;)HttpContext.Current.Cache[&lt;span style="color: #006080"&gt;&amp;quot;AlternateUrls&amp;quot;&lt;/span&gt;];&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  36:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (alternateUrls == &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;)&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  37:&lt;/span&gt;             {&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  38:&lt;/span&gt;                 alternateUrls = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; List&amp;lt;Uri&amp;gt;();&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  39:&lt;/span&gt;&amp;#160; &lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  40:&lt;/span&gt;                 SPWebApplication webApp = SPWebApplication.Lookup(System.Web.HttpContext.Current.Request.Url);&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  41:&lt;/span&gt;                 &lt;span style="color: #0000ff"&gt;foreach&lt;/span&gt; (SPAlternateUrl alternateUrl &lt;span style="color: #0000ff"&gt;in&lt;/span&gt; webApp.AlternateUrls)&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  42:&lt;/span&gt;                 {&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  43:&lt;/span&gt;                     alternateUrls.Add(alternateUrl.Uri);&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  44:&lt;/span&gt;                 }&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  45:&lt;/span&gt;&amp;#160; &lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  46:&lt;/span&gt;                 HttpContext.Current.Cache.Add(&lt;span style="color: #006080"&gt;&amp;quot;AlternateUrls&amp;quot;&lt;/span&gt;, alternateUrls, &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;, DateTime.Now.AddHours(12), System.Web.Caching.Cache.NoSlidingExpiration, System.Web.Caching.CacheItemPriority.Normal, &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;);&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  47:&lt;/span&gt;             }&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  48:&lt;/span&gt;&amp;#160; &lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  49:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; alternateUrls;&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  50:&lt;/span&gt;         }&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  51:&lt;/span&gt;     }&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  52:&lt;/span&gt; }&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;In a nutshell, I’m doing the following:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Create a class inheriting from System.Web.UI.Adapters.ControlAdapter &lt;/li&gt;

  &lt;li&gt;Override the Render method and read the stream’s text (Html) &lt;/li&gt;

  &lt;li&gt;Get the list of AlternateUrls from the current Web Application &lt;/li&gt;

  &lt;li&gt;Keep the list in caching (I did it for 12 absolute hours, you can change that to your liking) &lt;/li&gt;

  &lt;li&gt;Do a simple String.Replace() of the AlternateUrls for a relative url &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;In terms of performance, it’s negligible and it won’t be reprocessed if you have Page Output Caching enabled.&amp;#160; The SPWebApplication.Lookup is also very fast and I’m keeping the list in cache. As for the architecture, it ensures you are only stripping the correct URLs for only that control.&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;You’ll notice that there is no mention of the ContentEditorWebPart so far and that’s because we aren’t inheriting this Web Part.&amp;#160; That’s where the Control Adapter magic starts and you could even attach it to multiple controls if there’s a need!&amp;#160;&amp;#160; To bind it, you need to add (or update if you have one already) a compat.browser file in the App_Browsers folder of your web site.&amp;#160; This file requires the following:&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;div style="border-bottom: gray 1px solid; border-left: gray 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: gray 1px solid; cursor: text; border-right: gray 1px solid; padding-top: 4px"&gt;
  &lt;div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;
    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   1:&lt;/span&gt; &amp;lt;browsers&amp;gt;&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   2:&lt;/span&gt;     &amp;lt;browser refID=&lt;span style="color: #006080"&gt;&amp;quot;Default&amp;quot;&lt;/span&gt;&amp;gt;&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   3:&lt;/span&gt;         &amp;lt;controlAdapters&amp;gt;&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   4:&lt;/span&gt;             &amp;lt;adapter controlType=&lt;span style="color: #006080"&gt;&amp;quot;Microsoft.SharePoint.WebPartPages.ContentEditorWebPart&amp;quot;&lt;/span&gt; adapterType=&lt;span style="color: #006080"&gt;&amp;quot;MaximeBBlog.ContentEditorWebPartAdapter, MaximeBBlog, Version=1.0.0.0, Culture=neutral, PublicKeyToken=febc2e2cb2c3d564&amp;quot;&lt;/span&gt; /&amp;gt;&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   5:&lt;/span&gt;         &amp;lt;/controlAdapters&amp;gt;&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   6:&lt;/span&gt;     &amp;lt;/browser&amp;gt;&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   7:&lt;/span&gt; &amp;lt;/browsers&amp;gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Note: All you need to update is the namespace in both the code and compat.browser file to match your own; as well as signing it with your key.&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;You’ll notice that the DLL is signed, this allows me to deploy it in the GAC (through a WSP for example) and &lt;u&gt;NOT&lt;/u&gt; to require Full trust.&amp;#160; I’m still using WSS_Minimal in fact.&amp;#160; There is &lt;u&gt;NO&lt;/u&gt; requirement for a SafeControl entry in the Web.Config either.&amp;#160; Once your DLL is in the GAC and the compat.browser file in the App_Browsers directory of your web site, that web site will render the ContentEditorWebPart through your class.&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note: if you application domain is already loaded, you may need to recycle it for the update to start working, especially if the page was in the page output already.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;Thanks again to Waldek for his early start on the issue.&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;Cheers!&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9250044" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/maximeb/archive/tags/SharePoint/default.aspx">SharePoint</category><category domain="http://blogs.msdn.com/maximeb/archive/tags/Web+Content+Management/default.aspx">Web Content Management</category><category domain="http://blogs.msdn.com/maximeb/archive/tags/SharePoint+Architecture+_2600_+Design/default.aspx">SharePoint Architecture &amp; Design</category></item><item><title>How to sort the list of sites in the Create Sites page</title><link>http://blogs.msdn.com/maximeb/archive/2008/08/20/how-to-sort-the-list-of-sites-in-the-create-sites-page.aspx</link><pubDate>Wed, 20 Aug 2008 19:51:55 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8881570</guid><dc:creator>MaximeB</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/maximeb/comments/8881570.aspx</comments><wfw:commentRss>http://blogs.msdn.com/maximeb/commentrss.aspx?PostID=8881570</wfw:commentRss><description>&lt;p&gt;In a customer deployment, we had several custom Site Definitions to create (because they have variations) and we started noticing that the list of sites available in the Create Page is sorted in an odd way.&amp;#160; In fact, it's using neither the creation order, the configuration ID, nor the title (which is okay since it's multilingual).&lt;/p&gt;  &lt;p&gt;Using Reflector, I noticed that the page was using the GetAvailableWebTemplates() method of the SPWeb class in order to get its list.&amp;#160; I tried sorting the list like I wanted and then using the SetAvailableWebTemplate() but the list was still being returned in the original sorted way.&lt;/p&gt;  &lt;p&gt;Digging deeper with Reflector, I noticed that it uses the web property &amp;quot;__WebTemplates&amp;quot; and that returns a list of 'All' web templates as well as web templates by LCID.&lt;/p&gt;  &lt;p&gt;Here's the method I created to sort the web's site creation list.&amp;#160; You need to pass an SPWeb, a flag to determine if you want to be recursive, and the LCID of your web.&amp;#160; In my case, I only had All + 1033 in the English, and All + 1036 in French.&amp;#160; If you have multiple languages available in the same site, you may need to update the code a little bit.&lt;/p&gt;  &lt;div style="border-right: gray 1px solid; padding-right: 4px; border-top: gray 1px solid; padding-left: 4px; font-size: 8pt; padding-bottom: 4px; margin: 20px 0px 10px; overflow: auto; border-left: gray 1px solid; width: 101.03%; cursor: text; max-height: 200px; line-height: 12pt; padding-top: 4px; border-bottom: gray 1px solid; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; height: 312px; background-color: #f4f4f4"&gt;   &lt;div style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;     &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; SortWebTemplates(SPWeb web, &lt;span style="color: #0000ff"&gt;bool&lt;/span&gt; recursive, &lt;span style="color: #0000ff"&gt;uint&lt;/span&gt; lcid)&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   2:&lt;/span&gt; {&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   3:&lt;/span&gt;     SPWebTemplateCollection webTemplates = web.GetAvailableWebTemplates(lcid);&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   4:&lt;/span&gt;     StringBuilder sb = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; StringBuilder();&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   5:&lt;/span&gt;&amp;#160; &lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   6:&lt;/span&gt;     Collection&amp;lt;SPWebTemplate&amp;gt; collection = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; Collection&amp;lt;SPWebTemplate&amp;gt;();&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   7:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;foreach&lt;/span&gt; (SPWebTemplate template &lt;span style="color: #0000ff"&gt;in&lt;/span&gt; webTemplates)&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   8:&lt;/span&gt;     {&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   9:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;bool&lt;/span&gt; itemAdded = &lt;span style="color: #0000ff"&gt;false&lt;/span&gt;;&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  10:&lt;/span&gt;&amp;#160; &lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  11:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;for&lt;/span&gt; (&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i = 0; i &amp;lt; collection.Count; i++)&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  12:&lt;/span&gt;         {&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  13:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (template.Title.CompareTo(collection[i].Title) &amp;lt; 0)&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  14:&lt;/span&gt;             {&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  15:&lt;/span&gt;                 collection.Insert(i, template);&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  16:&lt;/span&gt;                 itemAdded = &lt;span style="color: #0000ff"&gt;true&lt;/span&gt;;&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  17:&lt;/span&gt;                 &lt;span style="color: #0000ff"&gt;break&lt;/span&gt;;&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  18:&lt;/span&gt;             }&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  19:&lt;/span&gt;         }&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  20:&lt;/span&gt;&amp;#160; &lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  21:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (!itemAdded)&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  22:&lt;/span&gt;             collection.Add(template);&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  23:&lt;/span&gt;     }&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  24:&lt;/span&gt;&amp;#160; &lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  25:&lt;/span&gt;     sb.Append(&lt;span style="color: #006080"&gt;&amp;quot;&amp;lt;webtemplates&amp;gt;&amp;lt;lcid id=\&amp;quot;all\&amp;quot;&amp;gt;&amp;quot;&lt;/span&gt;);&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  26:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;foreach&lt;/span&gt; (SPWebTemplate webTemplate &lt;span style="color: #0000ff"&gt;in&lt;/span&gt; collection)&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  27:&lt;/span&gt;     {&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  28:&lt;/span&gt;         sb.Append(&lt;span style="color: #006080"&gt;&amp;quot;&amp;lt;webtemplate name=\&amp;quot;&amp;quot;&lt;/span&gt; + webTemplate.Name + &lt;span style="color: #006080"&gt;&amp;quot;\&amp;quot; /&amp;gt;&amp;quot;&lt;/span&gt;);&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  29:&lt;/span&gt;     }&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  30:&lt;/span&gt;     sb.Append(&lt;span style="color: #006080"&gt;&amp;quot;&amp;lt;/lcid&amp;gt;&amp;lt;lcid id=\&amp;quot;&amp;quot;&lt;/span&gt; + lcid.ToString() + &lt;span style="color: #006080"&gt;&amp;quot;\&amp;quot;&amp;gt;&amp;quot;&lt;/span&gt;);&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  31:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;foreach&lt;/span&gt; (SPWebTemplate webTemplate &lt;span style="color: #0000ff"&gt;in&lt;/span&gt; collection)&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  32:&lt;/span&gt;     {&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  33:&lt;/span&gt;         sb.Append(&lt;span style="color: #006080"&gt;&amp;quot;&amp;lt;webtemplate name=\&amp;quot;&amp;quot;&lt;/span&gt; + webTemplate.Name + &lt;span style="color: #006080"&gt;&amp;quot;\&amp;quot; /&amp;gt;&amp;quot;&lt;/span&gt;);&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  34:&lt;/span&gt;     }&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  35:&lt;/span&gt;     sb.Append(&lt;span style="color: #006080"&gt;&amp;quot;&amp;lt;/lcid&amp;gt;&amp;lt;/webtemplates&amp;gt;&amp;quot;&lt;/span&gt;);&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  36:&lt;/span&gt;&amp;#160; &lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  37:&lt;/span&gt;     web.AllProperties[&lt;span style="color: #006080"&gt;&amp;quot;__WebTemplates&amp;quot;&lt;/span&gt;] = sb.ToString();&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  38:&lt;/span&gt;     web.Update();&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  39:&lt;/span&gt;&amp;#160; &lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  40:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (recursive &amp;amp;&amp;amp; web.Webs.Count &amp;gt; 0)&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  41:&lt;/span&gt;     {&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  42:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;foreach&lt;/span&gt; (SPWeb subWeb &lt;span style="color: #0000ff"&gt;in&lt;/span&gt; web.Webs)&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  43:&lt;/span&gt;         {&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  44:&lt;/span&gt;             SortWebTemplates(subWeb, recursive, lcid);&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  45:&lt;/span&gt;             subWeb.Dispose();&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  46:&lt;/span&gt;         }&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  47:&lt;/span&gt;     }&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  48:&lt;/span&gt; }&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;Maxime&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8881570" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/maximeb/archive/tags/SharePoint/default.aspx">SharePoint</category><category domain="http://blogs.msdn.com/maximeb/archive/tags/Web+Content+Management/default.aspx">Web Content Management</category></item><item><title>The power of deleting Content Deployment Jobs &amp; Paths</title><link>http://blogs.msdn.com/maximeb/archive/2008/06/10/the-power-of-deleting-content-deployment-jobs-paths.aspx</link><pubDate>Tue, 10 Jun 2008 15:07:40 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8589810</guid><dc:creator>MaximeB</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/maximeb/comments/8589810.aspx</comments><wfw:commentRss>http://blogs.msdn.com/maximeb/commentrss.aspx?PostID=8589810</wfw:commentRss><description>&lt;p&gt;For the past few weeks, I have been in parental leave (we just had our first baby girl) and unable to write much.&amp;#160; However, it seems that there was some issues with Content Deployment at work.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Actually, the installation of SP1 and Blackout had been scheduled for a while but it didn't resolve as many issues as we had hoped.&amp;#160; As such, we were still plagued with some &amp;quot;Object Reference Not Set&amp;quot; and &amp;quot;Primary Key constraint violation ...&amp;quot; during the Export phase.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;By calling support, my team was directed to another hotfix (950279), &lt;a href="http://support.microsoft.com/default.aspx/kb/950279"&gt;http://support.microsoft.com/default.aspx/kb/950279&lt;/a&gt; that had been released just after Blackout and we hadn't noticed it.&amp;#160; This is the 3rd hotfix that I remember seeing that fixes &amp;quot;Primary Key constraint violation...&amp;quot;.&amp;#160; &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;What you need to know about these errors is that they are mostly generic.&amp;#160; Also, it's not by exporting the content and importing it in your dev environment that you will be able to reproduce the issue.&amp;#160; The error is &amp;quot;Content Deployment&amp;quot; specific (I didn't check which database hosts the Content Deployment jobs and paths but it's likely to be Configuration, or otherwise Central Administration).&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;By deleting the Jobs &amp;amp; Paths, you will likely remove the issue that causes the Export to fail.&amp;#160; It seems that issues that were still there before the upgrade were still there after.&amp;#160; Also, the thing to know is that, after deleting/recreating the jobs &amp;amp; paths, the next incremental deployment will not have any knowledge of what has been deployed previously and will deploy everything.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;For some reason, the first incremental gave us some issues where we had several 'file already exists with the same name' issues.&amp;#160; I went ahead and deleted the Jobs/Paths again, did a Full Content Deployment once, and all other deployments have been Incremental and running fine.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;So unless you have no problem installing hotfixes (privates and/or publics), I would try this simple no-risk step before installing anything in production.&amp;#160; While, in some situation, it may only be a temporary solution, it may buy you enough time to test the hotfix deployment in your environments and hopefully wait for a public fix or even a Service Pack.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Maxime&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8589810" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/maximeb/archive/tags/SharePoint/default.aspx">SharePoint</category><category domain="http://blogs.msdn.com/maximeb/archive/tags/Web+Content+Management/default.aspx">Web Content Management</category><category domain="http://blogs.msdn.com/maximeb/archive/tags/Content+Deployment/default.aspx">Content Deployment</category></item><item><title>Updating site parameters using the API may freeze the variation job</title><link>http://blogs.msdn.com/maximeb/archive/2008/04/26/updating-site-parameters-using-the-api-may-freeze-the-variation-job.aspx</link><pubDate>Sat, 26 Apr 2008 16:32:02 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8427302</guid><dc:creator>MaximeB</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/maximeb/comments/8427302.aspx</comments><wfw:commentRss>http://blogs.msdn.com/maximeb/commentrss.aspx?PostID=8427302</wfw:commentRss><description>&lt;p&gt;As you probably know if you read my blog, we like to automate as much as we can our WCM portal deployments.&amp;nbsp; One of the thing we do is to update the Publishing Navigation to hide some sites/pages or simply re-order them correctly.&amp;nbsp; Unfortunately, when you have variations and you want to automate this for all languages, you have to specify some kind of "sleep" time so that it waits for the Variation Timer Job to kick in and create the site in all labels.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;Obviously, the sleep time period is guess work and is different on all servers (even on the same one!).&amp;nbsp; During the first attempts, our sleep timer was rather low and we noticed that if we tried opening a site in a target variation/label while the variation process was doing its work, the process was simply stopping!&amp;nbsp; I tried restarting the OWSTIMER service, rebooting the server, wait a day ... but no luck, it simply wasn't picking up again.&amp;nbsp; The Timer Job definitions were still 'running' every minutes, they simply didn't check if there was any updates to propagate.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;Unfortunately, so far, I haven't found a way to fix it and to be honest, we simply delayed running our updates on all labels to a later stage.&amp;nbsp; While I did take a look at trying to 'kick start' the process, I didn't go very deep and if I have the issue again, I'll try &lt;a href="http://stsadm.blogspot.com/2008/04/fix-variation-relationships-list.html" target="_blank"&gt;Gary Lapointe's variation relationship fix&lt;/a&gt; (which is VERY interesting and practical even if you don't have the issue I outlined here).&amp;nbsp; If that doesn't work, I'll go see if the relationship are created anyway but it's the Timer Job that cannot read them anymore.&amp;nbsp; I'll update the post when I have the time to reproduce the error and debug it.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;Maxime&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8427302" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/maximeb/archive/tags/SharePoint/default.aspx">SharePoint</category><category domain="http://blogs.msdn.com/maximeb/archive/tags/Web+Content+Management/default.aspx">Web Content Management</category><category domain="http://blogs.msdn.com/maximeb/archive/tags/Variations/default.aspx">Variations</category></item><item><title>Deployment lifecycle when using Site Definitions and Features (including post production day)</title><link>http://blogs.msdn.com/maximeb/archive/2008/02/23/deployment-lifecycle-when-using-site-definitions-and-features-including-post-production-day.aspx</link><pubDate>Sat, 23 Feb 2008 16:14:22 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:7857203</guid><dc:creator>MaximeB</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/maximeb/comments/7857203.aspx</comments><wfw:commentRss>http://blogs.msdn.com/maximeb/commentrss.aspx?PostID=7857203</wfw:commentRss><description>&lt;h4&gt;&lt;strong&gt;Summary &lt;/strong&gt;&lt;/h4&gt; &lt;p&gt;As you have noticed, I've changed my latest SharePoint focus to look at Site Definitions (and obviously Features but I played with them a lot prior to this).&amp;nbsp; The reason for this is that I was looking at the "best" way to deploy artifacts for SharePoint WCM portals.&amp;nbsp; While I had a very good working solution prior to me playing more with Site Definitions, I now think that I am ready to handle the task much better.&amp;nbsp; This is also a follow-up to a previous article : &lt;a href="http://blogs.msdn.com/maximeb/archive/2008/01/13/real-life-team-based-development-for-web-content-management-with-sharepoint-2007.aspx" target="_blank"&gt;http://blogs.msdn.com/maximeb/archive/2008/01/13/real-life-team-based-development-for-web-content-management-with-sharepoint-2007.aspx&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;The reason for this is that there is no single way to deploy SharePoint artifacts.&amp;nbsp; Worst, once you deployed the first time, your original mechanism may not work anymore or if it does, it's probably not what you should use!&amp;nbsp; What I'll attempt to do here is to define a few SharePoint artifacts that we deploy in a Web Content Management scenario for both production day and post production day, as well as the deployment lifecycle for the developers pre-production-day and post-production-day.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;h4&gt;&lt;strong&gt;SharePoint artifacts we'll cover:&lt;/strong&gt;&lt;/h4&gt; &lt;ul&gt; &lt;li&gt;Master pages&lt;/li&gt; &lt;li&gt;Page Layouts&lt;/li&gt; &lt;li&gt;CSS / JavaScripts / Images (for the masterpages and layouts)&lt;/li&gt; &lt;li&gt;Site Columns &amp;amp; Site Content Types&lt;/li&gt; &lt;li&gt;Library content types association&lt;/li&gt; &lt;li&gt;Custom Lists&lt;/li&gt; &lt;li&gt;Event Handlers on libraries&lt;/li&gt; &lt;li&gt;Feature Receivers&lt;/li&gt; &lt;li&gt;Timer jobs&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;h4&gt;&lt;strong&gt;SharePoint topics discussed: &lt;/strong&gt;&lt;/h4&gt; &lt;ul&gt; &lt;li&gt;Site Definitions&lt;/li&gt; &lt;li&gt;Features&lt;/li&gt; &lt;li&gt;Variations&lt;/li&gt; &lt;li&gt;Feature Stapling&lt;/li&gt; &lt;li&gt;Timer Jobs&lt;/li&gt; &lt;li&gt;Content Deployment&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;h4&gt;&lt;strong&gt;Why Site Definitions?&lt;/strong&gt;&lt;/h4&gt; &lt;p&gt;The timing of me digging Site Definitions more and this post, &lt;a href="http://www.andrewconnell.com/blog/archive/2008/02/15/You-dont-need-to-create-site-definitions.aspx" target="_blank"&gt;http://www.andrewconnell.com/blog/archive/2008/02/15/You-dont-need-to-create-site-definitions.aspx&lt;/a&gt;,&amp;nbsp; from Andrew Connell was interesting.&amp;nbsp; First of all, he's right, you do not need to create a Site Definition all the time.&amp;nbsp; However, there are also general guidelines.&amp;nbsp; When you look at the Publishing portal that is available out of the box, it really looks like a good sample for reverse-engineering (and believe me, I opened it often to learn stuff!).&amp;nbsp; How often have you kept the original "Press Releases" sub-site or used "Blueband" or any other master for your site?&amp;nbsp; What Andrew mentions is that you should create your own minimal publishing site or you can take a look at this one &lt;a href="http://www.codeplex.com/features" target="_blank"&gt;here&lt;/a&gt; on CodePlex but I suggest you still take it apart with your requirements.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;Also, I'm almost always in a multilingual scenario (i.e.: SharePoint Variations) and then Site Definitions takes its full meaning.&amp;nbsp; Why? well the Variation mechanism is really just a system that provision sites.&amp;nbsp; It is &lt;strong&gt;&lt;em&gt;not&lt;/em&gt;&lt;/strong&gt; a copy of the source site.&amp;nbsp; When the variation timer job kicks in, it will detect a new site in the source variation.&amp;nbsp; When it reads it, it takes the title, the description, the URL and the Site Template (i.e.: site definition).&amp;nbsp; Then it simply does a standard Create Site... with those parameters.&amp;nbsp; Once that is done, it will replicate only the &lt;strong&gt;publishing fields of the welcome page&lt;/strong&gt;.&amp;nbsp; Last, it will provision the other publishing pages the same way and replicate only the publishing fields on those pages.&amp;nbsp; &lt;strong&gt;Note that any customization done manually at the source, beside publishing pages and fields, will NOT be brought to the other variations.&amp;nbsp; That includes libraries undefined in the site definitions, documents or images, versioning settings, workflows, and everything else you see in the user interface that isn't a publishing field!&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;I think my last sentence was obvious enough that if you customize something at the source, you will customize it again at the destination.&amp;nbsp; While there may be scenarios when you might want this, it'll be unusual and the solution is to use Site Definitions so that the provisioning brings as much as possible.&lt;/p&gt; &lt;p&gt;&lt;br&gt;I'll finish this section with an example: today, if you have a Publishing site with the OOB site definition and that your welcome pages aren't "WelcomeLinks", what do you do?&amp;nbsp; First of all, at the source, you created a new page with your layout.&amp;nbsp; Then you updated the welcome page of your site to your new page and deleted the old "default.aspx".&amp;nbsp; Now all your welcome pages are not "default.aspx" but it's no big deal.&amp;nbsp; When you created a 2nd variation label, all the default.aspx/WelcomeLinks are back and they are the welcome pages of your sites in that variation!!&amp;nbsp; So you again updated the welcome page and deleted the default.aspx.&amp;nbsp; That's not very user friendly.&amp;nbsp; Also, if you wanted to ended up renaming your custom page to "default.aspx", the variation mechanism would break when trying to provision the site since it's the name for the WelcomeLinks.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;As you can see, Site Definitions becomes a must when using variations.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;h4&gt;&lt;strong&gt;What defines a Site Definitions?&lt;/strong&gt;&lt;/h4&gt; &lt;p&gt;First of all, there is no golden rule for this but here's what I personally follow to determine if I use the same definition or a new one:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;A different welcome page layout&lt;/li&gt; &lt;li&gt;I want to pre-provision a default set of web parts in a welcome page layout&lt;/li&gt; &lt;li&gt;(f) I want to associate specific content types to libraries&lt;/li&gt; &lt;li&gt;(f) I want to allow specific page layouts creation (i.e.: a "news" only section, a "product" only section, etc.)&lt;/li&gt; &lt;li&gt;(f) I want to add special Site Actions for some sites&lt;/li&gt; &lt;li&gt;(f) I want to have a special workflow for some sites&lt;/li&gt; &lt;li&gt;(f) I want to update library settings for some sites&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;em&gt;Note that the items prefixed by "(f)" are items where the delivery mechanism is Features but they are associated in some site definitions.&lt;/em&gt;&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;Also, one note that will affect your site definition architecture are Feature Stapling.&amp;nbsp; That functionality is one of the very practical mechanism to apply a feature to a site definition.&amp;nbsp; Unfortunately, it's also "only that".&amp;nbsp; What I mean is that if you have multiple sites with the same definition, it will apply the feature on all those sites.&amp;nbsp; This is great inside a single Site Collection but when your SharePoint farm contains multiple site collections (possibly for different customers), you may not want to apply a feature to all of them.&amp;nbsp; Unfortunately, I do not personally know of a better solution than to create your Site Definitions "per site collection" only (i.e.: in the naming).&amp;nbsp; They will still likely use the same features though.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;And really, when I design Site Definitions, I created a Feature that contains all the Features that I use for ALL sites.&amp;nbsp; That way, my Site Definitions are very small and only contains the customization for that site.&amp;nbsp; Also, I suggest taking a look at this tool to read your sites definitions : &lt;a href="http://blogs.msdn.com/maximeb/archive/2008/02/16/site-definition-viewer-a-windows-net-2-0-tool-to-read-site-definition-and-features-configurations-version-0-1.aspx" target="_blank"&gt;http://blogs.msdn.com/maximeb/archive/2008/02/16/site-definition-viewer-a-windows-net-2-0-tool-to-read-site-definition-and-features-configurations-version-0-1.aspx&lt;/a&gt;.&amp;nbsp; I also created some CMD files to automate development of site definitions and they come in handy to maximize your time.&amp;nbsp; I will post them soon.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&lt;strong&gt;&lt;em&gt;Before taking a look at the SharePoint artifacts, I need to give you a bit of background on how we get the artifacts: We set up a MOSS server only for "web integrators".&amp;nbsp; The Site Collections in there contains the files directly in the database edited through SharePoint Designer.&amp;nbsp; We hooked up an event on the libraries that, when a check-in is done, it brings the file in a Team Foundation Server.&amp;nbsp; Then, we have someone maintaining the build process and when he get the "go" from the web integrators, he builds the feature containing the files and that is sent to the developers for updates and eventually to production.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;h4&gt;&lt;strong&gt;SharePoint artifact deployment - Master Pages - Page Layouts - CSS/JS/Images&lt;/strong&gt;&lt;/h4&gt; &lt;h4&gt;1) Pre-production "day 1"&lt;/h4&gt; &lt;p&gt;You should create a site-scoped Feature containing your master pages and other files (pages layouts and css/js/images).&amp;nbsp; Take a look at the PublishingLayouts for ideas.&amp;nbsp; When this feature is activated on a site collection, it will add the file in the libraries in a ghosted format which means that there are no customization on them.&amp;nbsp; Note that if you ever unghost it at the destination, your feature will never update the file after.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;h4&gt;2) Post-production "day 2+"&lt;/h4&gt; &lt;p&gt;We'll have to define some sub-scenarios but first, let's start that, yes, you &lt;strong&gt;may&lt;/strong&gt; be able to uninstall the feature and reinstall it while using the -force command but I do not recommend it.&amp;nbsp; First, as I just mentioned, if you unghosted a file, it will not be updated.&amp;nbsp; So if you plan on using this technique, make sure you test first.&amp;nbsp; Also, I had some issues with BlobCache with CSS/JS/GIF/JPG but only when they were ghosted, never when unghosted.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Scenario #1 Updates to some/all the files&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;I would suggest creating an STSADM extension that update files defined in your Feature.&amp;nbsp; This extension will unghost the file and it will act as your mechanism to deploy updates.&amp;nbsp; What I use is a simple extension with an Xml input file that defines the files to update.&amp;nbsp; This file simply grows over time since I only append to it.&amp;nbsp; It gives me an added benefit with "change management" since it's not simply a build that picked up all files and sent it in the feature which may contain an update.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Scenario #2 New files&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;If you have new files, you probably have a "business reason" behind.&amp;nbsp; For a new master pages or page layout, is it only for a new type of site (i.e.: defined in a site definition) or would you like to apply it automatically on some/all sites?&amp;nbsp; That you have a new site definition or not, you are likely to have a new feature that brings the file.&amp;nbsp; This feature may contain a Feature Receiver that will do some actions with those files such as :&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Assigning the master page to some sites&lt;/li&gt; &lt;li&gt;Allowing the page layout to be created in some/all sites&lt;/li&gt; &lt;li&gt;If you have a new site definition, you may want to add it in the list of available web templates&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;Once you have your feature, you may want to create another one to staple the first feature with your site definition (some or all of them).&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;For new CSS/JS/images, they are probably used by a new page layout or master to being with so they will go in the same new feature.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;h4&gt;3) Developers Pre/Post production day&lt;/h4&gt; &lt;p&gt;During the initial development phase "pre-production day", developers should update their environment when they need it.&amp;nbsp; Since I have everything in Team Foundation, I created special CMD/Bath files for developers that helps them clean/create a site definition with some sub-sites already pre-populated.&amp;nbsp; This is enough for most cases.&amp;nbsp; It's clean and fast and they are up and running quickly.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;"Post-production day", the site definitions will not be updated (although they can be appended), nor the features, so they should run the same script that add files in the database and install the new features.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;&lt;/strong&gt;&amp;nbsp;&lt;/p&gt; &lt;h4&gt;SharePoint artifact deployment - Site Columns and Site Content types + library association&lt;/h4&gt; &lt;h4&gt;1) Pre-production "day 1"&lt;/h4&gt; &lt;p&gt;Feature is the best mechanism to bring columns and content types.&amp;nbsp; Note that the feature has to be Site scoped so it will not bring the content types to a library unless you &lt;em&gt;manually create a page through the GUI&lt;/em&gt; or that you use a content type association feature in your site definition.&amp;nbsp; You can take a look at &lt;a href="http://www.andrewconnell.com/blog/archive/2007/10/29/My-MOSS-WCM-STSADM-custom-commands-have-been-updated.aspx" target="_blank"&gt;Andrew Connell's STSADM extension&lt;/a&gt; for a good sample of exporting your columns/content types.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;h4&gt;2) Post-production "day 2+"&lt;/h4&gt; &lt;p&gt;Well we learned the hard way, since the MSDN documentation wasn't available back then, that if you add a column to a content type (in a feature), a "reinstall" of the feature will only bring the new column at the Site Collection level and it will not be replicated down to each libraries using that content type.&amp;nbsp; Fortunately, the user interface works great so if you do not have many columns to add, you may simply want to document the manual update. &lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;But you know I like automation ... so yes, we are also fortunate with the API and it replicates down the change as well.&amp;nbsp; An STSADM extension that adds column + associate it to a content type can be done easily so that it reads an Xml input file with all the updates since Day 1.&amp;nbsp; When it runs, if the column's already there, it simply skips it and go check if the content type contains the association to it.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;h4&gt;3) Developers Pre/Post production day&lt;/h4&gt; &lt;p&gt;The same process will apply for developers.&amp;nbsp; However, since the "STSADM extension" isn't created until Day 1, they may either recreate their site collection or manually add the column/content types when a change occurs.&amp;nbsp; In my case, since creating a site definition is scripted, it goes very fast.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;h4&gt;&lt;strong&gt;SharePoint artifact deployment - Custom lists&lt;/strong&gt;&lt;/h4&gt; &lt;h4&gt;1) Pre-production "day 1"&lt;/h4&gt; &lt;p&gt;A custom list is defined in a feature.&amp;nbsp; The definition contains the columns and types.&amp;nbsp; An instance of a list is defined in a Site Definition or through the user interface.&amp;nbsp; You can also populate rows of data for an instance of a list defined in the Site Definition.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;h4&gt;2) Post-production "day 2+"&lt;/h4&gt; &lt;p&gt;That one is tricker, you can update and reinstall the feature.&amp;nbsp; However, that will only affect new list creation.&amp;nbsp; I personally haven't gotten the need to add columns and data to a list post-production but I would likely need another little STSADM extension to update it.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;h4&gt;3) Developers Pre/Post production day&lt;/h4&gt; &lt;p&gt;Same process as the content types, if it's only a feature, then reinstall it.&amp;nbsp; If it's in the site definition, run the creation script.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;&lt;/strong&gt;&amp;nbsp;&lt;/p&gt; &lt;h4&gt;&lt;strong&gt;SharePoint artifact deployment - Event Handlers, Feature Receivers, and Timer Jobs&lt;/strong&gt;&lt;/h4&gt; &lt;h4&gt;1) Pre-production "day 1"&lt;/h4&gt; &lt;p&gt;All of these are class items.&amp;nbsp; You may want to run code for a specific event on a library, run code when a feature's activated, or run code through a timer job at a specific time.&amp;nbsp; All of them are also originally brought through a feature.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;h4&gt;2) Post-production "day 2+"&lt;/h4&gt; &lt;p&gt;Now, this can be either very easy or much harder depending on how "politically correct" you want to be.&amp;nbsp; Technically (or less politically correct), the classes are either in the BIN or the GAC, if you need to update the code, you can simply deploy them without touching anything in SharePoint (beside an application recycling or an IISRESET).&amp;nbsp; &lt;em&gt;That is, only if you kept the same assembly version.&lt;/em&gt;&amp;nbsp; &lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;Unfortunately, if you want to be more politically correct, you'd have to change the feature, since it contains the assembly version, and reinstall it but there are cases when it seems that some references are "ghosted" somewhere in a database so it may not work.&amp;nbsp; If you want to be politically correct (and normally, we should) with assembly versions, I would strongly suggest doing tests.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;h4&gt;3) Developers Pre/Post production day&lt;/h4&gt; &lt;p&gt;For pre-production day, it's easy, the version isn't likely to change much so you are good to deploy the DLL and reset IIS/app pool.&amp;nbsp; Post production day will depend on what you chose in scenario 2.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;h3&gt;Content Deployment with all this&lt;/h3&gt; &lt;p&gt;As long as your site definitions, features, and assemblies are all deployed at the destination, Content Deployment will work great with your artifacts.&amp;nbsp; Sounds simple but even with all my run-ins with Content Deployment, it works good in that scenario.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;Hope it helps a bit.&amp;nbsp; I know it's a bit sad that there isn't a "single scenario" and I'm still using STSADM extensions to do some updates, but remember, most of the updates are doable from either SharePoint Designer or the web user interface.&amp;nbsp; These 2 tools works good for the updates.&amp;nbsp; Unfortunately, this version of the product doesn't seem to include the fact that field WCM deployments often have a more rigid and secure environment and SPD users aren't likely to play in production or even staging.&amp;nbsp; That's when we, developers, want to automate the process and that's when we create STSADM extensions to fill the gap.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;Maxime&lt;/p&gt; &lt;p&gt;&lt;embed src="http://card.mygamercard.net/Mumren.swf" width="198" height="135" type="application/x-shockwave-flash" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"&gt;&lt;/embed&gt;&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=7857203" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/maximeb/archive/tags/SharePoint/default.aspx">SharePoint</category><category domain="http://blogs.msdn.com/maximeb/archive/tags/Web+Content+Management/default.aspx">Web Content Management</category><category domain="http://blogs.msdn.com/maximeb/archive/tags/STSADM+Extensions/default.aspx">STSADM Extensions</category><category domain="http://blogs.msdn.com/maximeb/archive/tags/Variations/default.aspx">Variations</category><category domain="http://blogs.msdn.com/maximeb/archive/tags/EventHandlers/default.aspx">EventHandlers</category><category domain="http://blogs.msdn.com/maximeb/archive/tags/Content+Deployment/default.aspx">Content Deployment</category><category domain="http://blogs.msdn.com/maximeb/archive/tags/SharePoint+Architecture+_2600_+Design/default.aspx">SharePoint Architecture &amp; Design</category><category domain="http://blogs.msdn.com/maximeb/archive/tags/Site+Definitions+and+Features/default.aspx">Site Definitions and Features</category></item><item><title>Debugging Content Deployment issues</title><link>http://blogs.msdn.com/maximeb/archive/2008/02/19/debugging-content-deployment-issues.aspx</link><pubDate>Tue, 19 Feb 2008 04:56:20 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:7784795</guid><dc:creator>MaximeB</dc:creator><slash:comments>7</slash:comments><comments>http://blogs.msdn.com/maximeb/comments/7784795.aspx</comments><wfw:commentRss>http://blogs.msdn.com/maximeb/commentrss.aspx?PostID=7784795</wfw:commentRss><description>&lt;p&gt;&lt;em&gt;(Last updated June 17th with the Object Reference Not Set to an Instance)&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;SharePoint's Content Deployment feature is a very complex functionality that, unfortunately, does not work all the time.&amp;#160; I've had scenarios where it ran very smoothly and I've had other scenarios (albeit similar in terms of architecture and design) that simply seems to have a different issue everyday.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;What I'll attempt here is to include a few ways of debugging Content Deployment as well as links to fixes (or at least, known issues).&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h3&gt;Is the error reproducible?&lt;/h3&gt;  &lt;p&gt;First of all, is the error reproducible.&amp;#160; If it's not, then it'll make it harder to determine the issue but I've had cases where we could still work it out.&amp;#160; If it is reproducible, I'd suggest 2 things:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;strong&gt;Use STSADM -o export [...] and STSADM -o import [...]&lt;/strong&gt;&amp;#160;&amp;#160; These commands are essentially a Full Content Deployment but it's also a little bit more verbose and you may be able to get the exact error and item. &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Open the exported CAB file&lt;/strong&gt; and look at the item that's failing.&amp;#160; For example, if you successfully 6872 objects, look at the 6873e object in the CAB file.&amp;#160; (note that this also works if the error is not reproducible)&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h3&gt;Look at the ULS logs&lt;/h3&gt;  &lt;p&gt;The Unified Logging System (ULS) logs may contain more information regarding your issue.&amp;#160; Look at the logs at the same &amp;quot;time&amp;quot; and see if you have more information depending on the type of error and how verbose you are logging.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h3&gt;Look at the Windows Event Log&lt;/h3&gt;  &lt;p&gt;For some reason, since we have SharePoint logs, we tend to go less often in the Windows Event Logs.&amp;#160; It's actually surprising how much more relevant the information can be there and it's also easier to search on an event ID than a string, especially if you have a localized error message.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Unfortunately, a default installation of SharePoint may also bring a lot of errors in the event log (that could be .NET errors, DCOM errors, etc.) so I would suggest taking a look at it before going to production and apply any other fixes that would help.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h3&gt;Run SPSReport, especially if you plan on opening a support call&lt;/h3&gt;  &lt;p&gt;You can download it here : &lt;a href="http://www.codeplex.com/spsreport"&gt;http://www.codeplex.com/spsreport&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h3&gt;Try between Incremental &amp;amp; Full Content Deployments&lt;/h3&gt;  &lt;p&gt;Okay, that's not a funny one but I've had cases where I had a reproducible error during incremental and we couldn't figure out why.&amp;#160; We ran a Full Content Deployment and the error disappeared for a couple weeks.&amp;#160; I had the opposite cases too though :)&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;While this may seem trivial, I often forget to look at the CAB file myself so I guess it's possible that not everyone knows about it; same with the Event Log.&amp;#160; Hopefully, they will give you enough information to find out which item is breaking your deployment or if a fix is available.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h3&gt;&lt;strong&gt;Read the exported Manifest.xml file&lt;/strong&gt;&lt;/h3&gt;  &lt;p&gt;The manifest file contains all deployed objects and may help determining which of them broke.&amp;#160; However, you need it to break during Import because the manifest file is only completed at the end of the Export phase.&amp;#160; Plus, the Incremental jobs almost always delete the file when the content deployment fails (and succeeds).&amp;#160; You can read about it &lt;a href="http://blogs.msdn.com/maximeb/archive/2008/05/16/sharepoint-content-deployment-manifest-reader.aspx"&gt;here&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h2&gt;List of issues I've worked with (&lt;em&gt;with or without fixes, I will update with comments &amp;amp; new issues/fixes&lt;/em&gt;)&lt;/h2&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h3&gt;The given key was not present in the dictionary. at System.ThrowHelper.ThrowKeyNotFoundException() at System.Collections.Generic.Dictionary`2.get_Item&lt;/h3&gt;  &lt;p&gt;&lt;strong&gt;Solution: &lt;/strong&gt;The Post-SP1 rollup fixes (&lt;a href="http://support.microsoft.com/kb/941422" target="_blank"&gt;WSS&lt;/a&gt;, &lt;a href="http://support.microsoft.com/kb/941274" target="_blank"&gt;MOSS&lt;/a&gt;) are fixing this.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;/strong&gt;&amp;#160;&lt;/p&gt;  &lt;h3&gt;Save Conflict Your changes conflict with those made concurrently by another user&lt;/h3&gt;  &lt;p&gt;&lt;strong&gt;Solution: &lt;/strong&gt;None yet, often case, a following Content Deployment may work.&amp;#160; I have to check at the CAB file for this one but I didn't get the chance&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;h3&gt;&amp;#160;&lt;/h3&gt;  &lt;h3&gt;The specified file is already used&lt;/h3&gt;  &lt;p&gt;&lt;strong&gt;Solution: &lt;/strong&gt;Delete the file and create it under another name; or delete it, deploy, and recreate it.&amp;#160; Also, the new post-SP1 WSS roll-up may fix this as it seems to fix it for lists (hopefully list items as well) : &lt;a href="http://support.microsoft.com/kb/941422/en-us"&gt;KB941422&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;I also documented this one here : &lt;a href="http://blogs.msdn.com/maximeb/archive/2007/11/20/incremental-content-deployment-completes-successfully-with-errors-mentioning-that-the-name-is-already-is-used.aspx"&gt;http://blogs.msdn.com/maximeb/archive/2007/11/20/incremental-content-deployment-completes-successfully-with-errors-mentioning-that-the-name-is-already-is-used.aspx&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h3&gt;Transaction logs are growing fast, especially when using Full Content Deployment&lt;/h3&gt;  &lt;p&gt;&lt;strong&gt;Solution: &lt;/strong&gt;While this seems to be by design, you can limit the transaction log file by using a SQL &amp;quot;Simple&amp;quot; recovery mode.&amp;#160; However, it also means that you can only recover your database with a backup (not with a backup + log backup).&amp;#160; Also, Database Mirroring requires a Full recovery mode.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h3&gt;Object reference not set to an instance during export&lt;/h3&gt;  &lt;p&gt;&lt;strong&gt;Solution: &lt;/strong&gt;The .NET Framework 2.0 SP1 fixes an instance of that issue (related to memory issues).&amp;#160; However, there's another case when you have a Quick Deploy job running while you flag a page to be quick deployed.&amp;#160; You can read it &lt;a href="http://blogs.msdn.com/maximeb/archive/2008/06/17/content-deployment-and-object-reference-not-set-to-an-instance.aspx"&gt;here&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;I noticed &amp;quot;Unhandled Exception: System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.&amp;quot; messages in the ULS logs and Event Logs. See &lt;a href="http://support.microsoft.com/kb/923028"&gt;KB923028&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h3&gt;Full Content Deployment may be slower after installing SP1&lt;/h3&gt;  &lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; None yet, not a &amp;quot;known issue&amp;quot;&lt;/p&gt;  &lt;p&gt;I documented this one here : &lt;a href="http://blogs.msdn.com/maximeb/archive/2008/02/13/make-sure-you-test-your-content-deployment-after-installing-sp1.aspx"&gt;http://blogs.msdn.com/maximeb/archive/2008/02/13/make-sure-you-test-your-content-deployment-after-installing-sp1.aspx&lt;/a&gt;.&amp;#160; I basically ran some performance tests (after noticing a performance degradation) after installing SP1 and got some concerns.&amp;#160; &lt;em&gt;Update: Note that in some cases, Anti-Virus software may be the cause to this as well (pre and post SP1).&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h3&gt;HTTP (400) Bad request, Invalid Hostname or &amp;quot;the file type is blocked&amp;quot; ... error message&lt;/h3&gt;  &lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; Configure your SharePoint Alternate Access Mappings (AAM) for your site so that the default zone for the Central Administration isn't load balanced; or configure IIS so that it responds when the server name and port number are used instead of the load balanced URL.&lt;/p&gt;  &lt;p&gt;I documented this one here : &lt;a href="http://blogs.msdn.com/maximeb/archive/2008/01/28/central-administration-and-alternate-access-mapping-aam-issues-with-content-deployment-and-sp1.aspx"&gt;http://blogs.msdn.com/maximeb/archive/2008/01/28/central-administration-and-alternate-access-mapping-aam-issues-with-content-deployment-and-sp1.aspx&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;&amp;#160; &lt;/p&gt;  &lt;h3&gt;The URL &amp;quot;Style Library/en-us&amp;quot; is invalid&lt;/h3&gt;  &lt;p&gt;&lt;strong&gt;Solution: &lt;/strong&gt;Delete your site collection at the destination, create a Publishing Site at the destination, delete it, and now create a Blank Site.&lt;/p&gt;  &lt;p&gt;I documented this one here : &lt;a href="http://blogs.msdn.com/maximeb/archive/2007/10/10/content-deployment-the-url-style-library-en-us-is-invalid.aspx"&gt;http://blogs.msdn.com/maximeb/archive/2007/10/10/content-deployment-the-url-style-library-en-us-is-invalid.aspx&lt;/a&gt;.&amp;#160; &lt;em&gt;Update: In fact, doing this also creates the correct Timer Jobs for other operations such as Variations to work so it's a requirement.&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h3&gt;The TCP connection was forcibly closed&lt;/h3&gt;  &lt;p&gt;&lt;strong&gt;Solution: &lt;/strong&gt;Run the &amp;quot;Netsh int ip set chimney ENABLED&amp;quot; command; &lt;a href="http://support.microsoft.com/kb/912222"&gt;KB912222&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;I documented this one here : &lt;a href="http://blogs.msdn.com/maximeb/archive/2007/11/17/slow-content-deployment-transportation-tcp-connection-was-forcibly-closed.aspx"&gt;http://blogs.msdn.com/maximeb/archive/2007/11/17/slow-content-deployment-transportation-tcp-connection-was-forcibly-closed.aspx&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h3&gt;Links are updated at the destination and are still pointing on your authoring farm&lt;/h3&gt;  &lt;p&gt;&lt;strong&gt;Solution: &lt;/strong&gt;None officially nor planned so far.&amp;#160; I ended up creating a simple &amp;quot;StringReplacement&amp;quot; HttpModule for a customer.&lt;/p&gt;  &lt;p&gt;I documented this one here : &lt;a href="http://blogs.msdn.com/maximeb/archive/2007/11/20/content-deployment-does-not-fix-links-at-import-when-the-source-has-been-deployed-with-features.aspx"&gt;http://blogs.msdn.com/maximeb/archive/2007/11/20/content-deployment-does-not-fix-links-at-import-when-the-source-has-been-deployed-with-features.aspx&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h3&gt;You cannot perform this action on a checked out document&lt;/h3&gt; &lt;strong&gt;Solution: &lt;/strong&gt;Someone probably checked out a document at the destination.&amp;#160; Unfortunately, the logs do not tell you which document is checked out.&amp;#160; I ended up creating an STSADM extension that would list all checked out documents by anyone.&amp;#160; &lt;em&gt;If anyone knows a CAML query to do this, it would also be an easy way to do it in the Content Structure Reports.&lt;/em&gt;  &lt;br /&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h3&gt;Master pages are not honoured&lt;/h3&gt;  &lt;p&gt;&lt;strong&gt;Solution: &lt;/strong&gt;Install SP1 or create an STSADM extension to update it.&amp;#160; However, note that incremental content deployment will not &amp;quot;erase&amp;quot; your update so you can update it manually at the destination after the initial content deployment.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h3&gt;Violation of Primary Key&lt;/h3&gt;  &lt;p&gt;&lt;strong&gt;Solution&lt;/strong&gt;: Install SP1.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h3&gt;Special characters are not deployed correctly&lt;/h3&gt;  &lt;p&gt;&lt;strong&gt;Solution: &lt;/strong&gt;Install SP1.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;h3&gt;Update : Error 4958: The stream does not support concurrent IO read or write operations&lt;/h3&gt;  &lt;p&gt;&lt;strong&gt;Solution: &lt;/strong&gt;Set the FileMaxSize property to 2MB in the Content Deployment Configuration.&amp;#160; &lt;em&gt;Thanks to Jian Gao for this one.&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;h3&gt;Update : Violation of Primary Key on #ExportObjects &lt;/h3&gt;  &lt;p&gt;&lt;strong&gt;Solution: &lt;/strong&gt;This one occurs sometimes when you modified some files in the Style Library and an exception is thrown early in the Export stage.&amp;#160; If you have this, go in the Style Library of your source web site, click on List settings and then Versioning settings and update the versioning so that it only accepts Major versions (NOT major &amp;amp; minor).&amp;#160; Execute the Content Deployment and it execute fine after.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Maxime&lt;/p&gt;  &lt;p&gt;&lt;embed src="http://card.mygamercard.net/Mumren.swf" width="198" height="135" type="application/x-shockwave-flash" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" /&gt;&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=7784795" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/maximeb/archive/tags/SharePoint/default.aspx">SharePoint</category><category domain="http://blogs.msdn.com/maximeb/archive/tags/Web+Content+Management/default.aspx">Web Content Management</category><category domain="http://blogs.msdn.com/maximeb/archive/tags/Content+Deployment/default.aspx">Content Deployment</category><category domain="http://blogs.msdn.com/maximeb/archive/tags/SharePoint+Architecture+_2600_+Design/default.aspx">SharePoint Architecture &amp; Design</category></item><item><title>Site Definition Viewer - a Windows (.NET 2.0) tool to read Site Definition and Features configurations (version 0.1)</title><link>http://blogs.msdn.com/maximeb/archive/2008/02/16/site-definition-viewer-a-windows-net-2-0-tool-to-read-site-definition-and-features-configurations-version-0-1.aspx</link><pubDate>Sat, 16 Feb 2008 03:15:23 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:7725150</guid><dc:creator>MaximeB</dc:creator><slash:comments>3</slash:comments><comments>http://blogs.msdn.com/maximeb/comments/7725150.aspx</comments><wfw:commentRss>http://blogs.msdn.com/maximeb/commentrss.aspx?PostID=7725150</wfw:commentRss><description>&lt;p&gt;I spent a little bit on time understanding Site Definitions lately, particularly the Publishing ones like BLANKINTERNET.&amp;nbsp; One very frustrating thing is to make sense of all the WEBTEMP* configurations, the site definitions, the features, the features dependencies, and the stapled features ...&amp;nbsp; When you start doing Windows search on a "text containing this Feature GUID" and then you open up a bunch of Notepads, you get lost :)&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;So I created this little Windows application with .NET 2.0. It basically ask you for which Site Definition folder you want to read and it will then create a complete TreeView showing the following information : &lt;/p&gt; &lt;ul&gt; &lt;li&gt;All Site Definition Configurations  &lt;li&gt;All Site Features as well as Web Features  &lt;li&gt;All manifests files in any feature used by the site definition configuration  &lt;li&gt;All receiver classes in any feature used by the site definition configuration  &lt;li&gt;All stapled features to the site definition configuration  &lt;li&gt;All properties for any feature used by the site definition&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;Other features enabled:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;On the feature GUID/NAME, a tooltip will appear with its description  &lt;li&gt;Double-clicking on the site definition configuration will open ONET.XML with your default XML launcher  &lt;li&gt;Double-clicking on a manifest file will open the file with its default launcher (usually XML)  &lt;li&gt;Double-click on a feature name will open the file with your default XML launcher  &lt;li&gt;There's a configuration file if you installed your 12 folder elsewhere, you can also specify the site definition to automatically select (practical if you launch the tool often and want to read the same definition :))&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;** UPDATE ** : I updated the application to not show an error when the feature.xml file doesn't load.&amp;nbsp; Some installations have a few empty folders and I was showing up lots of message boxes.&amp;nbsp; They have been removed.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;iframe scrolling="no" marginheight="0" marginwidth="0" frameborder="0" style="width:240px;height:66px;margin:3px;padding:0;border:1px solid #dde5e9;background-color:#ffffff;" src="http://cid-869ff26f3797a09a.skydrive.live.com/embedrowdetail.aspx/MaximeB-MSDNBlog/SiteDefinitionViewer_v0_2.zip"&gt;&lt;/iframe&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;Here's what it looks like for BLANKINTERNET:&lt;/p&gt; &lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/maximeb/WindowsLiveWriter/Sit.0tooltoreadSiteDefinitionandFeatures_10B87/sitedefinitionviewer_tooltip_2.jpg" target="_blank"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="484" alt="sitedefinitionviewer_tooltip" src="http://blogs.msdn.com/blogfiles/maximeb/WindowsLiveWriter/Sit.0tooltoreadSiteDefinitionandFeatures_10B87/sitedefinitionviewer_tooltip_thumb.jpg" width="625" border="0"&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;You can see here the all files (manifests) defined with the Publishing feature:&lt;/p&gt; &lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/maximeb/WindowsLiveWriter/Sit.0tooltoreadSiteDefinitionandFeatures_10B87/sitedefinitionviewer_manifests_2.jpg" target="_blank"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="484" alt="sitedefinitionviewer_manifests" src="http://blogs.msdn.com/blogfiles/maximeb/WindowsLiveWriter/Sit.0tooltoreadSiteDefinitionandFeatures_10B87/sitedefinitionviewer_manifests_thumb.jpg" width="625" border="0"&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;You can see here the properties for the NavigationProperties feature:&lt;/p&gt; &lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/maximeb/WindowsLiveWriter/Sit.0tooltoreadSiteDefinitionandFeatures_10B87/sitedefinitionviewer_properties_2.jpg" target="_blank"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="484" alt="sitedefinitionviewer_properties" src="http://blogs.msdn.com/blogfiles/maximeb/WindowsLiveWriter/Sit.0tooltoreadSiteDefinitionandFeatures_10B87/sitedefinitionviewer_properties_thumb.jpg" width="625" border="0"&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;You can see that the Publishing feature also defines a receiver class (when you are doing reverse engineering of a feature to understand it, the receiver class is very practical):&lt;/p&gt; &lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/maximeb/WindowsLiveWriter/Sit.0tooltoreadSiteDefinitionandFeatures_10B87/sitedefinitionviewer_receiverclass_4.jpg" target="_blank"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="484" alt="sitedefinitionviewer_receiverclass" src="http://blogs.msdn.com/blogfiles/maximeb/WindowsLiveWriter/Sit.0tooltoreadSiteDefinitionandFeatures_10B87/sitedefinitionviewer_receiverclass_thumb_1.jpg" width="625" border="0"&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;Last, you can see that the PublishingSite and PublishingWeb are stapled to all BLANKINTERNET definitions (even though they are defined in the site definition anyway) :&lt;/p&gt; &lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/maximeb/WindowsLiveWriter/Sit.0tooltoreadSiteDefinitionandFeatures_10B87/sitedefinitionviewer_stapledfeatures_2.jpg" target="_blank"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="484" alt="sitedefinitionviewer_stapledfeatures" src="http://blogs.msdn.com/blogfiles/maximeb/WindowsLiveWriter/Sit.0tooltoreadSiteDefinitionandFeatures_10B87/sitedefinitionviewer_stapledfeatures_thumb.jpg" width="625" border="0"&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;This tool is simply there to help you read all the parameters quickly.&amp;nbsp; It's working fine for me but I haven't done extensive testing and it's not doing everything.&amp;nbsp; Also, I read the WEBTEMP*.xml files in 1033 (english) only but that's also configurable in the configuration file.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;** UPDATE ** : I updated the application to not show an error when the feature.xml file doesn't load.&amp;nbsp; Some installations have a few empty folders and I was showing up lots of message boxes.&amp;nbsp; They have been removed.&lt;/p&gt; &lt;p&gt;&lt;iframe scrolling="no" marginheight="0" marginwidth="0" frameborder="0" style="width:240px;height:66px;margin:3px;padding:0;border:1px solid #dde5e9;background-color:#ffffff;" src="http://cid-869ff26f3797a09a.skydrive.live.com/embedrowdetail.aspx/MaximeB-MSDNBlog/SiteDefinitionViewer_v0_2.zip"&gt;&lt;/iframe&gt; &lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;Maxime&lt;/p&gt; &lt;p&gt;&lt;embed src="http://card.mygamercard.net/Mumren.swf" width="198" height="135" type="application/x-shockwave-flash" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"&gt;&lt;/embed&gt;&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=7725150" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/maximeb/archive/tags/SharePoint/default.aspx">SharePoint</category><category domain="http://blogs.msdn.com/maximeb/archive/tags/Web+Content+Management/default.aspx">Web Content Management</category><category domain="http://blogs.msdn.com/maximeb/archive/tags/SharePoint+Architecture+_2600_+Design/default.aspx">SharePoint Architecture &amp; Design</category><category domain="http://blogs.msdn.com/maximeb/archive/tags/Site+Definitions+and+Features/default.aspx">Site Definitions and Features</category></item><item><title>To Content Deployment or not to Content Deployment, that is the question</title><link>http://blogs.msdn.com/maximeb/archive/2008/02/14/to-content-deployment-or-not-to-content-deployment-that-is-the-question.aspx</link><pubDate>Thu, 14 Feb 2008 04:37:47 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:7683767</guid><dc:creator>MaximeB</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/maximeb/comments/7683767.aspx</comments><wfw:commentRss>http://blogs.msdn.com/maximeb/commentrss.aspx?PostID=7683767</wfw:commentRss><description>&lt;p&gt;As you probably have read, I ran into a couple issues lately with Content Deployment (&lt;a href="http://blogs.msdn.com/maximeb/archive/2008/02/13/make-sure-you-test-your-content-deployment-after-installing-sp1.aspx"&gt;Slow with SP1?&lt;/a&gt;, &lt;a href="http://blogs.msdn.com/maximeb/archive/2008/02/13/setting-major-minor-versions-and-content-deployment-issues.aspx"&gt;major/minor versions&lt;/a&gt;, &lt;a href="http://blogs.msdn.com/maximeb/archive/2008/01/28/central-administration-and-alternate-access-mapping-aam-issues-with-content-deployment-and-sp1.aspx"&gt;AAM on Central Administration&lt;/a&gt;, &lt;a href="http://blogs.msdn.com/maximeb/archive/2007/11/20/incremental-content-deployment-completes-successfully-with-errors-mentioning-that-the-name-is-already-is-used.aspx"&gt;specified file already in used&lt;/a&gt;, &lt;a href="http://blogs.msdn.com/maximeb/archive/2007/11/20/content-deployment-does-not-fix-links-at-import-when-the-source-has-been-deployed-with-features.aspx"&gt;links not fixed at destination&lt;/a&gt;, &lt;a href="http://blogs.msdn.com/maximeb/archive/2007/11/17/slow-content-deployment-transportation-tcp-connection-was-forcibly-closed.aspx"&gt;TCP connection closed&lt;/a&gt;, &lt;a href="http://blogs.msdn.com/maximeb/archive/2007/10/10/content-deployment-the-url-style-library-en-us-is-invalid.aspx"&gt;the requirement to create a publishing site + delete + create a blank site&lt;/a&gt;) along with a few others that I haven't post on yet (since I don't know how to fix them yet!).&amp;nbsp; Errors such as :&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Save Conflict Your changes conflict with those made concurrently by another user  &lt;li&gt;You cannot perform this action on a checked out document  &lt;li&gt;Timed out (at importing)  &lt;li&gt;Object reference not set (during export, I noticed "memory corrupt" exceptions close to the same time it fails; that problem might be fixed with .NET Framework 2.0)  &lt;li&gt;Cannot delete file since it does not exist  &lt;li&gt;Cannot create the file since it already exists at the destination  &lt;li&gt;The SQL Transaction logs are growing up very fast (I had a development environment with a 100 MB web site running a Full Content Deployment every day, yes I forgot I had activated it!, after a month, the transaction log was at 356 GB &amp;lt;-- yes GB and no I don't have backups for that database so that's why the log was so big).&amp;nbsp; it turns out that the Full Content Deployment runs so many queries that the transaction log grows pretty fast if you have Full Recovery (which is required for database mirroring).  &lt;li&gt;Web parts added on a page may not always be there at the destination  &lt;li&gt;and then some more issues that I forgot over time&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;Most of these are either errors that you can happily forget, some are errors that may or may not happen if you restart the deployment, some are "user created" but shouldn't happen, and some I had to create workarounds since no fixes are scheduled.&amp;nbsp; When you look at this, I cannot say that Content Deployment is reliable for that environment.&amp;nbsp; Unfortunately, it's not only for that environment.&amp;nbsp; I was able to experience these random issues with an OOB publishing site that didn't have any added content!&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;I'm in great need of inspiration from the product group on this one because I have a hard time saying that there won't be any issues with Content Deployment to a customer.&amp;nbsp; So I started musing on why we are using Content Deployment in the first place, after all, it's for an Intranet scenario.&amp;nbsp; Normally, you need Content Deployment because you want to have a staging site collection (or farm).&amp;nbsp; Especially for an Internet scenario, you probably want to put the authoring in a DMZ or even internally with your authenticated users secured.&amp;nbsp; Otherwise, you may simply want to limit your authors so that they cannot bring have an error in production easily and you want to validate everything before a content deployment.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;While these are still true, one of my environment is for an Intranet portal so the DMZ point isn't important as the users are authenticated everywhere on the site (and it's personalized).&amp;nbsp; All that's really left are the authors "screwing up" the web site!&amp;nbsp; However, I've seen scenarios where Incremental content deployments are running every 30 minutes ... that doesn't let you validate everything before now, does it?&amp;nbsp; Also, you can always approve a page right before a deployment and still have the issue.&amp;nbsp; So, if you don't need a DMZ, why should it be a best practice to have a staging farm?&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;Let's check what an author can really do to "break" a web site?&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;&lt;em&gt;The author forgot to approve images or linked documents used in the published page&lt;/em&gt;.&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;First of all, they can still run into that issue if they approve the page right before the Content Deployment.&amp;nbsp; 2nd, is content approval required for those images &amp;amp; documents?&amp;nbsp; often case, it's probably not.&amp;nbsp; If it is , then there isn't much to do but have a more rigorous approval process. Otherwise,&amp;nbsp; &lt;strong&gt;Solution : &lt;/strong&gt;don't use the default site definition and create yours where content approval is not required on documents &amp;amp; images (but still is on pages).&amp;nbsp; If you are already deployed, create a feature to set the parameters and staple it to the definitions you used.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;&lt;/strong&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;em&gt;&lt;strong&gt;The author needs to see the page as a visitor prior to approving it.&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Solution :&lt;/strong&gt; there is an option available through the toolbar under where you can view the page even if it's not approved.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;&lt;em&gt;What if the author adds something that shouldn't be there?&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;Well that's why "Approval" is still required.&amp;nbsp; If you activated the Review Workflow because it's the right thing to do but that approving simply means clicking the button, something's not right.&amp;nbsp; I often case have the question "why can't we approve multiple pages at once?".&amp;nbsp; Reality is that they might need "Publishing" instead of approving if they aren't going to check the pages.&amp;nbsp; To get back on track, the &lt;strong&gt;solution&lt;/strong&gt; is to define better workflows and to have more rigorous approvers.&amp;nbsp; It's also good to know that a workflow with multiple &amp;amp; sequential approvers do not actually require "Approvers" permissions, only the last one in the list who will do the actual transition from archived to published.&amp;nbsp; Don't forget that authors are also accountable.&amp;nbsp; While that may not be much once a "negative" page has been sent online, simply knowing this will likely make them think twice before approving or publishing content.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;&lt;em&gt;Can the performance be impacted since authoring pages are usually much bigger?&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;While it's true that editing will use more resources on the servers, the &lt;strong&gt;solution &lt;/strong&gt;is simple : dedicate one of your farm servers for your editors where their DNS directs them there directly and this server isn't returned by the load balancer.&amp;nbsp; If they are on the same DNS server, then you could also create an Alternate Access Mapping to that site, thus a different DNS, that only the authors access.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;&lt;em&gt;There's no need for quick deploy anymore&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;Well that's not a problem but directly a solution where Quick Deploy only works for publishing pages ... if that page references an image or a document, it won't be deployed at the same time.&amp;nbsp; While I'm guessing the feature's meant for updating text on an existing page, it's still annoying for authors to be able to deploy a page but not its images.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Food for thoughts&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;While I obviously "feel safer" to have a staging/authoring farm, in an intranet portal scenario, reality is that those portals are often case close to a collaboration portal without collaboration.&amp;nbsp; What I mean by that is that you are sharing information and documents while you don't need users to collaborate on it.&amp;nbsp; If you thought of it as Collaboration, you wouldn't consider using Content Deployment so why should it be different for a WCM intranet portal with no DMZ requirements?&amp;nbsp; I'm still taking about a portal that's viewed by 10-50k people a day.&amp;nbsp; Any comments?&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;Maxime&lt;/p&gt; &lt;p&gt;&lt;embed src="http://card.mygamercard.net/Mumren.swf" width="198" height="135" type="application/x-shockwave-flash" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"&gt;&lt;/embed&gt;&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=7683767" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/maximeb/archive/tags/SharePoint/default.aspx">SharePoint</category><category domain="http://blogs.msdn.com/maximeb/archive/tags/Web+Content+Management/default.aspx">Web Content Management</category><category domain="http://blogs.msdn.com/maximeb/archive/tags/Content+Deployment/default.aspx">Content Deployment</category><category domain="http://blogs.msdn.com/maximeb/archive/tags/SharePoint+Architecture+_2600_+Design/default.aspx">SharePoint Architecture &amp; Design</category></item><item><title>Make sure you test your Content Deployment after installing SP1...</title><link>http://blogs.msdn.com/maximeb/archive/2008/02/13/make-sure-you-test-your-content-deployment-after-installing-sp1.aspx</link><pubDate>Thu, 14 Feb 2008 02:47:45 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:7682551</guid><dc:creator>MaximeB</dc:creator><slash:comments>7</slash:comments><comments>http://blogs.msdn.com/maximeb/comments/7682551.aspx</comments><wfw:commentRss>http://blogs.msdn.com/maximeb/commentrss.aspx?PostID=7682551</wfw:commentRss><description>&lt;p&gt;I have been testing WSS/MOSS Service Pack 1 on a large-scale WCM portal for the past couple weeks and I ran into some issues with Content Deployment.&amp;nbsp; First of all, I&lt;strong&gt;&lt;u&gt; do not want to say there's necessarily a widespread bug with Content Deployment and SP1&lt;/u&gt;&lt;/strong&gt;.&amp;nbsp; Alright, you are warned :)&amp;nbsp; My goal here is that I do indeed have an issue and we are trying to go through support to eventually have some help from the product group to enlighten us.&amp;nbsp; Since I have this issue and that I do not see anyone opening support cases for the same thing nor people writing about it on the web, I'm assuming that it's working in most scenarios.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;In summary, make sure you test your Full Content Deployments after you install SP1 in your staging environment.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;Now that it's said, let's see why I'm thinking we have an issue.&amp;nbsp; First of all, we experience much more often the "Timed out" issue when using the Content Deployment issue.&amp;nbsp; Sometimes, it keeps going, sometimes, it's not.&amp;nbsp; The environment we are testing currently has been running a SINGLE job of Content Deployment for the last 8, yes EIGHT, days.&amp;nbsp; Since it's importing, the cancel button's not available and we cannot kill the job since it's running.&amp;nbsp; What are we importing?&amp;nbsp; about 100 MB of content with 21,000 objects.&amp;nbsp; It stopped doing anything significant after around 5400 objects.&amp;nbsp; While I would try rebooting the server or playing with a few jobs, I am purposely leaving the server as-is so that the support engineer might be able to realize that there's an issue.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;While we had that issue, the customer (obviously) is asking me if we should install SP1 in production and would we have the same issue.&amp;nbsp; The staging environment is a little bit different (barely) where it's running in a VMWare virtual environment.&amp;nbsp; It has the same content as the production (we did a manual export/import from production to staging).&amp;nbsp; The STSADM extension that limits versions (&lt;a href="http://blogs.msdn.com/maximeb/archive/2008/02/13/setting-major-minor-versions-and-content-deployment-issues.aspx"&gt;described here&lt;/a&gt;) hasn't been ran in staging (it was thought that the export was done after it was ran in production but actually wasn't so we had multiple versions of each pages/documents).&amp;nbsp; So I started working on those 2 differences to see if they had an impact.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;I did the test with 2 machines:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;My development virtual environment running in a VMWare with 2 GB RAM.&amp;nbsp; The SQL server is centralized on a physical killer box and it's running smoothly.&lt;/li&gt; &lt;li&gt;My personal Virtual PC on my laptop (dual-core centrino with 3 GB RAM but 1.7 RAM allocated to the VPC).&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;Since Content Deployment usually takes longer than "import" (and I didn't want to export everytime) since it's often "freezing" on my VMs since SP1, I decided to test with export/import.&amp;nbsp; SO I did an export of a "vanilla site" similar to the production (with much less content) that is about 100 MB (actually the CAB file is compressed at 17MB) and 11,000 objects.&amp;nbsp; I deleted the destination collection on both environments and started the imports.&lt;/p&gt; &lt;ul&gt; &lt;li&gt;on VMWare, the first full import took 1h15min&lt;/li&gt; &lt;li&gt;on VPC, the first full import took 45min&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;So far, not too bad although I would be curious as to why it's taking THAT long for so few elements.&amp;nbsp; I was a bit surprise on the VMWare where it took much longer than my VPC while I was still working with Outlook &amp;amp; IE &amp;amp; Word at the same time.&amp;nbsp; VMWare 0, VPC 1 :)&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;Right after that, I started a 2nd import of the same "export" file again:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;3h30 minutes on the VMWare&lt;/li&gt; &lt;li&gt;2h15 minutes on VPC&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;this is a bit depressing.&amp;nbsp; I have the same content re-imported and it's taking a &lt;em&gt;much&lt;/em&gt; longer time.&amp;nbsp; While I understand it's checking the file ... in most content deployment scenarios, we don't really care, we simply want the same thing at the destination.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;The 3rd time I ran it, I had the following:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;4h on VMWare, 3h on VPC&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;it's going up again!&amp;nbsp; The only differences this time is that there was 2 versions and it's adding a 3rd version!!!&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;I did some SQL profiling and couldn't see any request taking over 40ms (and there was very few of these).&amp;nbsp; I was only checking queries &amp;amp; stored procedures ... and I had over 100,000 lines in less than 5 minutes.&amp;nbsp; While everything seems to be running fine in Network Monitor on all environments, (CPU, disks, memory, network are all green), it's simply not going fast.&amp;nbsp; Maybe it's the sheer amount of queries that are running, I don't know and I do not have answers from the product group yet, but I'm getting more concerned with the feature now.&amp;nbsp; Unfortunately, I haven't run the same type of tests before SP1 so I don't know how bad it was, but I know it wasn't going up exponentially.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;Last, I noticed that it "freezes" every time, at least on the VMWare development boxes (I have over 12) I have.&amp;nbsp; I wondered if it was any customization we'd done so I created an OOB publishing site with barely anything (not even variations which are known to add LOTS of objects in Content Deployment (i.e.: a new site can take 140 objects instead of 3).&amp;nbsp; I have about 1,100 objects and it takes 20+ minutes for a few MBs!!!!&amp;nbsp; The export &amp;amp; transport phases are fast, but the import is really slow.&amp;nbsp; Unfortunately, not only it's slow, it also stops at times.&amp;nbsp; I simply do not see much SQL traffic going on at those times and the objects imported aren't going up.&amp;nbsp; It might do that for 10 minutes and start again!&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;Hopefully I'll have better news in the future regarding this.&amp;nbsp; Until then, I'm hoping it's a problem with my environments only or maybe a VMWare issue that we now have.&amp;nbsp; Just make sure you test with your staging environment before production ...&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;Maxime&lt;/p&gt; &lt;p&gt;&lt;embed src="http://card.mygamercard.net/Mumren.swf" width="198" height="135" type="application/x-shockwave-flash" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"&gt;&lt;/embed&gt;&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=7682551" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/maximeb/archive/tags/SharePoint/default.aspx">SharePoint</category><category domain="http://blogs.msdn.com/maximeb/archive/tags/Web+Content+Management/default.aspx">Web Content Management</category><category domain="http://blogs.msdn.com/maximeb/archive/tags/Content+Deployment/default.aspx">Content Deployment</category><category domain="http://blogs.msdn.com/maximeb/archive/tags/Hotfix/default.aspx">Hotfix</category></item><item><title>Setting Major/Minor versions and Content Deployment issues</title><link>http://blogs.msdn.com/maximeb/archive/2008/02/13/setting-major-minor-versions-and-content-deployment-issues.aspx</link><pubDate>Thu, 14 Feb 2008 02:19:05 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:7682191</guid><dc:creator>MaximeB</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/maximeb/comments/7682191.aspx</comments><wfw:commentRss>http://blogs.msdn.com/maximeb/commentrss.aspx?PostID=7682191</wfw:commentRss><description>&lt;p&gt;Just a quick heads-up when you want to limit versions in a Web Content Management scenario and you have Content Deployment set up.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;First of all, let me explain &lt;em&gt;why&lt;/em&gt; you would like to do this:&amp;nbsp; Basically, if you happen to execute routinely a Full Content Deployment, a new version of &lt;em&gt;every&lt;/em&gt; document (pages, images, document, etc.) at the destination.&amp;nbsp; Since the default library settings are set to accept unlimited major and minor versions, you will likely run into a disk space issue before long.&amp;nbsp; I noticed that on a WCM portal that was planned for about 100 MB of web content that turned out to have 600 MB quickly because not all content had been "web-ified" and was still in PDF and document.&amp;nbsp; That 600 MB was being added at each Full Content Deployment, that a modification occurred or not!&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;So now you have a fully deployed portal with 150+ sub-sites that you want to limit the versions on at least "/documents" and "/images" (and likely "/pages" as well).&amp;nbsp; At the time, we didn't know enough (or anything really) about Feature Stapling to use them so we created an STSADM extension that updates a library's versioning settings (i.e.: does it require approval, the major &amp;amp; minor versions supported, etc.).&amp;nbsp; I would suggest using Feature Stapling for yourself (with the same codebase really) since it will also affect new sites.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;To get back to the primary subject: if you set a major or a minor version limit in the GUI, apply the change, and deploy the update to the publishing farm;&amp;nbsp; then you go back and update to only have a major limit and do not support minors, the GUI will work correctly when you apply.&amp;nbsp; In fact, the "staging or authoring" farm will work correctly.&amp;nbsp; Unfortunately, when you use content deployment, it will say that you cannot set minor version limit on a library that only supports major versions!&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;I happened to know that error exactly since, when creating the STSADM extension, I got that error when playing with the properties in the "wrong" order.&amp;nbsp; It seems that Content Deployment do use the right order either.&amp;nbsp; You will have to remove the version limits, use content deployment, and then update to have only major versions.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;Maxime&lt;/p&gt; &lt;p&gt;&lt;embed src="http://card.mygamercard.net/Mumren.swf" width="198" height="135" type="application/x-shockwave-flash" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"&gt;&lt;/embed&gt;&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=7682191" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/maximeb/archive/tags/SharePoint/default.aspx">SharePoint</category><category domain="http://blogs.msdn.com/maximeb/archive/tags/Web+Content+Management/default.aspx">Web Content Management</category><category domain="http://blogs.msdn.com/maximeb/archive/tags/STSADM+Extensions/default.aspx">STSADM Extensions</category><category domain="http://blogs.msdn.com/maximeb/archive/tags/Content+Deployment/default.aspx">Content Deployment</category></item><item><title>Beware of SPWebProvisioningProvider when using Variations</title><link>http://blogs.msdn.com/maximeb/archive/2008/02/05/beware-of-spwebprovisioningprovider-when-using-variations.aspx</link><pubDate>Tue, 05 Feb 2008 20:22:20 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:7470659</guid><dc:creator>MaximeB</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/maximeb/comments/7470659.aspx</comments><wfw:commentRss>http://blogs.msdn.com/maximeb/commentrss.aspx?PostID=7470659</wfw:commentRss><description>&lt;p&gt;I was doing some research lately on how to have a different "Approvers" group depending on business rule.&amp;nbsp; To make it simple, the following statement had to be fulfilled:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Pages under subsite "/site1" have to be approved by group "Approvers1"  &lt;li&gt;Pages under subsite "/site2" have to be approved by group "Approvers2"  &lt;li&gt;and so on...  &lt;li&gt;We are in a multilingual scenario (i.e.: Variations)&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;we also have custom site definitions for modifying the default welcome page to something else than WelcomeLinks as well as bringing our content types in the library.&amp;nbsp; So the first thing we looked at was to use SPWebProvisioningProvider that allows to execute a class when provisioning a site.&amp;nbsp; You can take a look at these URLs for more explanation on SPWebProvisioningProvider:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;&lt;a href="http://weblogs.asp.net/paulballard/archive/2007/04/09/creating-a-custom-sharepoint-2007-portal-site-definition-using-the-portalprovisioningprovider-class.aspx"&gt;http://weblogs.asp.net/paulballard/archive/2007/04/09/creating-a-custom-sharepoint-2007-portal-site-definition-using-the-portalprovisioningprovider-class.aspx&lt;/a&gt;  &lt;li&gt;(French) &lt;a href="http://blogs.developpeur.org/themit/archive/2007/10/18/sharepoint-deployment-feature-feature-solution-mais-aussi-webprovisioningprovider.aspx"&gt;http://blogs.developpeur.org/themit/archive/2007/10/18/sharepoint-deployment-feature-feature-solution-mais-aussi-webprovisioningprovider.aspx&lt;/a&gt;  &lt;li&gt;&lt;a href="http://www.pings.dk/blog/archive/2007/10/18/create-a-web-provisioner-to-enable-quote-post-site-creation-actions-quote.aspx"&gt;http://www.pings.dk/blog/archive/2007/10/18/create-a-web-provisioner-to-enable-quote-post-site-creation-actions-quote.aspx&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;So basically, a site definition reside in the "onet.xml" file and you cannot define a class in that file.&amp;nbsp; The WEBTEMP*.xml (defined in all "available languages", i.e.: 1033 folder for english) file is the configuration used by the "Create site" interface.&amp;nbsp; This is where you specify your custom class for provisioning a web.&amp;nbsp; The first thing your custom class does is to use ApplyWebTemplate() so that the web site is created with the correct template.&amp;nbsp; Then I was simply modifying the "AssociationData" of the only workflow (Parallel Approval) to update its "Approvers" to my custom one depending on the URL.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;So far, so good.&amp;nbsp; Unfortunately, when you create this under a variation, it only works at the source.&amp;nbsp; The reason for this is that the variation process is only a provisioning mechanism; furthermore, it's only provisioning based on the site definition, not any customization done after.&amp;nbsp; That includes customization done through a SPWebProvisioningProvider.&amp;nbsp; So basically, while the "onet.xml" file is called by the variation process, the "WEBTEMP*.xml" isn't.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;What I ended up doing was to create a feature that contained the same code and added it to my site definition.&amp;nbsp; If the sites are already deployed, you can look at at using Feature Stapling to do the same thing.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;In my opinion, the SPWebProvisioningProvider should be a more accurate place to do this code as I want to customize another Feature through business logic.&amp;nbsp; Of course, I could copy the ReviewWorkflow and create as many of them as I need plus as many Site Definitions for them, which might be okay for SharePoint, but wouldn't be a very reusable approach.&amp;nbsp; I also find curious that we have a great customizable solution with the provider but it's simply not being called through the variation mechanism.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;Maxime&lt;/p&gt; &lt;p&gt;&lt;embed src="http://card.mygamercard.net/Mumren.swf" width="198" height="135" type="application/x-shockwave-flash" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"&gt;&lt;/embed&gt;&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=7470659" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/maximeb/archive/tags/SharePoint/default.aspx">SharePoint</category><category domain="http://blogs.msdn.com/maximeb/archive/tags/Web+Content+Management/default.aspx">Web Content Management</category><category domain="http://blogs.msdn.com/maximeb/archive/tags/Variations/default.aspx">Variations</category><category domain="http://blogs.msdn.com/maximeb/archive/tags/SharePoint+Architecture+_2600_+Design/default.aspx">SharePoint Architecture &amp; Design</category></item><item><title>SPWebProvisioningProvider and ApplyWebTemplate on publishing site definition (i.e.: BLANKINTERNET or custom)</title><link>http://blogs.msdn.com/maximeb/archive/2008/02/01/spwebprovisioningprovider-and-applywebtemplate-on-publishing-site-definition-i-e-blankinternet-or-custom.aspx</link><pubDate>Fri, 01 Feb 2008 21:34:28 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:7376761</guid><dc:creator>MaximeB</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/maximeb/comments/7376761.aspx</comments><wfw:commentRss>http://blogs.msdn.com/maximeb/commentrss.aspx?PostID=7376761</wfw:commentRss><description>&lt;p&gt;While I am planning to soon blog on real life SPWebProvisioningProvider and Site Definitions in regards of Variations &amp;amp; Content Deployment, I wanted to comment on a little issue that had been plaguing me the last couple days.&amp;nbsp; First of all, my goal is to create a custom publishing site with :&lt;/p&gt; &lt;ul&gt; &lt;li&gt;More content types in the pages library&lt;/li&gt; &lt;li&gt;Update the default Parallel Approval workflow to have a different approvers group&lt;/li&gt; &lt;li&gt;Add a Delete Approval workflow&lt;/li&gt; &lt;li&gt;Have a custom default page that isn't a WelcomeLink&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;So that leads me to creating a custom Site Definitions.&amp;nbsp; Since the approval workflow parameters that I need are variable, I am working with the SPWebProvisioningProvider to update the workflow association after I created either a BLANKINTERNET#2 or a custom site definition that's similar to that one.&amp;nbsp; Note that BLANKINTERNET#2 is the standard Publishing Site with Workflow definition.&amp;nbsp; I found this blog (in French), &lt;a href="http://blogs.developpeur.org/themit/archive/2007/10/18/sharepoint-deployment-feature-feature-solution-mais-aussi-webprovisioningprovider.aspx"&gt;http://blogs.developpeur.org/themit/archive/2007/10/18/sharepoint-deployment-feature-feature-solution-mais-aussi-webprovisioningprovider.aspx&lt;/a&gt;, that talks about how to do this and, unfortunately, it doesn't support comments so I'm commenting here.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;Basically, you do a "web.ApplyWebTemplates("BLANKINTERNET#2");" followed by a "web.Update();".&amp;nbsp; Unfortunately, if you do an Update() right after applying a definition that activates the Server Publishing feature, it will give you an odd behaviour.&amp;nbsp; Basically, you end up having a "half publishing site" where you can edit the page, create a sub-site, but cannot create a new page or update navigation from the Site Actions.&amp;nbsp; I noticed that deactivating and reactivating the Server Publishing was working but the Navigation parameters were still off.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;I then tried, by mistake :), commenting the "web.Update();" line and everything was working fine.&amp;nbsp; So beware if you use an Update() method call after doing an ApplyWebTemplate (you might require it depending on what you need to modify).&amp;nbsp; I didn't try that yet but you might be better off to do a "SPWeb updatedWeb = web.Site.OpenWeb(web.ServerRelativeUrl);" to get a new SPWeb variable.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;Maxime&lt;/p&gt; &lt;p&gt;&lt;embed src="http://card.mygamercard.net/mumren.swf" width="198" height="135" type="application/x-shockwave-flash" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"&gt;&lt;/embed&gt;&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=7376761" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/maximeb/archive/tags/SharePoint/default.aspx">SharePoint</category><category domain="http://blogs.msdn.com/maximeb/archive/tags/Web+Content+Management/default.aspx">Web Content Management</category><category domain="http://blogs.msdn.com/maximeb/archive/tags/SharePoint+Architecture+_2600_+Design/default.aspx">SharePoint Architecture &amp; Design</category></item><item><title>Real-life Team-Based Development for Web Content Management with SharePoint 2007</title><link>http://blogs.msdn.com/maximeb/archive/2008/01/13/real-life-team-based-development-for-web-content-management-with-sharepoint-2007.aspx</link><pubDate>Sun, 13 Jan 2008 21:33:21 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:7101724</guid><dc:creator>MaximeB</dc:creator><slash:comments>3</slash:comments><comments>http://blogs.msdn.com/maximeb/comments/7101724.aspx</comments><wfw:commentRss>http://blogs.msdn.com/maximeb/commentrss.aspx?PostID=7101724</wfw:commentRss><description>&lt;p&gt;It took me a while to come up with everything I needed for this post as I want to make it as accurate as possible with the experience I had on the field.&amp;nbsp; The goal of this post is to provide information on the different ways to work as a team for a WCM web site with MOSS 2007.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;I believe that MOSS is large enough that a "one size / fit all" approach is unlikely.&amp;nbsp; There are simply too many variables.&amp;nbsp; Fortunately, I believe that what myself and awesome people I've worked with have overcome most issues and we have automated most deployment procedures.&amp;nbsp; I also believe that most of this knowledge will likely apply to other MOSS scenarios such as Document Management.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&lt;strong&gt;This post applies to : &lt;/strong&gt;Microsoft Office SharePoint 2007 (based on real-life deployments pre-SP1), Microsoft Office SharePoint Designer 2007, Microsoft Visual Studio 2005 Team System, Microsoft Team Foundation Server (not required but nice to have).&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Contents&lt;/strong&gt;&lt;/p&gt; &lt;ul&gt; &lt;li&gt;&lt;a href="#overview"&gt;Overview&lt;/a&gt;  &lt;li&gt;&lt;a href="#itlifecycle"&gt;IT oriented lifecycle with multiple environments&lt;/a&gt;  &lt;li&gt;&lt;a href="#htmllifecycle"&gt;HTML oriented lifecycle&lt;/a&gt;  &lt;li&gt;&lt;a href="#contentdeployment"&gt;A primer on SharePoint's Content Deployment&lt;/a&gt;  &lt;li&gt;&lt;a href="#solutions"&gt;Solutions for deploying SharePoint artifacts&lt;/a&gt;  &lt;li&gt;&lt;a href="#primerfeature"&gt;A primer on SharePoint Features&lt;/a&gt;  &lt;li&gt;&lt;a href="#primerwsp"&gt;A primer on SharePoint Solution Packages (WSP)&lt;/a&gt;  &lt;li&gt;&lt;a href="#primerapi"&gt;A primer on SharePoint APIs&lt;/a&gt;  &lt;li&gt;&lt;a href="#featuresvsapis"&gt;Features versus SharePoint APIs&lt;/a&gt;  &lt;li&gt;&lt;a href="#vm"&gt;A note on using Virtual Machines with SharePoint&lt;/a&gt; &lt;/li&gt;&lt;/ul&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;h2&gt;&lt;a name="overview"&gt;Overview&lt;/a&gt;&lt;/h2&gt; &lt;p&gt;What this post will contain is directions and guidance on how to achieve a working multi-environment team-based development lifecycle for WCM with MOSS 2007.&amp;nbsp; Unfortunately, for legal purposes, I cannot offer all STSADM extensions, Event Handlers, Features, and other code artifacts we developed for specific entities.&amp;nbsp; While I may eventually create a more "blank code version", this isn't available at the moment.&amp;nbsp; However, the how-to knowledge should be relatively easy for developers.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;In my experience, there are 2 primary types of development topologies in a MOSS WCM project:&lt;/p&gt; &lt;ol&gt; &lt;li&gt;&lt;strong&gt;IT oriented lifecycle with multiple environments&lt;/strong&gt; such as :  &lt;ol&gt; &lt;li&gt;Individual development (while team-based)  &lt;li&gt;Integrated testing  &lt;li&gt;Staging  &lt;li&gt;Production&lt;/li&gt;&lt;/ol&gt; &lt;li&gt;&lt;strong&gt;HTML oriented lifecycle&lt;/strong&gt; with 1 (production only) or 2 environments (staging + production)&lt;/li&gt;&lt;/ol&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;The main differences between the 2 is where your "base environment" is and where you allow "SharePoint Designer users" to act.&amp;nbsp; In an IT oriented lifecycle, every deployment follows a strict cycle of testing, staging, and scheduled deployment to production for all artifacts.&amp;nbsp; In an HTML oriented lifecycle, that may be true for "code artifacts" but you may want to have web integrators use SharePoint Designer directly in the staging environment and/or production.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;Obviously, there are advantages and disadvantages for both sides :)&amp;nbsp; I'll try to describe them to the best of my knowledge, but first, I have to explain what Content Deployment is and why it's not meant for development environments:&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;h2&gt;&lt;a name="itlifecycle"&gt;IT oriented lifecycle with multiple environments&lt;/a&gt;&lt;/h2&gt; &lt;p&gt;What I call an IT oriented lifecycle is when you already have a development lifecycle in place.&amp;nbsp; Often case, this is for secure or critical environments where downtime is not acceptable.&amp;nbsp; A secure close-to-production Staging environment is usually available in order to test deployments before doing them in Production.&amp;nbsp; You will want minimal steps to deploy as the deployment may be done by a 3rd party who may not have as much SharePoint experience and who's goal is to maintain the environment, not debug it.&amp;nbsp; This lifecycle is more typical for Intranet web sites.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Developers&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;When you have this environment in place, are you are likely to have separate developer environments as well as an integrated environment.&amp;nbsp; First of all, let's talk about the separate developer environments.&amp;nbsp; You can take a look at this general Team-Based Development document on MSDN : &lt;a title="Team-Based Development in Microsoft Office SharePoint Server 2007" href="http://msdn2.microsoft.com/en-us/library/bb428899.aspx"&gt;http://msdn2.microsoft.com/en-us/library/bb428899.aspx&lt;/a&gt; for more information.&amp;nbsp; Basically, in order to develop MOSS artifacts such as:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;ASP.NET Web Parts  &lt;li&gt;MOSS library Event Handlers  &lt;li&gt;Custom Workflows  &lt;li&gt;ASP.NET User or custom controls to use in MOSS  &lt;li&gt;STSADM extensions  &lt;li&gt;Expression Builders  &lt;li&gt;BDC related code  &lt;li&gt;Feature or SharePoint solutions (WSP) event handlers&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;... a developer requires to have MOSS installed on the same machine as Visual Studio.&amp;nbsp; That will allow him to develop and debug his artifacts without impacting anyone else.&amp;nbsp; Note that, often case, in order for a developer to be effective, he will require the same page layouts, master pages, and other "graphical artifacts" to completely test his development.&amp;nbsp; The deployment process has to allow a developer to receive graphical updates without scraping his complete site collection.&lt;/p&gt; &lt;p&gt;&amp;nbsp; &lt;/p&gt; &lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/maximeb/WindowsLiveWriter/ReallifeTeamDevelopmentforWebContentMana_102C5/IT_oriented_lifecycle_simple_4.jpg"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="350" alt="IT_oriented_lifecycle_simple" src="http://blogs.msdn.com/blogfiles/maximeb/WindowsLiveWriter/ReallifeTeamDevelopmentforWebContentMana_102C5/IT_oriented_lifecycle_simple_thumb_1.jpg" width="533" border="0"&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Web integrators&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;For the web integrators doing graphical work and layouts, they do not require a separate development environment.&amp;nbsp; The best solution is for them to have SharePoint Designer (and their graphical design application) on their workstation and all of them should access the same MOSS server.&amp;nbsp; If working on the same Site Collection, SharePoint Designer may be challenging at times and requires some quirks (at least, pre-SP1).&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;Sometimes, for web integrators who already had their tools prior to developing for SharePoint, I found it easier for them to design their layouts outside first with the tools they know best.&amp;nbsp; Obviously, knowledge of ASP.NET, Master Pages, and SharePoint will help having an easier transition to SharePoint after.&amp;nbsp; Once their layout is as desired in their respective tools, they can then move that content in SharePoint Designer and apply the required updates to work in a SharePoint world.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;The MOSS server they work on should also receive development updates when they are at least unit-tested.&amp;nbsp; This update should occurs outside of their working hours if possible and possibly be automated.&lt;/p&gt; &lt;p&gt;&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Staging&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;The Staging environment is where you want your customers to first see the end results of their web site.&amp;nbsp; This environment has to be stable and is probably not updated frequently.&amp;nbsp; This is also where you test your complete deployment process.&amp;nbsp; It's not unusual that non-SharePoint resources execute the deployment or it may even be managed by a 3rd party.&amp;nbsp; The process has to be as transparent and automated as possible.&amp;nbsp; This will allow to validate how the deployment to production will occur.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;This environment is also often where you have all components similar to the production and hopefully a multi-server MOSS farm.&amp;nbsp; That allows other type of testing (i.e.: deploying WSP across multiple servers, deployment of MOSS hotfixes in a farm, etc.).&amp;nbsp; The network may also be more constrained/secured.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Production&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;This is the environment where everything has to run smoothly.&amp;nbsp; The deployment process should be the same as the Staging environment.&amp;nbsp; Authoring occurs here, either on the same site collection or a different one (the site collection could even be in a different farm if desired).&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Summary&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;It's clear that, with that many environment, an automated solution to deploy to all of these environments has to be elaborated.&amp;nbsp; Unfortunately, the only one available with the product is not meant for these deployments.&amp;nbsp; SharePoint Features and SharePoint Solution projects are a big key to the solution but may be incomplete depending on your scenarios (as they have been in my experience).&amp;nbsp; I will cover Features, Solutions, and alternatives further.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;The main observation on what I call IT focused lifecycle is that the "SharePoint Designer" role is not a heavy role and updates to page layouts are streamlined through tested IT deployments.&amp;nbsp; Designers aren't able to use Designer directly in Staging or Production.&amp;nbsp; Let's see the HTML oriented lifecycle.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;h2&gt;&lt;a name="#htmllifecycle"&gt;HTML oriented lifecycle&lt;/a&gt;&lt;/h2&gt; &lt;p&gt;What I call an HTML oriented lifecycle is where your web site requires frequent layout updates.&amp;nbsp; Your designers are likely to be close to the authors rather than the developers.&amp;nbsp; This can be typical for highly frequented Internet web sites.&amp;nbsp; Essentially, the same roles seen with the IT lifecycle has to be fulfilled, however, since developers are higher up in the chain, the "bubbling down" of their work may not be as obvious and less controlled.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/maximeb/WindowsLiveWriter/ReallifeTeamDevelopmentforWebContentMana_102C5/HTML_oriented_lifecycle_simple_4.jpg"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="454" alt="HTML_oriented_lifecycle_simple" src="http://blogs.msdn.com/blogfiles/maximeb/WindowsLiveWriter/ReallifeTeamDevelopmentforWebContentMana_102C5/HTML_oriented_lifecycle_simple_thumb_1.jpg" width="530" border="0"&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Developers&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;Developers essentially do the same thing as in the IT lifecycle.&amp;nbsp; Integrated testing is done similarly as before on a centralized server that receives more frequent updates from the designers.&amp;nbsp; The integrated testing environment acts as a staging for the development artifacts.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Web integrators&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;The main difference of this lifecycle reside here.&amp;nbsp; Web integrators are doing daily updates to layouts on an Authoring Site Collection.&amp;nbsp; They might even be "power authors" that also manage content.&amp;nbsp; They often work directly in the production environment albeit a different Site Collection that may or not be in a different MOSS farm than the Publishing Site Collection.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;em&gt;This allows them to easily deploy layout updates without requiring an IT deployment that is usually more complicated or constrained.&lt;/em&gt;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;&lt;/strong&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Staging&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;The real staging environment is really the Authoring Site Collection since this is the origin for all layouts.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Production&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;This environment will be the same as before with the exception that SharePoint Designer is allowed on the Authoring Site Collection.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Summary&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;As you can see, there are similarities in the 2 lifecycles, however, from an architecture perspective, there are differences when you want to extract designer updates.&amp;nbsp; For example, in the IT lifecycle, we can link the integrated environment with a Source Control (Team Foundation Server for example) and generate builds.&amp;nbsp; The same does not easily apply to the HTML lifecycle as your source control environment is unlikely to be in the same network environment and you will rather want to schedule extracts of the graphical artifacts, copy them to the development environment, and then create a build for developers.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;Also, while I've seen both topologies in the field, one could debate why would designers need to update layouts so frequently.&amp;nbsp; In my opinion, if you design your layouts correctly and provide the correct level of customization, you should probably not need updates frequently and you might be able to work out with the IT oriented lifecycle.&amp;nbsp; I wanted to discuss about the 2 main scenarios I've experienced and provide solutions for both.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;Now that we have seen the 2 lifecycles, I want to discuss Content deployment quickly to assert why it isn't a viable solution for deploying on all environments.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;h2&gt;&lt;a name="contentdeployment"&gt;A primer on SharePoint's Content Deployment&lt;/a&gt;&lt;/h2&gt; &lt;p&gt;Content Deployment is a SharePoint feature that allows a &lt;u&gt;complete site collection&lt;/u&gt; to be deployed from a source to a destination.&amp;nbsp; These 2 environments can be in the same farm or a different farm.&amp;nbsp; This is done through the Operations tab of the Central Administration web site and requires simple configuration.&amp;nbsp; Basically, you create a path between 1 or 2 Central Administration servers (i.e.: 1 or 2 farms), and then you can create jobs to copy content on a scheduled or manual basis.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;The &lt;strong&gt;primary requirement&lt;/strong&gt; is that the target or destination has to be a site collection with the &lt;strong&gt;Blank Site template&lt;/strong&gt; (of the same language of the source) and that all activated features to be installed but not activated at the destination.&amp;nbsp; When the first content deployment runs, it will copy all libraries and items to the destination and then activate the same features as the source.&amp;nbsp; &lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;This is very important and to explain it easily, take a look at the Publishing feature.&amp;nbsp; If you activate it, it creates the out of the box master pages, page layouts, and styles for a Publishing Web Site.&amp;nbsp; If you activate it before doing the first content deployment, it will create a "Style Library" with a different GUID than the source.&amp;nbsp; If you were to use content deployment, it would fail as there would be an item with the same name at the source with a different GUID and it won't accept to deploy it.&amp;nbsp; This is the same if you create custom features.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;So in essence, since Content Deployment is used to have 2 sites that will be exactly be the same, it's primary use is for having a "staging authoring environment" where you author and test everything.&amp;nbsp; Then Content Deployment is used to update the production environment according to a schedule or a manual request.&amp;nbsp; Note that there are 3 variants of Content Deployment:&lt;/p&gt; &lt;ol&gt; &lt;li&gt;Through the Central Administration web site  &lt;li&gt;Through the STSADM -o import and STSADM -o export commands  &lt;li&gt;Through the APIs (Stephan Gossner wrote a great article about the APIs on his blog : &lt;a href="http://blogs.technet.com/stefan_gossner/archive/2007/08/30/deep-dive-into-the-sharepoint-content-deployment-and-migration-api-part-1.aspx"&gt;http://blogs.technet.com/stefan_gossner/archive/2007/08/30/deep-dive-into-the-sharepoint-content-deployment-and-migration-api-part-1.aspx&lt;/a&gt;.&lt;/li&gt;&lt;/ol&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;A deployment job consists of 3 primary steps : &lt;/p&gt; &lt;ol&gt; &lt;li&gt;Export (at the source).&amp;nbsp; This operation may be computer intensive.  &lt;li&gt;Transport (between the 2).&amp;nbsp; This is simply the file copy, however, there's a related article that can affect performance and I had to apply the fix for a customer.&amp;nbsp; It made the transport much faster.  &lt;li&gt;Import (at the destination).&amp;nbsp; This operation is not so computer intensive, yet very long to process.&amp;nbsp; I have cases where it takes less than 5 minutes to export and transport, and then 1h30min to import.&lt;/li&gt;&lt;/ol&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;The Central Administration web site's Content Deployment interface allows you to schedule deployment jobs easily.&amp;nbsp; Unfortunately, you cannot separate the 3 steps so it's good if you only need to deploy to one environment.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;Unfortunately, this is usually not an acceptable scenario to update &lt;em&gt;all&lt;/em&gt; environments such as Development or even Integrated Testing for the following reasons:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;You do not want multiple exports;  &lt;li&gt;The import process is long;  &lt;li&gt;It's not meant for destinations where you are also authoring on it (i.e.: developers testing their new web parts);  &lt;li&gt;It's not easy to "label" (as in Source Control labelling) a deployment.&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;Because of these concerns, other scenarios such as SharePoint Features, SharePoint Solution (WSP) projects, and the SharePoint APIs have to be explored and the following sections will elaborate on my findings for these technologies.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;em&gt;Note, &lt;/em&gt;&lt;a href="http://sharepointnutsandbolts.blogspot.com/"&gt;&lt;em&gt;Chris O'brien&lt;/em&gt;&lt;/a&gt;&lt;em&gt; also have great posts on Content Deployment and Features.&lt;/em&gt;&lt;/p&gt; &lt;p&gt;&lt;em&gt;&lt;/em&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;em&gt;&lt;/em&gt;&amp;nbsp;&lt;/p&gt; &lt;h2&gt;&lt;a name="solutions"&gt;Solutions for deploying SharePoint artifacts&lt;/a&gt;&lt;/h2&gt; &lt;p&gt;Now that we have a better understanding of what we are up against, let's look at what solutions are available to us.&amp;nbsp; Here are the possible solutions :&lt;/p&gt; &lt;ol&gt; &lt;li&gt;Content Deployment  &lt;li&gt;Backup/Restore  &lt;li&gt;Export/Import through SharePoint Designer (i.e.: Personal Web Package)  &lt;li&gt;Publishing through SharePoint Designer  &lt;li&gt;SharePoint Solution Generator  &lt;li&gt;SharePoint Features  &lt;li&gt;SharePoint Solution Packages (WSP)  &lt;li&gt;SharePoint APIs&lt;/li&gt;&lt;/ol&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;There may be other possibilities that I'm unaware of but these are the ones I've tested with.&amp;nbsp; Note that this was done pre-SP1.&amp;nbsp; I'll work by elimination (and reduce the list dramatically :)):&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Content Deployment : As stated previously, it's good only for equal environments so it's not practical for our scenarios;  &lt;li&gt;Backup/Restore : essentially the same as Content Deployment albeit much faster but less user friendly, not "scheduled", but usually with less errors/issues;  &lt;li&gt;Export/Import through SharePoint &amp;amp; Personal Web Package : My experience with it was ... very buggy.&amp;nbsp; I simply could not make it work correctly; for example, it created a 2nd Master Page Gallery (after renaming the original) at the destination when I tried it.&amp;nbsp; It didn't seem like a reliable solution, at least, before SP1;  &lt;li&gt;Publishing through SharePoint Designer is similar to Content Deployment.&amp;nbsp; I'm not sure if it uses the same Web Services or not, but the end result is the same with a confusing user experience;  &lt;li&gt;SharePoint Solution Generator : This tool is available through the &lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=19f21e5e-b715-4f0c-b959-8c6dcbdc1057&amp;amp;DisplayLang=en"&gt;WSS 3.0 Tools&lt;/a&gt;.&amp;nbsp; It's great to create site definitions, however, it doesn't work with the Publishing templates and isn't meant for WCM.&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;So we are left with 3 plausible solutions:&lt;/p&gt; &lt;ol&gt; &lt;li&gt;SharePoint Features  &lt;li&gt;SharePoint Solution Packages (WSP)  &lt;li&gt;SharePoint APIs&lt;/li&gt;&lt;/ol&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;Let me start by summarizing each of them:&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;/p&gt; &lt;h2&gt;&lt;a name="#primerfeature"&gt;A primer on SharePoint Features&lt;/a&gt;&lt;/h2&gt; &lt;p&gt;SharePoint Features are basically what SharePoint uses to deploy functionality to a SharePoint site.&amp;nbsp; For example, the Publishing feature is activated on a Blank Site to create a Publishing Web Site.&amp;nbsp; This will add the Style Libraries and the Master Pages gallery along with modifying the look &amp;amp; feel of your web site.&amp;nbsp; For example, the Site Actions will contain different actions than for a Collaboration web site.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;A SharePoint Feature consists of a manifest Xml file that is deployed in the 12 hive.&amp;nbsp; That manifest in turn specify what actions need to be done to the web site.&amp;nbsp; These actions can be from simply copying files (i.e.: page layouts, master pages, CSS, images, etc.) for creating the baseline of your web site, it can create site columns and content types, as well as even executing any .NET code you want through Event Handlers.&amp;nbsp; On paper, it's &lt;em&gt;the&lt;/em&gt; solution and SharePoint itself uses it.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;Unfortunately, creating features can be challenging as it requires knowing CAML.&amp;nbsp; CAML is the language definition for configuring any features.&amp;nbsp; While MSDN provides documentation for lots of the Xml elements available, MSDN is meant more as a reference, not for training.&amp;nbsp; Also, while I still create SharePoint Features today, I do not use is exclusively anymore as I found some bugs &amp;amp; quirks that I couldn't workaround well.&amp;nbsp; Particularly, using it to provision the baseline files.&amp;nbsp; For some other scenarios (Timer Jobs or Site Actions for example), Features are still the best solution.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;h2&gt;&lt;a name="#primerwsp"&gt;A primer on SharePoint Solution Packages (WSP)&lt;/a&gt;&lt;/h2&gt; &lt;p&gt;WSP files are really CAB files that SharePoint knows what to do with it.&amp;nbsp; The goal of SharePoint Solution Packages are to deploy a package once to the &lt;em&gt;MOSS Farm&lt;/em&gt; and then it will deploy and execute what's required for each server of the farm.&amp;nbsp; It includes even more features such as an interface in the Central Administration where you can schedule when you want a solution to be deployed or even retracted!&amp;nbsp; And to sugarcoat it, if you add servers to a farm, it will apply the solution packages automatically.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;em&gt;** Update ** : A colleague pointed me to the fact that solution will even automatically deploy after a server crash.&amp;nbsp; His scenario was that a solution was deployed in a farm and one of the servers had crashed.&amp;nbsp; When they fixed the servers, they simply had to bring it back online and the solution was automatically deployed to that server without any manual operation (no wizard execution).&amp;nbsp; ** /end Update**&lt;/em&gt;&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;Common scenarios include copying file to the GAC, modifying the web.config (using &lt;a href="http://msdn2.microsoft.com/en-us/library/microsoft.sharepoint.administration.spwebconfigmodification.aspx"&gt;SPWebConfigModification&lt;/a&gt; class), copying resources files, and copying physical files to the web site.&amp;nbsp; SharePoint Solution Packages are a must to most SharePoint deployments.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;h2&gt;&lt;a name="#primerapi"&gt;A primer on SharePoint APIs&lt;/a&gt;&lt;/h2&gt; &lt;p&gt;SharePoint APIs might seem to be a curious addition to this list as it's not really a deployment mechanism, or at least, not yet a user-friendly one.&amp;nbsp; However, while there may be bugs with SharePoint Features and Content Deployment in some cases, the SharePoint APIs is very robust and complete.&amp;nbsp; More so, strong developers can find more code samples as well as using tools such as Intellisense to &lt;em&gt;guess&lt;/em&gt; possible solutions.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;In your deployments, you are likely to have to use APIs for Event Handlers or web.config modifications, at the least, but my reason for mentioning it as a deployment alternative is that we ended up replacing some "Feature" scenarios that we had issue with for a complete SharePoint API solution.&amp;nbsp; Here's some operations that we automated, by creating custom STSADM extensions, for deploying complete Publishing web sites:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Create Site Columns including Lookup columns  &lt;li&gt;Create and update Content Types  &lt;li&gt;Create and update Master Pages, Page Layouts, CSS, Javascript, images, and other "baseline files" for a web site  &lt;li&gt;Create Publishing Sites and Pages with content (great for creating content-less (or near content-less) landing pages as well.&amp;nbsp; We also create an input file to create complete files with content so that, at a click, we can create a fully working development environment with content)  &lt;li&gt;Create SharePoint lists and referenced by Lookup columns  &lt;li&gt;Update Available Page Layouts for a publishing site  &lt;li&gt;Update Default page for a publishing site  &lt;li&gt;Create SharePoint Permission set and groups  &lt;li&gt;Update Versioning information for publishing site (i.e.: number of major &amp;amp; minor versions, activate/deactivate workflow requirement, etc.)  &lt;li&gt;Update a site's master page  &lt;li&gt;Update Publishing navigation settings (hiding sites/pages, inheriting from parent (or not) navigation, etc.)  &lt;li&gt;and more!&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;Since lots of these cannot or should not be done by Features, we had to drill the APIs extensively.&amp;nbsp; When strong (showstopper) issues came up for some Features scenarios, we shifted our focus to the APIs.&amp;nbsp; Let me go into more details on the pros &amp;amp; cons of Features versus APIs.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;h2&gt;&lt;a name="featuresvsapis"&gt;Features versus SharePoint APIs&lt;/a&gt;&lt;/h2&gt; &lt;p&gt;Features can be a great reusable way of deploying new functionality to a SharePoint site.&amp;nbsp; A SharePoint Feature is a set of functions, settings, and files to be added to a site (there are different levels of features but I'll keep it simple for now) when activated.&amp;nbsp; It's a great reusable mechanism for lots of scenarios such as adding a &lt;a href="http://msdn2.microsoft.com/en-us/library/bb418728.aspx"&gt;Custom Site Action&lt;/a&gt;, &lt;a href="http://www.andrewconnell.com/blog/articles/CreatingCustomSharePointTimerJobs.aspx"&gt;adding a Timer Job&lt;/a&gt;, and to some level, &lt;a href="http://www.katriendg.com/aboutdotnet/2007_3_13_publishing_contenttypes_feature.aspx"&gt;adding columns and content types&lt;/a&gt;.&amp;nbsp; You can take a look at this MSDN article for starting to work with Features : &lt;a title="Working with Features" href="http://msdn2.microsoft.com/en-us/library/ms460318.aspx"&gt;http://msdn2.microsoft.com/en-us/library/ms460318.aspx&lt;/a&gt;.&amp;nbsp; &lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;On one of my projects following the IT Lifecycle, we tried to use Features as much as possible since it was, for us, how reusable deployment artifacts should have been.&amp;nbsp; Unfortunately, we ran into some severe issues when using them for Columns/Content Types and files such as Page Layouts (ASPX), Master Pages, CSS, JavaScripts, and images.&amp;nbsp; While we have successfully used features for other artifacts as mentioned in the previous paragraph, our feature that creates the "web site's baseline" with all the right master pages using custom CSS, images, and scripts;&amp;nbsp; is being phased out.&amp;nbsp; Here are the issues that we ran into:&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;ol&gt; &lt;li&gt;Sometimes, the BlobCache may corrupt some files that are deployed through a feature.&amp;nbsp; This requires some explanation as the first goal of the BlobCache is to physically cache a file on the Web Front-End instead of fetching it from the database all the time.&amp;nbsp; Since the feature already brings the file on the disk (in the 12 hive), BlobCache wouldn't be necessary.&amp;nbsp; Unfortunately, the BlobCache is also the mechanism by which the Cache-Control Http header is set and that header is the one that let a browser (or proxy) cache a file instead of making it expire right now.&amp;nbsp; We experienced 2 types of corruptions, one where the files were half-correct, and half-blacked-out; one where JS and CSS were simply cropped and were missing content.&amp;nbsp; Note that all files were correct in the feature but simply not in the BlobCache folder.&amp;nbsp; Luckily, we use Content Deployment from Authoring to Publishing and that makes it so that the files are now in the database and there is no corruption then.&amp;nbsp; While MOSS itself uses files in features (i.e.: _layouts or styles library), there is a special Virtual Directory for them and the BlobCache doesn't treat them the same way.  &lt;li&gt;If you want to export (i.e.: content deployment) a site collection (the production/publishing environment) and import them in a test environment, a feature update will not work since the Import process will put the files in the database (similar to unghosted files, but really, it's not reading the feature at that point).  &lt;li&gt;If you update a Content Type and add a new column to it, the column will not be propagated to all libraries (this is not related to the checkbox to force inherit settings on child content types).&amp;nbsp; Let me explain a bit more, when you create a Site Column or a Content Type at the site collection level, and then you create a page that uses that content type in a sub-site's Pages library, the content type and columns are &lt;u&gt;copied&lt;/u&gt; to the library.&amp;nbsp; When you add a column to a content type through the GUI or the APIs, it will automatically add the column in all libraries where the content type is used.&amp;nbsp; Unfortunately, a Feature simply does not do it.&lt;/li&gt;&lt;/ol&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;While number 1 was annoying for the authoring environment, and number 3 wasn't happening often enough;&amp;nbsp; number 2 is the real issue where we hadn't found a workaround yet.&amp;nbsp; Plus we knew that the APIs work great for all of them.&amp;nbsp; What we ended up creating was an STSADM extension that reads the same CAML files that this feature used and:&lt;/p&gt; &lt;ol&gt; &lt;li&gt;Creates the site columns  &lt;li&gt;Create the content types  &lt;li&gt;Add page layouts and master pages  &lt;li&gt;Add files (CSS, GIF, JPG, PNG, JS) in any libraries&lt;/li&gt;&lt;/ol&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;We still package a WSP that runs the commands, actually, we could still use a Feature that adds and removes the files when activated/deactivated (through code) instead of using the CAML definition of provisioned files.&amp;nbsp; In my experience with Publishing Web Site, it's much safer in the database than in physical files.&amp;nbsp; Also, learning how to create columns and content types in .NET, or to add files in the database, is very easy and you'll have access to Intellisense.&amp;nbsp; Learning CAML and try all the scenarios (updating an environment, updating an environment that uses Content Deployment, versioning of documents deployed through features, etc.) is likely to be more challenging and time consuming. &lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;The next section is for detail's sake and because I have lots of questions on Virtual environments for developing in SharePoint.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;em&gt;&lt;/em&gt;&amp;nbsp;&lt;/p&gt; &lt;h2&gt;&lt;a name="vm"&gt;A note on using Virtual Machines with SharePoint&lt;/a&gt;&lt;/h2&gt; &lt;p&gt;While SharePoint can work correctly in a virtual environment, you have to be aware that the solution is not officially supported by Microsoft unless it's on Virtual Server.&amp;nbsp; What Microsoft Support will offer is what they call "Best effort support" where they'll help until they cannot reproduce the error and may ask to reproduce the error on a non-virtual environment.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;Also, in my experience, I wouldn't recommend virtual environment for production web sites.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;For development and up to staging however, I have seen both successful and very sluggish environments.&amp;nbsp; Personally, if going VM, I recommend the following parameters:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Have at least 2 GB of RAM  &lt;li&gt;You can use a single SQL for all developers  &lt;li&gt;SQL will offer better performance if not in a VM  &lt;li&gt;SQL's disks should be physical if possible as I've seen saturated SAN scenarios for having a few MOSS developers&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;In a coming article, I'll detail how we used Team Foundation Server to synchronize SharePoint Designer users with the main source database which allowed us to easily create WSP packages.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;Maxime&lt;/p&gt; &lt;p&gt;&lt;embed src="http://card.mygamercard.net/Mumren.swf" width="198" height="135" type="application/x-shockwave-flash" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"&gt;&lt;/embed&gt;&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=7101724" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/maximeb/archive/tags/SharePoint/default.aspx">SharePoint</category><category domain="http://blogs.msdn.com/maximeb/archive/tags/Web+Content+Management/default.aspx">Web Content Management</category><category domain="http://blogs.msdn.com/maximeb/archive/tags/Content+Deployment/default.aspx">Content Deployment</category><category domain="http://blogs.msdn.com/maximeb/archive/tags/SharePoint+Architecture+_2600_+Design/default.aspx">SharePoint Architecture &amp; Design</category></item></channel></rss>