<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-3706294656317442171</id><updated>2011-09-23T11:06:04.802+02:00</updated><category term='tetris'/><category term='softris'/><category term='RunWithElevatedPrivileges'/><category term='google wave'/><category term='Capgemini'/><category term='tfs'/><category term='personal'/><category term='W3C'/><category term='local'/><category term='moss 2007'/><category term='development'/><category term='dispose'/><category term='simple urls'/><category term='azure'/><category term='deployment'/><category term='SharePoint'/><category term='friendly urls'/><category term='environment'/><category term='team foundation server'/><category term='_layouts'/><category term='chrome'/><category term='Spring.Net'/><category term='fanboy'/><category term='game development'/><category term='global'/><category term='scrum'/><category term='performance'/><category term='PublishingConsole'/><category term='comments'/><title type='text'>Terborn</title><subtitle type='html'>This blog is not used anymore as I have a new position where I won't have the time necessary. Thanks.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://www.terborn.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3706294656317442171/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://www.terborn.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Terborn</name><uri>http://www.blogger.com/profile/08699582580311827918</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='21' src='http://2.bp.blogspot.com/_YZ6h0DIe-AY/SJ8hnRT_OsI/AAAAAAAAAR0/i0s6-3N1BUA/s1600-R/IMG_1119_lzn-2.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>25</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-3706294656317442171.post-3476030152330351034</id><published>2009-07-07T23:57:00.002+02:00</published><updated>2009-07-07T23:59:07.611+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='google wave'/><category scheme='http://www.blogger.com/atom/ns#' term='development'/><title type='text'>Google Wave</title><content type='html'>Oh boy, what a nice demo video I saw yesterday!&lt;br /&gt;&lt;br /&gt;If you have not heard of or seen the Google Wave demo yet, drop everything and go here:&lt;br /&gt;&lt;a href="http://wave.google.com/"&gt;http://wave.google.com/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;You won't regret it.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3706294656317442171-3476030152330351034?l=www.terborn.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.terborn.com/feeds/3476030152330351034/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3706294656317442171&amp;postID=3476030152330351034' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3706294656317442171/posts/default/3476030152330351034'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3706294656317442171/posts/default/3476030152330351034'/><link rel='alternate' type='text/html' href='http://www.terborn.com/2009/07/google-wave.html' title='Google Wave'/><author><name>Terborn</name><uri>http://www.blogger.com/profile/08699582580311827918</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='21' src='http://2.bp.blogspot.com/_YZ6h0DIe-AY/SJ8hnRT_OsI/AAAAAAAAAR0/i0s6-3N1BUA/s1600-R/IMG_1119_lzn-2.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3706294656317442171.post-3251858964132593523</id><published>2009-07-07T23:51:00.004+02:00</published><updated>2009-07-07T23:56:50.958+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='development'/><category scheme='http://www.blogger.com/atom/ns#' term='azure'/><title type='text'>Azure Services Platform</title><content type='html'>Got my Azure account a week or so ago. I'm really looking forward to have time enough to take it on a test run! :-)&lt;br /&gt;&lt;br /&gt;&lt;em&gt;I &lt;strong&gt;almost &lt;/strong&gt;wish it wasn't summer and nice weather...&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;And of course I am particularily interested in the Microsoft SharePoint Services part.&lt;br /&gt;&lt;br /&gt;Not checked it out yet? Please go here: &lt;a href="http://www.microsoft.com/azure/"&gt;http://www.microsoft.com/azure/&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3706294656317442171-3251858964132593523?l=www.terborn.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.terborn.com/feeds/3251858964132593523/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3706294656317442171&amp;postID=3251858964132593523' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3706294656317442171/posts/default/3251858964132593523'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3706294656317442171/posts/default/3251858964132593523'/><link rel='alternate' type='text/html' href='http://www.terborn.com/2009/07/azure-services-platform.html' title='Azure Services Platform'/><author><name>Terborn</name><uri>http://www.blogger.com/profile/08699582580311827918</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='21' src='http://2.bp.blogspot.com/_YZ6h0DIe-AY/SJ8hnRT_OsI/AAAAAAAAAR0/i0s6-3N1BUA/s1600-R/IMG_1119_lzn-2.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3706294656317442171.post-335179273307162688</id><published>2009-06-01T13:34:00.006+02:00</published><updated>2009-06-01T14:22:43.558+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='moss 2007'/><category scheme='http://www.blogger.com/atom/ns#' term='dispose'/><category scheme='http://www.blogger.com/atom/ns#' term='SharePoint'/><category scheme='http://www.blogger.com/atom/ns#' term='RunWithElevatedPrivileges'/><title type='text'>Re-use when executing elevated code</title><content type='html'>&lt;em&gt;Each time you open a web in SharePoint you create a possible memory leak. Generally, using the &lt;span style="font-family:courier new;"&gt;using&lt;/span&gt; directive ensures that no leak will happen. And since opening a web is normally only one line of code, it is fine to write this code in-line without reusing elements of it.&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:180%;"&gt;Challenge&lt;/span&gt;&lt;br /&gt;However, when using &lt;span style="font-family:courier new;"&gt;SPSecurity.RunWithElevatedPrivileges&lt;/span&gt; to elevate rights we have a similar issue, but there's several lines of code that you'd like to be able to reuse between different methods. For example, you'll have to &lt;strong&gt;open a site&lt;/strong&gt; (sometimes at least), &lt;strong&gt;open a web&lt;/strong&gt;, and &lt;strong&gt;set&lt;/strong&gt; &lt;span style="font-family:courier new;"&gt;AllowUnsafeUpdates&lt;/span&gt; &lt;strong&gt;on both site and web&lt;/strong&gt;. &lt;em&gt;And you still need to ensure that disposing works correctly.&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;If you create a method that, for example, simply returns an elevated web you'll have no control over whether that web is disposed or not in the end. And the code will become quite hard to manage later on as reusable blocks of code might have to manage both webs that shall be disposed and those that shouldn't be disposed (such as &lt;span style="font-family:courier new;"&gt;SPContext.Current.Web&lt;/span&gt;).&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:180%;"&gt;Solution&lt;/span&gt;&lt;br /&gt;My solution? Write reusable methods that take a delegate for the actions to execute in elevated mode. I create overloads that cover all the needs for the project. But, let's look at an example.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;A delegate&lt;/strong&gt;&lt;br /&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;public delegate void WebCodeDelegate(SPWeb elevatedWeb);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;The reusable code block&lt;/strong&gt;&lt;br /&gt;&lt;pre&gt;public static void ExecuteElevatedCode(Guid siteId, Guid webId, WebCodeDelegate webCode)&lt;br /&gt;{&lt;br /&gt;    SPSecurity.RunWithElevatedPrivileges(delegate()&lt;br /&gt;    {&lt;br /&gt;        // Use "using" to automatically release site resources.&lt;br /&gt;        using (SPSite site = new SPSite(siteId))&lt;br /&gt;        {&lt;br /&gt;            site.AllowUnsafeUpdates = true;&lt;br /&gt;            // Open a web. Be sure to release resources!&lt;br /&gt;            SPWeb elevatedWeb = site.OpenWeb(webId);&lt;br /&gt;            try&lt;br /&gt;            {&lt;br /&gt;                elevatedWeb.AllowUnsafeUpdates = true;&lt;br /&gt;                // Execute delegate.&lt;br /&gt;                webCode(elevatedWeb);&lt;br /&gt;            }&lt;br /&gt;            finally&lt;br /&gt;            {&lt;br /&gt;                // Release web resources.&lt;br /&gt;                elevatedWeb.Dispose();&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;    });&lt;br /&gt;}&lt;/pre&gt;&lt;strong&gt;Calling the reusable code&lt;/strong&gt;&lt;br /&gt;&lt;pre&gt;ExecuteElevatedCode(siteId, process.Id, delegate(SPWeb elevatedWeb)&lt;br /&gt;{&lt;br /&gt;    SPList elevatedList = elevatedWeb.Lists[PROCESS_WEB_LIST_NAME];&lt;br /&gt;    SPListItem item = elevatedList.Items[0];&lt;br /&gt;    item[GUID_STATUS] = "status";&lt;br /&gt;    item[GUID_ERROR_DESCRIPTION] = "description";&lt;br /&gt;    item.Update();&lt;br /&gt;});&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Other examples of overloads&lt;br /&gt;&lt;/strong&gt;&lt;pre&gt;// Executes elevated code on the root web of the current site collection.&lt;br /&gt;public static void ExecuteElevatedCode(WebCodeDelegate webCode)&lt;br /&gt;// Executes elevated code on the root web of the specified site collection.&lt;br /&gt;public static void ExecuteElevatedCode(SPSite site, WebCodeDelegate webCode)&lt;br /&gt;// Executes elevated code on the specified web.&lt;br /&gt;public static void ExecuteElevatedCode(SPWeb web, WebCodeDelegate webCode)&lt;br /&gt;// Executes elevated code on the specified web (using the url as reference to the web).&lt;br /&gt;public static void ExecuteElevatedCode(Guid siteId, string webUrl, WebCodeDelegate webCode)&lt;br /&gt;// Executes elevated code on the specified list.&lt;br /&gt;public static void ExecuteElevatedCode(SPList list, ListCodeDelegate listCode)&lt;br /&gt;// Executes elevated code on the specified item.&lt;br /&gt;public static void ExecuteElevatedCode(SPListItem item, ListItemCodeDelegate listItemCode)&lt;/pre&gt;&lt;br /&gt;So, that's it. Hope it'll be of help to someone!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3706294656317442171-335179273307162688?l=www.terborn.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.terborn.com/feeds/335179273307162688/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3706294656317442171&amp;postID=335179273307162688' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3706294656317442171/posts/default/335179273307162688'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3706294656317442171/posts/default/335179273307162688'/><link rel='alternate' type='text/html' href='http://www.terborn.com/2009/06/re-use-when-executing-elevated-code.html' title='Re-use when executing elevated code'/><author><name>Terborn</name><uri>http://www.blogger.com/profile/08699582580311827918</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='21' src='http://2.bp.blogspot.com/_YZ6h0DIe-AY/SJ8hnRT_OsI/AAAAAAAAAR0/i0s6-3N1BUA/s1600-R/IMG_1119_lzn-2.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3706294656317442171.post-8411408061904278537</id><published>2009-02-02T16:50:00.019+01:00</published><updated>2009-03-19T14:58:40.829+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='moss 2007'/><category scheme='http://www.blogger.com/atom/ns#' term='development'/><category scheme='http://www.blogger.com/atom/ns#' term='SharePoint'/><category scheme='http://www.blogger.com/atom/ns#' term='PublishingConsole'/><title type='text'>Custom PublishingConsole</title><content type='html'>I generally like the publishing features in MOSS 2007. And as a general-purpose page editor control, I think the PublishingConsole is quite alright. But I do have the following issues with it: &lt;ol&gt;&lt;li&gt;It is difficult if not impossible to make it look just the way you'd like.&lt;/li&gt;&lt;li&gt;The accessibility aspects of the control are bad. It simply does not comply with W3C or WCAG standards.&lt;/li&gt;&lt;li&gt;Configuring the console requires modifications to the CustomQuickAccess.xml and CustomEditingMenu.xml files. These are database files who are very difficult to modify programmatically. This makes an automatic deployment without manual steps difficult.&lt;/li&gt;&lt;/ol&gt;&lt;div&gt;Depending on requirements these issues may be more or less important. One might argue that since the publishing controls are usually only visible to administrators, who cares of the look n' feel and accessibility? Well, that's true often, but not always...&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;In my current project, all of the above turned out to be serious issues. So we ended up building our own control. This is how it looks in its current draft version:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;img id="BLOGGER_PHOTO_ID_5314822191168720946" style="DISPLAY: block; MARGIN: 0px auto 10px; CURSOR: hand; TEXT-ALIGN: center" alt="" src="http://1.bp.blogspot.com/_YZ6h0DIe-AY/ScIKn6z5kDI/AAAAAAAAAn8/uMbiOxLYIBc/s400/blog_publishing_bar.png" border="0" /&gt;&lt;br /&gt;&lt;div align="center"&gt;&lt;em&gt;(Sorry for the swedish, but the controls are undo, check out, check in, publish, remove and confirm.)&lt;/em&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;How it's done&lt;/strong&gt;&lt;br /&gt;Reusing what we could from the standard controls were important of course. By going through code and by using Lutz Roeder's Reflector I finally managed to get my own publishing console working.&lt;br /&gt;&lt;br /&gt;Here's how:&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;strong&gt;In the page layout .aspx file&lt;/strong&gt;, add the following code:&lt;/p&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;&amp;lt;%@ Register Tagprefix="PublishingWebControls" Namespace="Microsoft.SharePoint.Publishing.WebControls" Assembly="Microsoft.SharePoint.Publishing, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;&amp;lt;!-- Edit mode support without PublishingConsole --&gt; &amp;lt;PublishingWebControls:PublishingContext id="mPublishingContext" runat="server" /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;&amp;lt;PublishingWebControls:EditModePanel runat="server" id="mEditContent" PageDisplayMode="Edit" SuppressTag="true"&gt; &amp;lt;PublishingWebControls:SaveBeforeNavigationControl id="mSaveBeforeNavigation" runat="server" &gt;&amp;lt;/PublishingWebControls:SaveBeforeNavigationControl&gt; &amp;lt;/PublishingWebControls:EditModePanel&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The above code generates the required standard controls. The "save before navigation" control is of course only required when in edit mode.&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;strong&gt;Create a web control&lt;/strong&gt; that somehow gives your users the ability to send commands such as check out, check in, undo check out, publish and so on.&lt;/p&gt;&lt;p&gt;The buttons (or links, or...) need to support both a clientside javascript and a page postback. In my own case i created a generic CommandBarControl that is fed commands by the page layout using it.&lt;/p&gt;&lt;p&gt;A command includes the following:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Name/Title/Description information, depending on your needs&lt;/li&gt;&lt;li&gt;Logic for determining visibility and enabled states, depending on your needs (I used delegates for these purposes myself)&lt;/li&gt;&lt;li&gt;Client-side javascript&lt;/li&gt;&lt;li&gt;Logic for performing the action (I used a delegate here as well)&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;Define code behind methods&lt;/strong&gt; for the commands. Please see below for examples of code I used for some typical commands. &lt;em&gt;Note that the examples are simplified and thus I have not compiled and tested these examples. Personally I use a three-layered, service oriented and test-driven architecture with Spring.Net for IoC &amp;amp; AOP caching and so. ;-)&lt;/em&gt;&lt;/p&gt;&lt;strong&gt;Check out&lt;/strong&gt;&lt;br /&gt;A javascript is required here to get the user interface to switch to edit mode. Add the following javascript to your button's "&lt;span style="font-family:courier new;font-size:85%;"&gt;onclick&lt;/span&gt;"-event:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;javascript:if (document.forms['aspnetForm']['MSOLayout_InDesignMode'] != null) document.forms['aspnetForm']['MSOLayout_InDesignMode'].value = 1;if (document.forms['aspnetForm']['MSOAuthoringConsole_FormContext'] != null) document.forms['aspnetForm']['MSOAuthoringConsole_FormContext'].value = 1;if (document.forms['aspnetForm']['MSOSPWebPartManager_DisplayModeName'] != null) document.forms['aspnetForm']['MSOSPWebPartManager_DisplayModeName'].value = 'Design'&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The code behind-logic should be similar to this:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;public void CheckOut()&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;SPListItem item = SPContext.Current.ListItem;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;if (item.File.Level != SPFileLevel.Checkout)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;PublishingPage page = PublishingPage.GetPublishingPage(item);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;page.CheckOut();&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;SPContext.Current.FormContext.SetFormMode(SPControlMode.Edit, true);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Undo check out&lt;/strong&gt;&lt;br /&gt;The code behind-logic should be similar to this:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;public void UndoCheckOut()&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;SPListItem item = SPContext.Current.ListItem;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;if (item.File.Level == SPFileLevel.Checkout)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;item.File.UndoCheckOut();&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;CleanRedirect();&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The &lt;span style="font-family:courier new;"&gt;&lt;span style="font-size:85%;"&gt;CleanRedirect(&lt;/span&gt;)&lt;/span&gt; method is necessary to remove the edit mode from the user interface. Microsoft themselves to something similar (according to the Reflector):&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;private static void CleanRedirect()&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;HttpContext context = HttpContext.Current;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;SPUtility.Redirect(context.Request.Url.AbsoluteUri, SPRedirectFlags.Default, context);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Check in&lt;/strong&gt;&lt;br /&gt;The code behind-logic should be similar to this:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;public void CheckIn(SPListItem item)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;SPListItem item = SPContext.Current.ListItem;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;if (item.File.Level == SPFileLevel.Checkout)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;PublishingPage page = PublishingPage.GetPublishingPage(item);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;page.CheckIn(string.Empty);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;CleanRedirect();&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Publish&lt;/strong&gt;&lt;br /&gt;The code behind-logic should be similar to this:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;public void Publish(SPListItem item)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Courier New;font-size:85%;"&gt;// Note: You could add an automatic check in here, now it is&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Courier New;font-size:85%;"&gt;// only possible to publish after a manual check in.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;if (item.File.Level != SPFileLevel.Checkout)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;item.File.Publish(string.Empty);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;CleanRedirect();&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Well, that's basically it. I hope this will help you on your way! And - please give me feedback whether this was useful or not. :-)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3706294656317442171-8411408061904278537?l=www.terborn.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.terborn.com/feeds/8411408061904278537/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3706294656317442171&amp;postID=8411408061904278537' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3706294656317442171/posts/default/8411408061904278537'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3706294656317442171/posts/default/8411408061904278537'/><link rel='alternate' type='text/html' href='http://www.terborn.com/2009/02/custom-publishinglayout.html' title='Custom PublishingConsole'/><author><name>Terborn</name><uri>http://www.blogger.com/profile/08699582580311827918</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='21' src='http://2.bp.blogspot.com/_YZ6h0DIe-AY/SJ8hnRT_OsI/AAAAAAAAAR0/i0s6-3N1BUA/s1600-R/IMG_1119_lzn-2.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_YZ6h0DIe-AY/ScIKn6z5kDI/AAAAAAAAAn8/uMbiOxLYIBc/s72-c/blog_publishing_bar.png' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3706294656317442171.post-8835450833674875130</id><published>2008-12-03T11:14:00.007+01:00</published><updated>2008-12-03T16:13:45.739+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='moss 2007'/><category scheme='http://www.blogger.com/atom/ns#' term='deployment'/><category scheme='http://www.blogger.com/atom/ns#' term='SharePoint'/><category scheme='http://www.blogger.com/atom/ns#' term='_layouts'/><title type='text'>Deploying a file to the "_layouts" folder</title><content type='html'>&lt;em&gt;I don't like to feel stupid. At all. But sometimes it is a wonderful feeling, because sometimes it means "Shit, how could I have missed this simple solution?".&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;In my current project, we've had an issue with deploying to SharePoint's &lt;span style="font-family:courier new;"&gt;_layouts&lt;/span&gt; folder. Using a module in the &lt;span style="font-family:courier new;"&gt;Elements.xml&lt;/span&gt; file only creates a ghosted database copy which won't work for example a custom login page, which is what I wanted to deploy.&lt;br /&gt;&lt;br /&gt;Now, at this small conferance in Malmö, Sweden, I met &lt;a href="http://www.zimmergren.net/"&gt;Tobias Zimmergren&lt;/a&gt; who said something along the lines of "&lt;em&gt;But why don't you just use the &lt;span style="font-family:courier new;"&gt;RootFiles&lt;/span&gt;-element in your &lt;span style="font-family:courier new;"&gt;manifest.xml&lt;/span&gt; file? I do that all the time.&lt;/em&gt;".&lt;br /&gt;&lt;br /&gt;So, yea, I felt stupid sure, but... The next day I also had an auto-deployed custom login page to the &lt;span style="font-family:courier new;"&gt;_layouts&lt;/span&gt;-folder. :-)&lt;br /&gt;&lt;br /&gt;The code is very easy...&lt;br /&gt;&lt;br /&gt;In your &lt;span style="font-family:courier new;"&gt;xyz.ddf&lt;/span&gt;-file you'll put something along the lines of:&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;.Set DestinationDir="Layouts"&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Features\XyzSecurity\Page\XyzLoginPage.aspx&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;In your &lt;span style="font-family:courier new;"&gt;manifest.xml&lt;/span&gt; you'll write something similar to:&lt;br /&gt;&lt;templatefiles&gt;&lt;templatefile location="Layouts\XyzLoginPage.aspx"&gt;&lt;span style="font-family:courier new;"&gt;&amp;lt;TemplateFiles&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;lt;TemplateFile Location="Layouts\XyzLoginPage.aspx"/&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;lt;/TemplateFiles&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;/templatefiles&gt;&lt;br /&gt;Very nice!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3706294656317442171-8835450833674875130?l=www.terborn.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.terborn.com/feeds/8835450833674875130/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3706294656317442171&amp;postID=8835450833674875130' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3706294656317442171/posts/default/8835450833674875130'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3706294656317442171/posts/default/8835450833674875130'/><link rel='alternate' type='text/html' href='http://www.terborn.com/2008/12/deploying-file-to-layouts-folder.html' title='Deploying a file to the &quot;_layouts&quot; folder'/><author><name>Terborn</name><uri>http://www.blogger.com/profile/08699582580311827918</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='21' src='http://2.bp.blogspot.com/_YZ6h0DIe-AY/SJ8hnRT_OsI/AAAAAAAAAR0/i0s6-3N1BUA/s1600-R/IMG_1119_lzn-2.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3706294656317442171.post-9112021646647844902</id><published>2008-11-23T14:36:00.010+01:00</published><updated>2008-12-02T15:07:01.445+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='tfs'/><category scheme='http://www.blogger.com/atom/ns#' term='development'/><category scheme='http://www.blogger.com/atom/ns#' term='team foundation server'/><category scheme='http://www.blogger.com/atom/ns#' term='scrum'/><title type='text'>TFS and Scrum</title><content type='html'>&lt;div align="left"&gt;&lt;em&gt;I'm one of those who truly appreciate a strong methodology that supports the project with structure and a true sense of direction. However, I'm also one of those that cannot stand administrative tasks that move the developer's focus from what he's supposed to be doing - which is creating fantastic, innovative, high-quality solutions to our clients!&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;In an &lt;a href="http://terborn.blogspot.com/2008/11/adapting-scrum.html"&gt;earlier post&lt;/a&gt; I mentioned how I currently work using a Scrum-like process. So, I thought I'd share the tools I use and show how powerful this environment is!&lt;br /&gt;&lt;br /&gt;But first, a sneak peek on the result. This is the normal dashboard view where the developer interact with the Scrum-process:&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;img id="BLOGGER_PHOTO_ID_5271859823274000450" style="DISPLAY: block; MARGIN: 0px auto 10px; WIDTH: 400px; CURSOR: hand; HEIGHT: 305px; TEXT-ALIGN: center" alt="" src="http://1.bp.blogspot.com/_YZ6h0DIe-AY/SSlok-fmgEI/AAAAAAAAAaw/cyYwDmDex3M/s400/scrumdashboard.png" border="0" /&gt;&lt;br /&gt;This view allows for drag n'drop of sprint activities from "Not Done" to "In Progress" and so forth. It is an easy, quick and rewarding system. There's nothing like making a sprint task green! :-)&lt;br /&gt;&lt;br /&gt;So, how is this environment created?&lt;br /&gt;&lt;br /&gt;This is the products we've used:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Visual Studio Team Suite 2008&lt;/li&gt;&lt;li&gt;SQL Server 2005&lt;/li&gt;&lt;li&gt;MOSS 2007&lt;/li&gt;&lt;li&gt;Team Foundation Server 2008&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.scrumforteamsystem.com/"&gt;Scrum for Team System&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://msdn.microsoft.com/en-us/tfs2008/bb980951.aspx"&gt;Visual Studio Team System 2008 Web Access&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.codeplex.com/scrumdashboard"&gt;Scrum Dashboard&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;The Scrum Dashboard (created by the EPiServer team, thanks guys!) makes the whole process visible and fun, which is very important. We have a distributed team so a physical Scrum board is not an option. Also, I strongly believe in giving feedback, and the dashboard gives a nice, green feedback each time a developer finishes a task. :-)&lt;br /&gt;&lt;br /&gt;All in all, this environment works like a charm and I'm very pleased.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Drawbacks&lt;/strong&gt;&lt;br /&gt;The TFS environment is built upon a flat layer of "tasks". It is possible to configure any number of different types of tasks of course, but it is not designed for the dual layer that the Scrum template uses where Sprint Backlog Items are part of Product Backlog Items.&lt;br /&gt;&lt;br /&gt;To represent this task structure the Scrum template uses the "Link" functionality available for tasks. Basically, spring backlog items are linked to from the product backlog item and the Scrum template contains an event manager that listens to changes and updates linked items accordingly. For example, when estimated times are changed in a sprint backlog item the product backlog item is updated automatically.&lt;br /&gt;&lt;br /&gt;This works fairly well but when you update tasks from TFS you need to truly understand this logic since it is easy to break it. For example when moving a sprint backlog item from one product backlog item to another it is important to work from the sprint backlog item view and not the product backlog item view for some reason. In the first case the event triggers, in the latter the event does not trigger, leaving product backlog items with incorrect values.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;strong&gt;Screens&lt;br /&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;img id="BLOGGER_PHOTO_ID_5275191150804375218" style="DISPLAY: block; MARGIN: 0px auto 10px; WIDTH: 400px; CURSOR: hand; HEIGHT: 230px; TEXT-ALIGN: center" alt="" src="http://1.bp.blogspot.com/_YZ6h0DIe-AY/STU-Zwn6lrI/AAAAAAAAAbI/fONFnQvI494/s400/scrumburndown.png" border="0" /&gt;&lt;/p&gt;&lt;p align="center"&gt;&lt;em&gt;The burn-down chart, from Reporting Services. It shows the actual time, the trend, and the capactity trend. (And yea, got hit with a lot of sickness this sprint...)&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;&lt;div align="center"&gt;&lt;img id="BLOGGER_PHOTO_ID_5275192748183576722" style="DISPLAY: block; MARGIN: 0px auto 10px; WIDTH: 345px; CURSOR: hand; HEIGHT: 400px; TEXT-ALIGN: center" alt="" src="http://4.bp.blogspot.com/_YZ6h0DIe-AY/STU_2vUy4JI/AAAAAAAAAbQ/0gZH-0F_EOY/s400/scrumspi.png" border="0" /&gt;&lt;em&gt;The sprint backlog item web editor that opens if you click on an item. Hosted by the "web access" layer and based on the Scrum template. Only one field has been added by me - the "Work Performed" text box. Product backlog items may be edited as well and look similar.&lt;/em&gt;&lt;/div&gt;&lt;br /&gt;&lt;strong&gt;Summary&lt;/strong&gt;&lt;br /&gt;Besides from the somewhat cumbersome TFS management, I have nothing bad to say about this system. On the contrary, I am very pleased by what these open source products have to offer!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3706294656317442171-9112021646647844902?l=www.terborn.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.terborn.com/feeds/9112021646647844902/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3706294656317442171&amp;postID=9112021646647844902' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3706294656317442171/posts/default/9112021646647844902'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3706294656317442171/posts/default/9112021646647844902'/><link rel='alternate' type='text/html' href='http://www.terborn.com/2008/11/tfs-and-scrum.html' title='TFS and Scrum'/><author><name>Terborn</name><uri>http://www.blogger.com/profile/08699582580311827918</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='21' src='http://2.bp.blogspot.com/_YZ6h0DIe-AY/SJ8hnRT_OsI/AAAAAAAAAR0/i0s6-3N1BUA/s1600-R/IMG_1119_lzn-2.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_YZ6h0DIe-AY/SSlok-fmgEI/AAAAAAAAAaw/cyYwDmDex3M/s72-c/scrumdashboard.png' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3706294656317442171.post-337748289606535881</id><published>2008-11-23T13:36:00.008+01:00</published><updated>2008-11-23T14:34:11.993+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='tfs'/><category scheme='http://www.blogger.com/atom/ns#' term='development'/><category scheme='http://www.blogger.com/atom/ns#' term='SharePoint'/><category scheme='http://www.blogger.com/atom/ns#' term='team foundation server'/><category scheme='http://www.blogger.com/atom/ns#' term='scrum'/><title type='text'>Adapting Scrum</title><content type='html'>In my current project we use the agile method Scrum for the every-day business. Not &lt;strong&gt;true&lt;/strong&gt; Scrum though, since we have the following challenges:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Fixed price&lt;/li&gt;&lt;li&gt;Fairly fixed functionality&lt;/li&gt;&lt;li&gt;The client prefers a RUP-like delivery&lt;/li&gt;&lt;li&gt;A virtual team - i.e. team members are distributed across the globe&lt;/li&gt;&lt;/ul&gt;So, why did I even want to use a Scrum-like method? Quite frankly, I think it is clearly superior in the every-day development process due to:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;The entire team shares responsibility (flat organization)&lt;/li&gt;&lt;li&gt;Very detailed project status always available&lt;/li&gt;&lt;li&gt;Challenges detected very quickly&lt;/li&gt;&lt;li&gt;More freedom = more &lt;strong&gt;innovation&lt;/strong&gt;&lt;/li&gt;&lt;li&gt;The process is very visual&lt;/li&gt;&lt;li&gt;There are great tools available to support the process!&lt;/li&gt;&lt;/ul&gt;So how did we modify Scrum to suit our challenges above?&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;The client prefers a RUP-like interface&lt;/strong&gt;&lt;br /&gt;We divided the project into the four phases: Inception, Elaboration, Construction and Transition.&lt;br /&gt;&lt;br /&gt;The Inception phase worked as one would expect for a project that starts with a bid stage.&lt;br /&gt;&lt;br /&gt;The Elaboration phase however was shortened considerably. I, as the technical project manager and lead system architect, created the SAD (Software Architecture Document) and SSDS (System Software Design Specification) documents containing the basic outlining for the entire project. This step is necessary for a fixed price project either way for us to be able to deliver a detailed time estimate to the project manager and steering committee. We also communicated to the client that the design will continue to grow during the Construction phase.&lt;br /&gt;&lt;br /&gt;The Construction phase was broken down into four client deliveries. Internally, we broke down these four client deliveries into 16 Scrum sprints of three weeks each. We will thus have 4 internal deliveries for each client delivery. The time estimate from the elaboration phase contained a rudimentary break-down of activities. These were fairly easily broken down into product backlog items (PBI's). A product backlog was thus easily created. And as the four client deliveries each had a "theme", it was also fairly simple to decide PBI priority.&lt;br /&gt;&lt;br /&gt;The roles of project manager and technical project manager still exist in the project. I still do believe that a project manager and a steering committee is important for a successful project, at least for my company since we deliver projects as a service for our clients.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Fixed price and functionality&lt;/strong&gt;&lt;br /&gt;The product owner became an internal role - the technical project manager (me). One of the developers became the Scrum Master to separate concerns and to delegate responsibility.&lt;br /&gt;&lt;br /&gt;Fixed price means that we as developers are restricted when we do our sprint planning meetings. We are free to move time from one product backlog to another. BUT - as soon as we find that we need more time (i.e. the time estimate was wrong) we need to escalate this to the project manager in the form of an "overrun risk".&lt;br /&gt;&lt;br /&gt;In Scrum, the work spent in itself is not very interesting, only the estimated time left. However, in fixed price projects, we also need to measure time used. When we spend considerably more time than the allotted (estimated) time on a sprint task, we need to report this as "overrun" to the project manager.&lt;br /&gt;&lt;br /&gt;We also need to consider change requests. A Change Control Board (CCB) is available and handled by the project manager and the technical project manager together with the client. Generally, the developer need not be concerned about this process. When the client requests a new feature, the CCB manages this, and finally a new PBI is added to the backlog.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Virtual team&lt;/strong&gt;&lt;br /&gt;No matter what process used, the team will deliver better when they are gathered at one location. However, this will not always be possible for a number of valid reasons.&lt;br /&gt;&lt;br /&gt;In my project we all meet regularly at one location, especially during spring planning and retrospective meetings. We run daily Scrum meetings as usual, but over conference phones.&lt;br /&gt;&lt;br /&gt;We also use a tool to manage the Scrum process. The burn-down chart and sprint task board are both virtualized using Team Foundation Server (TFS) with some open-source add-ons. &lt;em&gt;More on this environment in a later post.&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;To summarize, a Scrum-like methodology gives your team a lot of power and freedom. I believe it is possible to use this method in most scenarios. And I think your developers will truly love to work in the environment that the system gives you!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3706294656317442171-337748289606535881?l=www.terborn.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.terborn.com/feeds/337748289606535881/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3706294656317442171&amp;postID=337748289606535881' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3706294656317442171/posts/default/337748289606535881'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3706294656317442171/posts/default/337748289606535881'/><link rel='alternate' type='text/html' href='http://www.terborn.com/2008/11/adapting-scrum.html' title='Adapting Scrum'/><author><name>Terborn</name><uri>http://www.blogger.com/profile/08699582580311827918</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='21' src='http://2.bp.blogspot.com/_YZ6h0DIe-AY/SJ8hnRT_OsI/AAAAAAAAAR0/i0s6-3N1BUA/s1600-R/IMG_1119_lzn-2.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3706294656317442171.post-7628025929086603133</id><published>2008-07-13T19:02:00.004+02:00</published><updated>2008-10-25T00:12:40.998+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='moss 2007'/><category scheme='http://www.blogger.com/atom/ns#' term='development'/><category scheme='http://www.blogger.com/atom/ns#' term='SharePoint'/><category scheme='http://www.blogger.com/atom/ns#' term='Spring.Net'/><title type='text'>Spring.Net and SharePoint</title><content type='html'>&lt;em&gt;I really like test-driven development (TDD). I like the architecture that is forced upon you, and I definately like the quality output from the team. TDD simply works great, especially in combination with a continuous integration environment such as CruiseControl.Net or Microsoft Team Foundation Server.&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;So, of course I like to use tools or frameworks that enhance the TDD aspects of my projects. &lt;em&gt;Or, to put it this way, I like tools and frameworks that enhance my projects, period.&lt;/em&gt; And &lt;strong&gt;Spring.Net&lt;/strong&gt;... well, it really enhances my projects!&lt;br /&gt;&lt;br /&gt;And, as an added bonus, you don't have to be too envious of those Java geeks talking about how great Spring is anymore. Great eh?&lt;br /&gt;&lt;br /&gt;Spring.Net gives me access to:&lt;br /&gt;* Inversion of Control (IoC) (&lt;a href="http://en.wikipedia.org/wiki/Inversion_of_control"&gt;http://en.wikipedia.org/wiki/Inversion_of_control&lt;/a&gt;)&lt;br /&gt;* Aspect-Oriented Programming (&lt;a href="http://en.wikipedia.org/wiki/Aspect-oriented_programming"&gt;http://en.wikipedia.org/wiki/Aspect-oriented_programming&lt;/a&gt;)&lt;br /&gt;&lt;br /&gt;So, of course I'd like to use Spring.Net in my SharePoint projects. At the start, I was not so sure whether the technologies would work nicely together. But, let me assure you, after running it in two MOSS 2007 projects, I have still to find any problems with the combination.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Inversion of Control&lt;/strong&gt;&lt;br /&gt;By using Spring.Net I get a simple dependency injection running. It does create some hassle for the developer since dependencies between objects are now specified separately from the class file. But - we get the perfect TDD architecture running. Creating unit tests with mocking logic is now very simple. My junior developers also learn to code in a more structured fashion - with more "black box" design.&lt;br /&gt;&lt;br /&gt;Do I apply dependency injection on all my objects then? No. So far I've only done this for Business and Data layers - that is, everything but the UI layer.&lt;br /&gt;&lt;br /&gt;Why? For two reasons - it would complicate things for SharePoint, and well, I generally do not develop unit tests for user components anyhow since testing graphical interfaces is quite complex and expensive. Note that I make sure to keep logic in the UI layer at a bare minimum of course.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Aspect-oriented programming&lt;/strong&gt;&lt;br /&gt;Now, here's where the real fun begins. You do not see the value with dependency injection? Fine, you'll do well enough without it, especially with a good mocking framework.&lt;br /&gt;&lt;br /&gt;But, using Spring.Net's dependency injection is required to get aspects working. Imagine the possible potential of developing your own aspects! So, have I created my own aspects? &lt;em&gt;No. &lt;/em&gt;Quite frankly, so far I've only come around to using the built-in aspects available in Spring.Net. But boy, are they worth it.&lt;br /&gt;&lt;br /&gt;One in particular stand out - the caching aspect. It uses the ASP.Net caching to work it's magic and since we're building a portal using SharePoint, it's a perfect fit. And lets face it - a portal will require a lot of caching to get the performance of a user-friendly site.&lt;br /&gt;&lt;br /&gt;I've used several caching frameworks in my career (for example Microsoft Enterprise Library) and Spring.Net easily beats any other frameworks I've tested. &lt;em&gt;Put simply, the caching aspect has saved weeks of work in my latest projects, and not once has it not worked as expected.&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;Time for an example:&lt;br /&gt;In your data layer &lt;span style="font-family:courier new;"&gt;SettingsDac&lt;/span&gt; is responsible for retrieving and storing settings in your application. Settings are stored in a SharePoint list, but getting them from the list each time will impact on performance, so you want some caching.&lt;br /&gt;&lt;br /&gt;This is the code, using Spring.Net and the caching aspect (a bit simplified):&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;[CacheResult(CACHENAME, "'Setting.Key=' + #key")]&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;public SettingsBE GetSetting(string key)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;SPList list = GetSecurityElevatedList(LISTNAME);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;// TODO: Validate list.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;SPQuery query = new SPQuery();&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;query.Query = string.Format(QUERY_KEY, key);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;SPListItemCollection listItemCollection = list.GetItems(query);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;// TODO: Validate that we have exactly one result.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;return CreateSetting(listItemCollection[0]);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;As you can see, the only code the developer needs to get caching is the attribute &lt;span style="font-family:courier new;"&gt;CacheResult&lt;/span&gt;, the rest is done automatically (with the help of some configuration).&lt;br /&gt;&lt;br /&gt;So, AOP might be complex sure, and all developers won't understand how it works, but frankly... When it's as simple as in the example above to use... do they have to understand it? As long as they get directives to, for example, only use it in DAC classes.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;If you haven't tried out Spring.Net yet - do it now. You'll never regret it. :-)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3706294656317442171-7628025929086603133?l=www.terborn.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.terborn.com/feeds/7628025929086603133/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3706294656317442171&amp;postID=7628025929086603133' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3706294656317442171/posts/default/7628025929086603133'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3706294656317442171/posts/default/7628025929086603133'/><link rel='alternate' type='text/html' href='http://www.terborn.com/2008/07/springnet-and-sharepoint.html' title='Spring.Net and SharePoint'/><author><name>Terborn</name><uri>http://www.blogger.com/profile/08699582580311827918</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='21' src='http://2.bp.blogspot.com/_YZ6h0DIe-AY/SJ8hnRT_OsI/AAAAAAAAAR0/i0s6-3N1BUA/s1600-R/IMG_1119_lzn-2.jpg'/></author><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3706294656317442171.post-8594670594559437818</id><published>2008-07-08T12:43:00.007+02:00</published><updated>2008-07-08T13:31:04.416+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='moss 2007'/><category scheme='http://www.blogger.com/atom/ns#' term='global'/><category scheme='http://www.blogger.com/atom/ns#' term='development'/><category scheme='http://www.blogger.com/atom/ns#' term='SharePoint'/><category scheme='http://www.blogger.com/atom/ns#' term='local'/><title type='text'>Global and local information in one page</title><content type='html'>I recently had to solve a challenging requirement for a MOSS 2007 site we were building a prototype for.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;The scenario&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;A central organisation creates articles (using a complex approval workflow). Local organisations shall be able to add local information to these articles (using a simple approval workflow). Only additions are allowed at specific places in the article - the global information may not be overridden.&lt;br /&gt;&lt;br /&gt;Now, users of the site should by default see the global article. When they select a local branch however, the same information shall be visible with the local information added to the page.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;The solution&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Our first thought was to use variations. But it didn't feel right. Not enough control, and we might want to use variations for language later on.&lt;br /&gt;&lt;br /&gt;Instead, we chose to have one global site that contained all global articles. Another site contained all local organisations, and below each of these we had a container with local articles. However, it was imperative that we did not duplicate any content - &lt;em&gt;that's quite simply against my principles&lt;/em&gt;.&lt;br /&gt;&lt;br /&gt;Global articles used the content type &lt;span style="font-family:courier new;"&gt;GlobalArticle&lt;/span&gt; while the local articles used the content type &lt;span style="font-family:courier new;"&gt;LocalArticle&lt;/span&gt;. Each &lt;span style="font-family:courier new;"&gt;LocalArticle&lt;/span&gt; contains a reference to a &lt;span style="font-family:courier new;"&gt;GlobalArticle&lt;/span&gt;. The &lt;span style="font-family:courier new;"&gt;LocalArticle&lt;/span&gt; does not contain the fields that exist in &lt;span style="font-family:courier new;"&gt;GlobalArticle&lt;/span&gt;, but instead contains a field for each place where local content is allowed.&lt;br /&gt;&lt;br /&gt;The PageLayout used for rendering a &lt;span style="font-family:courier new;"&gt;LocalArticle&lt;/span&gt; looks up the &lt;span style="font-family:courier new;"&gt;GlobalArticle&lt;/span&gt; and renders its information in a read-only mode. In other aspects, it works just like any other PageLayout, allowing an editor to modify the local content as usual.&lt;br /&gt;&lt;br /&gt;The appeal of this solution is that we use standard MOSS functionality almost all the way, with only a minimal look-up in the local PageLayout. We support standard MOSS page workflows. Global content is automatically updated on the local site without we having to do anything.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;img id="BLOGGER_PHOTO_ID_5220601236239766322" style="DISPLAY: block; MARGIN: 0px auto 10px; CURSOR: hand; TEXT-ALIGN: center" alt="" src="http://1.bp.blogspot.com/_YZ6h0DIe-AY/SHNNKhgJUzI/AAAAAAAAAC0/CPp_35-n9KQ/s400/moss_local_global_structure.png" border="0" /&gt;&lt;br /&gt;&lt;strong&gt;Solution details&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Some additional challenges existed though. We wanted to make a local article available automatically when the first global article was published. Also, the article context should remain on the user screen even when the user switched between the global to a local view, and between different local views.&lt;br /&gt;&lt;br /&gt;The components we needed:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;A business service that returns the local sites&lt;br /&gt;&lt;em&gt;Simply list all sites in the "local sites" site.&lt;/em&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;em&gt;A&lt;/em&gt;n event that listens to changes in the global article list&lt;br /&gt;&lt;em&gt;When an article is published (or unpublished) it checks whether a local copy exists in each local site. If not, it creates and publishes a LocalArticle in the local store, with a reference to the recently published GlobalArticle.&lt;/em&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;A little user component letting the user switch to a local context&lt;br /&gt;&lt;em&gt;The important thing here was to still remain on the same article. Quite easy thanks to the structure we used.&lt;/em&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;That's basically it. Might be worth mentioning that the user interface was designed to clearly show what information was global and what was local by use of both icons and color.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3706294656317442171-8594670594559437818?l=www.terborn.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.terborn.com/feeds/8594670594559437818/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3706294656317442171&amp;postID=8594670594559437818' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3706294656317442171/posts/default/8594670594559437818'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3706294656317442171/posts/default/8594670594559437818'/><link rel='alternate' type='text/html' href='http://www.terborn.com/2008/07/global-and-local-information-in-one.html' title='Global and local information in one page'/><author><name>Terborn</name><uri>http://www.blogger.com/profile/08699582580311827918</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='21' src='http://2.bp.blogspot.com/_YZ6h0DIe-AY/SJ8hnRT_OsI/AAAAAAAAAR0/i0s6-3N1BUA/s1600-R/IMG_1119_lzn-2.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_YZ6h0DIe-AY/SHNNKhgJUzI/AAAAAAAAAC0/CPp_35-n9KQ/s72-c/moss_local_global_structure.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3706294656317442171.post-6050896406982494464</id><published>2008-02-27T13:30:00.005+01:00</published><updated>2008-02-27T14:14:06.502+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='moss 2007'/><category scheme='http://www.blogger.com/atom/ns#' term='development'/><category scheme='http://www.blogger.com/atom/ns#' term='SharePoint'/><category scheme='http://www.blogger.com/atom/ns#' term='friendly urls'/><category scheme='http://www.blogger.com/atom/ns#' term='simple urls'/><title type='text'>Simple URLs in SharePoint</title><content type='html'>The ability to create simple URLs in a public site is important, especially for public web sites. One of my customers wants to use these simple links in paper ads and other documentations. Quite understandable.&lt;br /&gt;&lt;br /&gt;A typical URL to available jobs on a MOSS site would be:&lt;br /&gt;mysite.com/about/jobs&lt;br /&gt;&lt;br /&gt;Or even worse, if it's a page and not a sub site:&lt;br /&gt;mysite.com/about/Pages/jobs.aspx&lt;br /&gt;&lt;br /&gt;Creating a nice link like "mysite.com/jobs" in standard MOSS would require you to create a sub site named "jobs" directly in the site collection. Not very nice if you like to structure your content properly.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;A solution&lt;/strong&gt;&lt;br /&gt;A work-around would be to always only print the link to the start page (for example mysite.com) and guide the user from there. But that's too simple right, and not always sufficient. &lt;em&gt;For ads, yes, for documentation that will be in play for a long time, no.&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;Instead, enter the HTTP module.&lt;br /&gt;&lt;br /&gt;Basically, this is standard ASP.Net technology, and a great article about this approach can be found here:&lt;br /&gt;&lt;a href="http://msdn2.microsoft.com/en-us/library/ms972974.aspx"&gt;http://msdn2.microsoft.com/en-us/library/ms972974.aspx&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Step 1 - create the HTTP module class&lt;/strong&gt;&lt;br /&gt;In your Visual Studio solution, create a class similar to this (of course, choose a proper namespace):&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;using System;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;using System.Collections.Generic;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;using System.Text;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;using System.Web;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;namespace MyNamespace&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;public class UrlRedirectHttpModule : IHttpModule&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;public virtual void Init(HttpApplication pApplication)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;pApplication.BeginRequest += new EventHandler(BeginRequest);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;public virtual void Dispose()&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;void BeginRequest(object pSender, EventArgs pArgs)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;HttpApplication application = (HttpApplication)pSender;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;// TODO: Implement simple link switching here.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;if (application.Request.Path.EndsWith("a"))&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;application.Response.Redirect("&lt;/span&gt;&lt;a href="http://www.google.com/"&gt;&lt;span style="font-family:courier new;"&gt;http://www.google.com&lt;/span&gt;&lt;/a&gt;&lt;span style="font-family:courier new;"&gt;", true);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Step 2 - Modify web.config&lt;/strong&gt;&lt;br /&gt;Add the following line last into the "&amp;lt;&lt;span style="font-family:courier new;"&gt;system.web&gt;&amp;lt;httpModules&gt;&lt;/span&gt;" section:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;lt;add name="UrlRedirect" type="MyNamespace.UrlRedirectHttpModule, MyNamespace, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Of course, modify the namespace name. Also specify PublicKeyToken if your assembly is signed. &lt;em&gt;Which I recommend you do by the way.&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Step 3 - Enhancement&lt;/strong&gt;&lt;br /&gt;I suggest you create a list in your SharePoint solution that basically contains the simple url in the first column, and the redirect url in the second column. &lt;em&gt;These might or might not support regular expressions, depending on the targeted users/administrators of the simple url functionality.&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;In your "BeginRequest" event listener, simply do a look-up to the SharePoint list and check if a redirect should occur or not. Oh, and remember to cache the look-up as well for better performance. Note that this check will occur for every HTTP request!&lt;br /&gt;&lt;br /&gt;That's it!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3706294656317442171-6050896406982494464?l=www.terborn.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.terborn.com/feeds/6050896406982494464/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3706294656317442171&amp;postID=6050896406982494464' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3706294656317442171/posts/default/6050896406982494464'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3706294656317442171/posts/default/6050896406982494464'/><link rel='alternate' type='text/html' href='http://www.terborn.com/2008/02/simple-urls-in-sharepoint.html' title='Simple URLs in SharePoint'/><author><name>Terborn</name><uri>http://www.blogger.com/profile/08699582580311827918</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='21' src='http://2.bp.blogspot.com/_YZ6h0DIe-AY/SJ8hnRT_OsI/AAAAAAAAAR0/i0s6-3N1BUA/s1600-R/IMG_1119_lzn-2.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3706294656317442171.post-428655537619349382</id><published>2008-02-18T19:16:00.002+01:00</published><updated>2008-02-18T19:31:07.780+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='personal'/><title type='text'>Running away from a run</title><content type='html'>Next time, please remind me not to agree to stupid things when I meet my colleagues by the pub for a little afterwork. &lt;em&gt;Please.&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;So, what did I agree on? &lt;em&gt;Oh, shivers run through my body when I think of it.&lt;/em&gt; I agreed to run the Gothenburg semi-marathon "Göteborgsvarvet". Or, look at it this way: In a couple of month's time I shall run 21 km while competing with tens of thousands of others. &lt;em&gt;Shit. I'm dead.&lt;/em&gt; Oh. Ran 13km yesterday, my first trial so-to-speak, and today... My left foot aches like hell, my legs can hardly walk down stairs, my right knee makes strange noises and hurts... well... a little. &lt;em&gt;I'm dead. Soon.&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;Just promise me one thing. On my gravestone, don't write any bad puns like "He liked SCRUM, but did he have to sprint to his death?"&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3706294656317442171-428655537619349382?l=www.terborn.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.terborn.com/feeds/428655537619349382/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3706294656317442171&amp;postID=428655537619349382' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3706294656317442171/posts/default/428655537619349382'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3706294656317442171/posts/default/428655537619349382'/><link rel='alternate' type='text/html' href='http://www.terborn.com/2008/02/running-away-from-run.html' title='Running away from a run'/><author><name>Terborn</name><uri>http://www.blogger.com/profile/08699582580311827918</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='21' src='http://2.bp.blogspot.com/_YZ6h0DIe-AY/SJ8hnRT_OsI/AAAAAAAAAR0/i0s6-3N1BUA/s1600-R/IMG_1119_lzn-2.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3706294656317442171.post-2862642393568764838</id><published>2008-01-25T15:15:00.000+01:00</published><updated>2008-01-25T15:29:11.171+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='moss 2007'/><category scheme='http://www.blogger.com/atom/ns#' term='development'/><category scheme='http://www.blogger.com/atom/ns#' term='SharePoint'/><category scheme='http://www.blogger.com/atom/ns#' term='W3C'/><title type='text'>SharePoint and HTML 4.0</title><content type='html'>&lt;em&gt;I'm proud of my work and what I do. I love to deliver high quality products. And I love working with the SharePoint suite of products. My problem right now is that these two things aren't fully compatible! And it hurts.&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;Part of delivering a quality web site, be it internal or external, is that it fully conforms to a standard of some sort. In this day and age, that means either HTML 4.0 or XHTML 1.0. The bad news is that the out-of-the-box SharePoint installation... well... just isn't quite up to the task.&lt;br /&gt;&lt;br /&gt;As a developer, you'll have to do some additional work to get closer to the standard. Now, truth be told, I think that the product I deliver is good enough. We've done successful tests with visually impaired, to mention one example. But for a perfectionist like me, it still is painful to se my solution not fully validating to the W3C compatibility checker.&lt;br /&gt;&lt;br /&gt;Of course, I've talked to Microsoft about this. They basically refer me to this article:&lt;br /&gt;&lt;a href="http://zac.provoke.co.nz/archive/2007/04/19/guide-to-making-sharepoint-xhtml-compliant.aspx"&gt;http://zac.provoke.co.nz/archive/2007/04/19/guide-to-making-sharepoint-xhtml-compliant.aspx&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Oh well... Who knows what Service Pack 2 will contain... :-)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3706294656317442171-2862642393568764838?l=www.terborn.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.terborn.com/feeds/2862642393568764838/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3706294656317442171&amp;postID=2862642393568764838' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3706294656317442171/posts/default/2862642393568764838'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3706294656317442171/posts/default/2862642393568764838'/><link rel='alternate' type='text/html' href='http://www.terborn.com/2008/01/sharepoint-and-html-40.html' title='SharePoint and HTML 4.0'/><author><name>Terborn</name><uri>http://www.blogger.com/profile/08699582580311827918</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='21' src='http://2.bp.blogspot.com/_YZ6h0DIe-AY/SJ8hnRT_OsI/AAAAAAAAAR0/i0s6-3N1BUA/s1600-R/IMG_1119_lzn-2.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3706294656317442171.post-7983453009116256169</id><published>2008-01-20T19:06:00.000+01:00</published><updated>2008-01-20T21:29:23.588+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='moss 2007'/><category scheme='http://www.blogger.com/atom/ns#' term='comments'/><category scheme='http://www.blogger.com/atom/ns#' term='development'/><category scheme='http://www.blogger.com/atom/ns#' term='SharePoint'/><title type='text'>Adding comments to a page in MOSS</title><content type='html'>I'm a big fan of the Web 2.0 concept. I want to build sites where people are communicating, sharing, and creating something bigger together. Today, company sites and intranets are often very static. How many sites have you not seen that are basically just a hierarchy of information pages created by a few web authors? &lt;em&gt;I want to change this!&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;A small start would be to allow comments on the typical static information pages, basically the same as a blog entry can be commented upon. Many online news papers have adopted this idea, and I often find myself enjoying the comments more than the article itself!&lt;br /&gt;&lt;br /&gt;The basic principle for my implementation is to have a web part presenting the page comments on a page. The comments themselves reside in a list. Bunch together the web part, content part definitions, list definitions and the domain-model implementation into a WSS feature/solution and viola - you're done! &lt;em&gt;I also use IoC and AOP for caching using Spring.Net, but that's just for fun really. :-)&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;Let me flesh this out a bit.&lt;br /&gt;&lt;br /&gt;The domain model business class can have a simple interface like this:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;public interface IPageCommentBC&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;void CreatePageComment(PageCommentBE comment);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;PageCommentListBE GetPageComments(int pageId);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The "data access component" responsible for SharePoint communication (i.e. to read/write to the list) uses a similar interface. Note that you probably will want to request higher access rights in your code so that you may restict access to the list itself but still allow users to read/write using your web part.&lt;br /&gt;&lt;br /&gt;The web part gets the page ID using the SharePoint context (SPContext). When it has the page ID it can easily call the business component to get a list of all posts, and also save new posts.&lt;br /&gt;&lt;br /&gt;Code for creating a page comment in your web part code behind may look something like this:&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;// Submit comment.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;int pageId = SPContext.Current.ItemId;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;IPageCommentBC pageCommentBC = BusinessFactory.PageCommentBC;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;PageCommentBE comment = new PageCommentBE();&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;comment.PageId = pageId;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;comment.Title = mTitleTextBox.Text;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;comment.Body = mBodyTextBox.Text;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;pageCommentBC.CreatePageComment(comment);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The content type is easy. Minimally, you will want to inherit from Item and add two fields - PageId and Body. The content type will thus have Title, PageId and Body fields. The list itself will add default columns such as the creator and creation date. You can add additional columns to the content type to get more functionality, such as for anonymous users, modified functionality and so on.&lt;br /&gt;&lt;br /&gt;Of course, you will have to be a bit smart when implementing - for example you will need some algoritm to avoid duplicate posts.&lt;br /&gt;&lt;br /&gt;That's it really. Let me know if you want me to add some more information or if you have some comments!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3706294656317442171-7983453009116256169?l=www.terborn.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.terborn.com/feeds/7983453009116256169/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3706294656317442171&amp;postID=7983453009116256169' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3706294656317442171/posts/default/7983453009116256169'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3706294656317442171/posts/default/7983453009116256169'/><link rel='alternate' type='text/html' href='http://www.terborn.com/2008/01/adding-comments-to-page-in-moss.html' title='Adding comments to a page in MOSS'/><author><name>Terborn</name><uri>http://www.blogger.com/profile/08699582580311827918</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='21' src='http://2.bp.blogspot.com/_YZ6h0DIe-AY/SJ8hnRT_OsI/AAAAAAAAAR0/i0s6-3N1BUA/s1600-R/IMG_1119_lzn-2.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3706294656317442171.post-5726910088522999494</id><published>2008-01-18T11:40:00.000+01:00</published><updated>2008-01-20T15:35:27.232+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='personal'/><category scheme='http://www.blogger.com/atom/ns#' term='fanboy'/><category scheme='http://www.blogger.com/atom/ns#' term='Capgemini'/><title type='text'>Working at Capgemini</title><content type='html'>Well here I am... Completely stressed out, documenting a big workshop that's been going on for several days (working from 7.30AM to 11PM several days in a row is exhausting). And I get interrupted all the time by colleagues with ideas, thoughts and questions. Stressful, yes, but also great fun to be in the middle of all this business! &lt;em&gt;Live meetings, phone, mail, MSN, Facebook... Probably should cut down on communication medias or something. Hehe.&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;A colleague out of Mumbai sent an MSN-message and asked if I had any new MOSS projects on the horizon. Apparently he enjoyed working with me and would like to do so again - even if it meant going back to Sweden for a while.&lt;br /&gt;&lt;br /&gt;And suddenly I got this happiness rush, realizing how much I love working at Capgemini. So many outstanding, enthusiastic people with such different sets of skills and so many nationalities. Simply put: Amazing!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3706294656317442171-5726910088522999494?l=www.terborn.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.terborn.com/feeds/5726910088522999494/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3706294656317442171&amp;postID=5726910088522999494' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3706294656317442171/posts/default/5726910088522999494'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3706294656317442171/posts/default/5726910088522999494'/><link rel='alternate' type='text/html' href='http://www.terborn.com/2008/01/working-at-capgemini.html' title='Working at Capgemini'/><author><name>Terborn</name><uri>http://www.blogger.com/profile/08699582580311827918</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='21' src='http://2.bp.blogspot.com/_YZ6h0DIe-AY/SJ8hnRT_OsI/AAAAAAAAAR0/i0s6-3N1BUA/s1600-R/IMG_1119_lzn-2.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3706294656317442171.post-4200321548459072153</id><published>2008-01-02T20:14:00.000+01:00</published><updated>2008-01-02T20:20:24.539+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='personal'/><title type='text'>Happy new year!</title><content type='html'>I had a marvelous new year's eve celebration up in Gothenburg this year. Spent it at &lt;a href="http://www.stenungsbaden.se/"&gt;http://www.stenungsbaden.se&lt;/a&gt; - a hotel in Stenungsund, just by the water. &lt;em&gt;Of course they had to charge extra for late check out. Irritating, but surely a nice extra income for them. Really, how many are capable of driving home att 11 am after a night of celebration? Not I...&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;Anyways, cheers! Have a happy 2008!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3706294656317442171-4200321548459072153?l=www.terborn.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.terborn.com/feeds/4200321548459072153/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3706294656317442171&amp;postID=4200321548459072153' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3706294656317442171/posts/default/4200321548459072153'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3706294656317442171/posts/default/4200321548459072153'/><link rel='alternate' type='text/html' href='http://www.terborn.com/2008/01/happy-new-year.html' title='Happy new year!'/><author><name>Terborn</name><uri>http://www.blogger.com/profile/08699582580311827918</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='21' src='http://2.bp.blogspot.com/_YZ6h0DIe-AY/SJ8hnRT_OsI/AAAAAAAAAR0/i0s6-3N1BUA/s1600-R/IMG_1119_lzn-2.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3706294656317442171.post-6409428475981432787</id><published>2007-12-22T19:57:00.000+01:00</published><updated>2007-12-22T20:14:38.659+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='moss 2007'/><category scheme='http://www.blogger.com/atom/ns#' term='development'/><category scheme='http://www.blogger.com/atom/ns#' term='SharePoint'/><title type='text'>A new public MOSS site - VA SYD</title><content type='html'>Wow!&lt;br /&gt;&lt;br /&gt;One of my project's has reached 1.0 and is now available online. &lt;em&gt;I just wish more of my projects were public so that I can show friends and family what I do...&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;This small project was very time intensive - we had about two month's worth of project time, not much, but we did it in time, as usual. :-)&lt;br /&gt;&lt;br /&gt;Well, here's the link:&lt;br /&gt;&lt;a href="http://www.vasyd.se/"&gt;http://www.vasyd.se/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;And yes, it's in swedish. It's the public site for VA SYD - the organisation responsible for water and refusal management in the muncipalites of Malmö and Lund in Sweden.&lt;br /&gt;&lt;br /&gt;Please, let me know what you think.&lt;br /&gt;&lt;br /&gt;(And yes, I know, we do not fully conform to W3C standards and there's some other chinks in the armor too at the moment. I at least partially blame MOSS, but more of that in a later post.)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3706294656317442171-6409428475981432787?l=www.terborn.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.terborn.com/feeds/6409428475981432787/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3706294656317442171&amp;postID=6409428475981432787' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3706294656317442171/posts/default/6409428475981432787'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3706294656317442171/posts/default/6409428475981432787'/><link rel='alternate' type='text/html' href='http://www.terborn.com/2007/12/new-public-moss-site-va-syd.html' title='A new public MOSS site - VA SYD'/><author><name>Terborn</name><uri>http://www.blogger.com/profile/08699582580311827918</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='21' src='http://2.bp.blogspot.com/_YZ6h0DIe-AY/SJ8hnRT_OsI/AAAAAAAAAR0/i0s6-3N1BUA/s1600-R/IMG_1119_lzn-2.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3706294656317442171.post-394474561958228360</id><published>2007-12-22T19:50:00.000+01:00</published><updated>2007-12-22T20:12:47.457+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='personal'/><title type='text'>What? Christmas? Already?!?</title><content type='html'>Is it already late december? Oh my... What happened to november?&lt;br /&gt;&lt;br /&gt;Hmm... Hardly bought any christmas presents yet. And I can't really buy chocolates and liqour to the whole family right? Damn! There's surely going to be some desperate shopping tomorrow!!&lt;br /&gt;&lt;br /&gt;So, why has this blog been more or less dead? Well, I've been busy, that's why. Not only do I need to close a lot of business before year's end - I'm also a single man in my "best" years... And you all know how much work that can be right? :-)&lt;br /&gt;&lt;br /&gt;Hopefully I'll be able to summarize my recent thoughts about SharePoint in the following weeks!!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3706294656317442171-394474561958228360?l=www.terborn.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.terborn.com/feeds/394474561958228360/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3706294656317442171&amp;postID=394474561958228360' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3706294656317442171/posts/default/394474561958228360'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3706294656317442171/posts/default/394474561958228360'/><link rel='alternate' type='text/html' href='http://www.terborn.com/2007/12/what-christmas-already.html' title='What? Christmas? Already?!?'/><author><name>Terborn</name><uri>http://www.blogger.com/profile/08699582580311827918</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='21' src='http://2.bp.blogspot.com/_YZ6h0DIe-AY/SJ8hnRT_OsI/AAAAAAAAAR0/i0s6-3N1BUA/s1600-R/IMG_1119_lzn-2.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3706294656317442171.post-6448738570354478388</id><published>2007-10-20T23:47:00.000+02:00</published><updated>2007-11-06T09:06:40.649+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='performance'/><category scheme='http://www.blogger.com/atom/ns#' term='development'/><category scheme='http://www.blogger.com/atom/ns#' term='SharePoint'/><title type='text'>Profiling your MOSS application</title><content type='html'>&lt;div align="left"&gt;So, you've done a great job, the portal contains one hell of a bunch of fancy stuff. The portal chrome shines like a newly washed Aston Martin, and your colleagues "ooohs" and "aaahs" when you show them a screen shot. You even got these cool Ajax features built in.&lt;br /&gt;&lt;br /&gt;Now, if the bloody portal would just respond to a click before you die of old age...&lt;br /&gt;&lt;br /&gt;So, you start to think of streamlining the portal and bring up your trusted profiling application. Or do you still do the System.Diagnostics.Debug.WriteLine? If so, stop, now.&lt;br /&gt;&lt;br /&gt;What profiling application then? Well, the one in Visual Studio might work, but personally I prefer to use dotTrace. Easy to setup and use on your MOSS site, and it gives results easy to analyze, at least if you use the flat view and sort the list properly.&lt;br /&gt;&lt;br /&gt;http://www.jetbrains.com/profiler/&lt;br /&gt;&lt;br /&gt;But - hey - the profiling tools won't work in your virtual environment! So annoying, I know. What to do then? You did read my earlier post on setting up a development support environment right? Well, I just hope you didn't use a virtual environment for that one...&lt;br /&gt;&lt;br /&gt;Bottom line - it's nice to have one environment for your portal that do not use a virtual server. Or is there anyone out there that have tips on getting dotTrace or any other profiler to work in a virtual environment?&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3706294656317442171-6448738570354478388?l=www.terborn.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.terborn.com/feeds/6448738570354478388/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3706294656317442171&amp;postID=6448738570354478388' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3706294656317442171/posts/default/6448738570354478388'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3706294656317442171/posts/default/6448738570354478388'/><link rel='alternate' type='text/html' href='http://www.terborn.com/2007/10/profiling-your-moss-application.html' title='Profiling your MOSS application'/><author><name>Terborn</name><uri>http://www.blogger.com/profile/08699582580311827918</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='21' src='http://2.bp.blogspot.com/_YZ6h0DIe-AY/SJ8hnRT_OsI/AAAAAAAAAR0/i0s6-3N1BUA/s1600-R/IMG_1119_lzn-2.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3706294656317442171.post-8466498847186584918</id><published>2007-10-20T23:30:00.000+02:00</published><updated>2007-10-20T23:46:14.795+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='development'/><category scheme='http://www.blogger.com/atom/ns#' term='SharePoint'/><title type='text'>Performance with WSS 3.0 API calls</title><content type='html'>In the end, what you want to deliver to your client is a powerhouse of a portal. It should contain all these fantastic features and integrations, and still respond within a second right?&lt;br /&gt;&lt;br /&gt;So, of course we cache all integrations where possible, that's an obvious performance tweak. But did you know that you'll most likely will have to cache many of your MOSS read API calls as well? Not as obvious to me, but when I started profiling my portal... Well, a couple of hours work and the portal morphed from turtle to viper. :-)&lt;br /&gt;&lt;br /&gt;To name an example, if your portal is somewhat complex, I'm guessing you'll have added a settings list that you access through the WSS API. (You of course do not want it in your web.config since that is hard both to deploy and to administer.)&lt;br /&gt;&lt;br /&gt;In my case, these settings were accessed over a hundred times in one request (yes, a lot, but it's one complicated first page, I'll tell you...). Now, this actually took seconds to process on my virtual environment. A simple cache layer that sets all those calls to zero ms - and yeehaa - response times worth talking about.&lt;br /&gt;&lt;br /&gt;Bottom line - don't trust SharePoint to help you out with performance!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3706294656317442171-8466498847186584918?l=www.terborn.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.terborn.com/feeds/8466498847186584918/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3706294656317442171&amp;postID=8466498847186584918' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3706294656317442171/posts/default/8466498847186584918'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3706294656317442171/posts/default/8466498847186584918'/><link rel='alternate' type='text/html' href='http://www.terborn.com/2007/10/performance-with-wss-30-api-calls.html' title='Performance with WSS 3.0 API calls'/><author><name>Terborn</name><uri>http://www.blogger.com/profile/08699582580311827918</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='21' src='http://2.bp.blogspot.com/_YZ6h0DIe-AY/SJ8hnRT_OsI/AAAAAAAAAR0/i0s6-3N1BUA/s1600-R/IMG_1119_lzn-2.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3706294656317442171.post-8068799219845239454</id><published>2007-09-24T22:50:00.000+02:00</published><updated>2007-09-25T17:58:22.925+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='moss 2007'/><category scheme='http://www.blogger.com/atom/ns#' term='deployment'/><category scheme='http://www.blogger.com/atom/ns#' term='development'/><category scheme='http://www.blogger.com/atom/ns#' term='SharePoint'/><title type='text'>Version dependent deployment with MOSS 2007</title><content type='html'>&lt;em&gt;Want to deploy your MOSS 2007 solutions with one file – a file that will also deploy content and support future upgrades without overriding changes to old deployed content? Well, read on to see how I solved this.&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;I like to package my solutions. In a perfect world a delivery from one of my projects consist of one file – usually a .msi file, or, in terms of MOSS, a .wsp file.&lt;br /&gt;&lt;br /&gt;I also believe that a developer never should touch the production environment. The development team will instead produce the required documentation to allow an administrator of some sort to perform deployment to the production environment. Of course, this is hardly possible if the installation requires too much manual work or is too complex.&lt;br /&gt;&lt;br /&gt;Finally, it must be very simple to upgrade the solution to a new version – both for fixing defects and for new functionality.&lt;br /&gt;&lt;br /&gt;So, how to perform the above for a MOSS 2007 solution? Before we can answer this question, we need to answer the question: What do we want to deploy?&lt;br /&gt;&lt;br /&gt;This is what I personally have wanted to deploy in my MOSS projects so far:&lt;br /&gt;• Compiled code (DLL files)&lt;br /&gt;• Artifacts - master pages, page layouts, style sheets, script files and images&lt;br /&gt;• Entities – fields, content types, list templates and web parts&lt;br /&gt;• Permission groups&lt;br /&gt;• Content: Lists with data&lt;br /&gt;• Content: Site structure – sub sites (webs), pages and customized navigation&lt;br /&gt;• Content: Pages and publishing pages containing pre-configured web parts and publishing data&lt;br /&gt;&lt;br /&gt;Of course, there are other things to deploy automatically, such as workflows, BDC configurations and custom reports, but I’ll leave such out of here since I’ve not done this myself so far.&lt;br /&gt;&lt;br /&gt;So, what can standard MOSS 2007 functionality provide in terms of deployment? The MOSS 2007 solution package with features is great for deploying compiled code, artifacts and entities and in this regard I need nothing more. However, when we look at content what I’ve seen so far is very lacking. Actually, I’m quite confounded that so little is offered.&lt;br /&gt;&lt;br /&gt;For example, it is possible to deploy an instance of a list, with data, in a feature using the standard solution package. But, what happens when you upgrade? All existing content in the list will be overwritten! Let’s say you deploy a Settings list, containing settings for your application. After initial deployment the administrators change some settings accordingly to the production environment. When the new version arrives – all previous settings return to their original values. Horrible! Site templates do not seem to work in an upgrade scenario either. Please correct me if I’m wrong, but I hereby claim there is no way of solving this nicely using standard MOSS functionality!&lt;br /&gt;&lt;br /&gt;Ok, so what can we do?&lt;br /&gt;&lt;br /&gt;Use a Visual Studio 2005 solution to build a .wsp solution file. The manifest.xml and the .ddf files are created manually to get full control. Everything but content is deployed in features as normal.&lt;br /&gt;&lt;br /&gt;For content, an XML structure is designed that contain all information about the content to deploy, structured within a version structure. A corresponding XML schema file is created for validation purposes and for IntelliSense support in Visual Studio.&lt;br /&gt;&lt;br /&gt;The XML structure is similar to this:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;content system=”MySystem”&amp;gt;&lt;br /&gt;  &amp;lt;versions&amp;gt;&lt;br /&gt;    &amp;lt;version id=”MyFeature_1”&amp;gt;&lt;br /&gt;      &amp;lt;sites&amp;gt;&amp;lt;!-- Site content in here --&amp;gt;&amp;lt;/sites&amp;gt;&lt;br /&gt;      &amp;lt;pages&amp;gt;&amp;lt;!-- Page content in here --&amp;gt;&amp;lt;/pages&amp;gt;&lt;br /&gt;      &amp;lt;lists&amp;gt;&amp;lt;!-- List content in here --&amp;gt;&amp;lt;/lists&amp;gt;&lt;br /&gt;    &amp;lt;/version&amp;gt;&lt;br /&gt;    &amp;lt;version id=”MyFeature_2”&amp;gt;&lt;br /&gt;      &amp;lt;!-- Sites, Pages, Lists and other data here --&amp;gt;&lt;br /&gt;    &amp;lt;/version&amp;gt;&lt;br /&gt;  &amp;lt;/versions&amp;gt;&lt;br /&gt;&amp;lt;/content&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The structure may also contain logic for deletion and update of data which may be required in later versions of your solution. I’d suggest you simply create a structure that is good enough for your project at this time and add functionality when a new version requires it.&lt;br /&gt;&lt;br /&gt;A standard feature event listener is then created. All features that want to deploy content add this feature listener in their feature.xml file and put the XML data in the Feature\Content\DeploymentContent.xml file. The standard feature event listener will know the location of the feature and can thus find this file when triggered. The feature listener will listen to the feature activation event. When the event is triggered we will thus know which site/web to deploy on (depending on feature scope) and we have access to the XML data. The feature listener will simply call the DeploymentManager with this information.&lt;br /&gt;&lt;br /&gt;The DeploymentManager class will perform XML validation (using XmlDocument) and then parse the XML. I personally prefer to use XML serialization instead of using XmlDocument or XmlReader, but I guess that does not really matter. :-)&lt;br /&gt;&lt;br /&gt;The first time the DeploymentManager is executed, it will create a list called Version, prefixed with the system name in the XML – for example “MySystemVersion”. Each time the DeploymentManager finds a “version” tag in the XML, it will first check if this version is already added to the version list. If it is already added, this version is skipped and the DeploymentManager will move along to the next version. This will ensure that no version is deployed more than once – and this system will also make upgrade from any version to any other version possible – no instructions like “first run patch 1.2, then patch 1.3, to finally run patch 1.4” and such.&lt;br /&gt;&lt;br /&gt;I guess that’s about it. If anyone’s interested, let me know and I might come up with some code examples and such. And of course let me know if you think I’m right or wrong in this approach!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3706294656317442171-8068799219845239454?l=www.terborn.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.terborn.com/feeds/8068799219845239454/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3706294656317442171&amp;postID=8068799219845239454' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3706294656317442171/posts/default/8068799219845239454'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3706294656317442171/posts/default/8068799219845239454'/><link rel='alternate' type='text/html' href='http://www.terborn.com/2007/09/moss-advanced-deployment.html' title='Version dependent deployment with MOSS 2007'/><author><name>Terborn</name><uri>http://www.blogger.com/profile/08699582580311827918</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='21' src='http://2.bp.blogspot.com/_YZ6h0DIe-AY/SJ8hnRT_OsI/AAAAAAAAAR0/i0s6-3N1BUA/s1600-R/IMG_1119_lzn-2.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3706294656317442171.post-2877737841956572809</id><published>2007-09-11T10:33:00.000+02:00</published><updated>2007-09-11T11:12:32.689+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='softris'/><category scheme='http://www.blogger.com/atom/ns#' term='personal'/><category scheme='http://www.blogger.com/atom/ns#' term='tetris'/><category scheme='http://www.blogger.com/atom/ns#' term='game development'/><title type='text'>Softris</title><content type='html'>Every developer has written a game or two in his life right? I’ve probably started developing around 20 games, but only finished four as I can recall. There was the multi-player Worm in Quick Basic (&lt;em&gt;up to 4 worms at a time!&lt;/em&gt;), a Scorched Earth clone with up to eight tanks in Borland Pascal, the Pacman clone (&lt;em&gt;with an animated death sequence!&lt;/em&gt;) in Borland Pascal (&lt;em&gt;all 256 color graphics in Pascal were created with inline assembler code writing directly to graphics card memory back then, cool&lt;/em&gt;), and finally, my last real finished game, the Tetris clone Softris, made in Visual Basic 6.0.&lt;br /&gt;&lt;br /&gt;&lt;img id="BLOGGER_PHOTO_ID_5108862823410381730" style="DISPLAY: block; MARGIN: 0px auto 10px; CURSOR: hand; TEXT-ALIGN: center" alt="" src="http://3.bp.blogspot.com/_YZ6h0DIe-AY/RuZTq4OTM6I/AAAAAAAAAAs/WF_uacqPbAc/s400/softris.png" border="0" /&gt; &lt;em&gt;Softris was actually created to become an easter egg in a retailer system my team was building, but we never had the guts to sneak it in. Pathetic right? ;-)&lt;/em&gt;&lt;br /&gt;&lt;div align="left"&gt;&lt;br /&gt;Back then I really, really disliked VB 6.0. &lt;em&gt;Oh, come to think of it, I still do.&lt;/em&gt; But I didn’t really have much choice - all my Java animated game try-outs back then really never took off, too many graphic glitches for my taste. And my work buddies Martin and Johan challenged me to do some cool stuff in VB… And who am I to shrink away from a challenge?&lt;/div&gt;&lt;div align="left"&gt;&lt;/div&gt;&lt;br /&gt;&lt;div align="left"&gt;So, a week or so later the game was finished. I quickly got a powerful fan base – Johan and my friend Cia, who today are the only ones that actually got a higher score than myself. Several years later, Cia let me know she got over a million points! I still find it hard to believe her, but after seeing her play, well, just say I was quickly convinced.&lt;/div&gt;&lt;div align="left"&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;/div&gt;&lt;br /&gt;&lt;div align="left"&gt;I thought I’d put up the game here and see if I can convince anyone to try my old game out. I would actually state that it’s still quite playable. However, to my dismay I just realized I couldn’t get it to run on Vista. Wonder if there’s some DLL missing or something… Bah, shall my only living game finally beat the dust. Oh, it hurts my 30-year old heart.&lt;/div&gt;&lt;br /&gt;&lt;div align="left"&gt;Oh, and if anyone would like to look at the old code, please go ahead and download the source package. You’ll need Visual Studio 6 to do anything useful with it though. Best of luck.&lt;/div&gt;&lt;br /&gt;&lt;div align="left"&gt;And if you get any good high scores, please let me know. &lt;em&gt;And yes, I know the high score file isn’t encrypted… Go ahead and cheat, you… *eh* you cheater!&lt;/em&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;em&gt;&lt;/em&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;strong&gt;Download Softris&lt;/strong&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;a href="http://www.box.net/shared/kjsqqvefcz"&gt;http://www.box.net/shared/kjsqqvefcz&lt;/a&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;/div&gt;&lt;div align="left"&gt;1. Unzip file.&lt;/div&gt;&lt;div align="left"&gt;2. Open "Softris" folder and run "Softris.exe"&lt;/div&gt;&lt;div align="left"&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;strong&gt;Download Softris source&lt;/strong&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;a href="http://www.box.net/shared/q2q4bhcumn"&gt;http://www.box.net/shared/q2q4bhcumn&lt;/a&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3706294656317442171-2877737841956572809?l=www.terborn.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.terborn.com/feeds/2877737841956572809/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3706294656317442171&amp;postID=2877737841956572809' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3706294656317442171/posts/default/2877737841956572809'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3706294656317442171/posts/default/2877737841956572809'/><link rel='alternate' type='text/html' href='http://www.terborn.com/2007/09/softris.html' title='Softris'/><author><name>Terborn</name><uri>http://www.blogger.com/profile/08699582580311827918</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='21' src='http://2.bp.blogspot.com/_YZ6h0DIe-AY/SJ8hnRT_OsI/AAAAAAAAAR0/i0s6-3N1BUA/s1600-R/IMG_1119_lzn-2.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_YZ6h0DIe-AY/RuZTq4OTM6I/AAAAAAAAAAs/WF_uacqPbAc/s72-c/softris.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3706294656317442171.post-6016951602457414458</id><published>2007-09-05T10:39:00.000+02:00</published><updated>2007-09-05T10:56:06.277+02:00</updated><title type='text'>Graphical design of table headers</title><content type='html'>So, time to rant about one of my pet peeves. :-)&lt;br /&gt;&lt;br /&gt;Too often I see user interfaces where meta data is more pronounced than the data itself. I would say that developers unfortunately are over-represented here.&lt;br /&gt;&lt;br /&gt;So, for example look at this image taken from Excel:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://4.bp.blogspot.com/_YZ6h0DIe-AY/Rt5sKIOTM4I/AAAAAAAAAAc/GZvG6WHw2VQ/s1600-h/heading_fat.png"&gt;&lt;img id="BLOGGER_PHOTO_ID_5106637948746675074" style="CURSOR: hand" alt="" src="http://4.bp.blogspot.com/_YZ6h0DIe-AY/Rt5sKIOTM4I/AAAAAAAAAAc/GZvG6WHw2VQ/s320/heading_fat.png" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Looking at this user interface, it seems as if the designer believes the table headings are more important than the data contained. The designer really should ask himself the question - why is the user looking at this information - isn't for the data in the table?&lt;br /&gt;&lt;br /&gt;I see table headings simply as meta data - a tool for the user to quickly find the information &lt;em&gt;he's really looking for&lt;/em&gt;. However, in the above example, my eyes inadvertantly stray to the bold headings - the design tells my eyes that the important stuff is the headings, not the data.&lt;br /&gt;&lt;br /&gt;With some minor modifications to the above image, the table could look like this instead:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://4.bp.blogspot.com/_YZ6h0DIe-AY/Rt5sKIOTM5I/AAAAAAAAAAk/q8ziHZTG2hw/s1600-h/heading_small.png"&gt;&lt;img id="BLOGGER_PHOTO_ID_5106637948746675090" style="CURSOR: hand" alt="" src="http://4.bp.blogspot.com/_YZ6h0DIe-AY/Rt5sKIOTM5I/AAAAAAAAAAk/q8ziHZTG2hw/s320/heading_small.png" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Now, the data style is unchanged. The headings however, have a smaller font and a weaker color but are still bold. I'm not saying this is good-looking or anything, but now the data gets my focus much easier. &lt;em&gt;Hmm... Maybe the headings should be even less pronounced.&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;Working with developers on a daily basis I see this issue all the time, as soon as the typical developer has to create a user interface without a guiding design. You can do better!&lt;br /&gt;&lt;br /&gt;Do you agree with me, or am I wrong? Please let me know either way. :-)&lt;br /&gt;&lt;br /&gt;Best regards,&lt;br /&gt;Daniel&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3706294656317442171-6016951602457414458?l=www.terborn.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.terborn.com/feeds/6016951602457414458/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3706294656317442171&amp;postID=6016951602457414458' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3706294656317442171/posts/default/6016951602457414458'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3706294656317442171/posts/default/6016951602457414458'/><link rel='alternate' type='text/html' href='http://www.terborn.com/2007/09/graphical-design-of-table-headers.html' title='Graphical design of table headers'/><author><name>Terborn</name><uri>http://www.blogger.com/profile/08699582580311827918</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='21' src='http://2.bp.blogspot.com/_YZ6h0DIe-AY/SJ8hnRT_OsI/AAAAAAAAAR0/i0s6-3N1BUA/s1600-R/IMG_1119_lzn-2.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_YZ6h0DIe-AY/Rt5sKIOTM4I/AAAAAAAAAAc/GZvG6WHw2VQ/s72-c/heading_fat.png' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3706294656317442171.post-7863197734211419010</id><published>2007-09-05T09:09:00.000+02:00</published><updated>2007-10-29T14:10:05.465+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='moss 2007'/><category scheme='http://www.blogger.com/atom/ns#' term='SharePoint'/><category scheme='http://www.blogger.com/atom/ns#' term='chrome'/><title type='text'>Custom chrome in MOSS 2007</title><content type='html'>I just love developing web parts in MOSS. &lt;em&gt;Well, as long as they are Ajax-enabled anyways.&lt;/em&gt; There is one thing that bugs me quite a lot though – the inability to easily change that horribly ugly border and title (called chrome) that is default in MOSS. You can change some styles, but quite frankly, that’s not enough if you want to do something really nice-looking.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://3.bp.blogspot.com/_YZ6h0DIe-AY/Rt5c74OTM2I/AAAAAAAAAAM/DvFIZk2fhWg/s1600-h/moss_standard_chrome.png"&gt;&lt;img id="BLOGGER_PHOTO_ID_5106621211259122530" style="CURSOR: hand" alt="" src="http://3.bp.blogspot.com/_YZ6h0DIe-AY/Rt5c74OTM2I/AAAAAAAAAAM/DvFIZk2fhWg/s320/moss_standard_chrome.png" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;em&gt;The typical MOSS chrome&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/_YZ6h0DIe-AY/Rt5dUYOTM3I/AAAAAAAAAAU/cOZ2amm4Amo/s1600-h/moss_custom_chrome.png"&gt;&lt;img id="BLOGGER_PHOTO_ID_5106621632165917554" style="CURSOR: hand" alt="" src="http://1.bp.blogspot.com/_YZ6h0DIe-AY/Rt5dUYOTM3I/AAAAAAAAAAU/cOZ2amm4Amo/s320/moss_custom_chrome.png" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;em&gt;A custom "chrome" using this technique&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;Had it been a basic ASP.Net 2.0 environment, you could build your own chrome and your own WebPartZone to use your chrome. However, it isn’t this easy in MOSS. The chrome class in MOSS 2007, &lt;span style="font-family:courier new;"&gt;SPChrome&lt;/span&gt;, is sealed, and thus you cannot inherit it and add your own code. And you do not want to try to re-write everything that you get from MOSS. &lt;em&gt;Well, at least I didn’t want to.&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;So, what did I end up doing?&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Create a base web part class.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;In the base class, set the ChromeType property to “TitleOnly”. This will hide the MOSS chrome. &lt;em&gt;You could leave it to page configuration as well if you wish of course.&lt;/em&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Implement my own “chrome” in the base web part and make a “canvas” panel available for inherited web parts to add their own UI components.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;The most challenging part – add the standard web part menu to my custom framework. And yes, this solution does qualify as a hack in my opinion, but it works.&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;&lt;em&gt;Tip: Note that this base web part is also the perfect spot to add standard Ajax functionality.&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;Now, for you that are interested, let me show you some of the code for this base class. It is very simplified for your viewing pleasure. ;-)&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;public class BaseWebPart : Microsoft.SharePoint.WebPartPages.WebPart&lt;br /&gt;{&lt;br /&gt;  // Constants.&lt;br /&gt;  private const string REPLACE_CLIENTNAME = "varPart";&lt;br /&gt;  // Thanks Dave, &lt;a href="http://www.kcdholdings.com/blog/p=32"&gt;http://www.kcdholdings.com/blog/p=32&lt;/a&gt;, for getting me started.&lt;br /&gt;  // Note: I've made a bug fix in this code to allow for customized menues.&lt;br /&gt;  private const string LITERAL_WEBPARTMENU = "&amp;lt;a onclick="'MSOWebPartPage_OpenMenu((window.WebPart{0}_Menu" id="'WebPart{1}_MenuLink'" onkeydown="'MSOMenu_KeyboardClick(WebPart{2}_MenuLink," href="'#'"&gt;&amp;lt;img src="'/Style%20Library/Images/porten_button_menu.png'" border="'0'" width="'11'" height="'11'" title="'{3}" alt="'{4}" /&gt;&amp;lt;/a&gt;";&lt;br /&gt;  // Members.&lt;br /&gt;  private Panel mCanvasPanel;&lt;br /&gt;&lt;br /&gt;  [Personalizable(PersonalizationScope.Shared),&lt;br /&gt;   WebBrowsable(),&lt;br /&gt;   WebDisplayName("Framework visible"),&lt;br /&gt;   WebDescription("Whether the web part framework is displayed or not")]&lt;br /&gt;  public bool FrameworkVisible&lt;br /&gt;  {&lt;br /&gt;    get { return mFrameworkVisible; }&lt;br /&gt;    set { mFrameworkVisible = value; }&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  [Personalizable(PersonalizationScope.Shared),&lt;br /&gt;   WebBrowsable(),&lt;br /&gt;   WebDisplayName("Framework style"),&lt;br /&gt;   WebDescription("Which framework style to use for this web part")]&lt;br /&gt;  public FrameworkStyle FrameworkStyle&lt;br /&gt;  {&lt;br /&gt;    get { return mFrameworkStyle; }&lt;br /&gt;    set { mFrameworkStyle = value; }&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  protected override void CreateChildControls()&lt;br /&gt;  {&lt;br /&gt;    base.CreateChildControls();&lt;br /&gt;    // Create the framework.&lt;br /&gt;    // TODO: ...&lt;br /&gt;    // Create canvas panel.&lt;br /&gt;    mCanvasPanel = new Panel();&lt;br /&gt;    // TODO: Add canvas panel to framework.&lt;br /&gt;    // Add menu element.&lt;br /&gt;    // Note: This is a bit of a hack.&lt;br /&gt;    // As far as I know there's no nice way of doing this.&lt;br /&gt;    // A custom web part chrome would be preferred, but of&lt;br /&gt;    // course this is not possible in the current MOSS&lt;br /&gt;    // version. Perhaps in a later service pack?&lt;br /&gt;    string webPartId = GetWebPartId();&lt;br /&gt;    LiteralControl menu = new LiteralControl(&lt;br /&gt;    string.Format(LITERAL_WEBPARTMENU,&lt;br /&gt;      webPartId,&lt;br /&gt;      webPartId,&lt;br /&gt;      webPartId,&lt;br /&gt;      Title,&lt;br /&gt;      Title)&lt;br /&gt;    );&lt;br /&gt;    // TODO: Add menu control to framework.&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  protected virtual string GetWebPartId()&lt;br /&gt;  {&lt;br /&gt;    return ClientName.Replace(REPLACE_CLIENTNAME, string.Empty);&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;There is one problem with this solution - if there are no standard MOSS chromes on the page (i.e. ChromeType set to "None"), the web part menu functionality will not work as some needed code is not generated. My work-around for this is to set ChromeType to "TitleOnly", and then hide the chrome using CSS, like this:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;/* This is a hack to hide chromes */&lt;br /&gt;.ms-WPHeader&lt;br /&gt;{&lt;br /&gt;  display: none;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;/* This is a hack to SHOW chromes in edit mode despite earlier hack :-) */&lt;br /&gt;.ms-SPZone tr td table tr td table .ms-WPHeader&lt;br /&gt;{&lt;br /&gt;  display: block;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Perhaps you have a better solution for this?&lt;br /&gt;&lt;br /&gt;I’d love your comments on this solution - I’d really like a better solution, so if you know of one, let me know!&lt;br /&gt;&lt;br /&gt;Best regards,&lt;br /&gt;Daniel&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3706294656317442171-7863197734211419010?l=www.terborn.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.terborn.com/feeds/7863197734211419010/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3706294656317442171&amp;postID=7863197734211419010' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3706294656317442171/posts/default/7863197734211419010'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3706294656317442171/posts/default/7863197734211419010'/><link rel='alternate' type='text/html' href='http://www.terborn.com/2007/09/custom-chrome-in-moss-2007.html' title='Custom chrome in MOSS 2007'/><author><name>Terborn</name><uri>http://www.blogger.com/profile/08699582580311827918</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='21' src='http://2.bp.blogspot.com/_YZ6h0DIe-AY/SJ8hnRT_OsI/AAAAAAAAAR0/i0s6-3N1BUA/s1600-R/IMG_1119_lzn-2.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_YZ6h0DIe-AY/Rt5c74OTM2I/AAAAAAAAAAM/DvFIZk2fhWg/s72-c/moss_standard_chrome.png' height='72' width='72'/><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3706294656317442171.post-8848421565703086858</id><published>2007-09-03T08:07:00.000+02:00</published><updated>2007-09-03T08:23:59.072+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='moss 2007'/><category scheme='http://www.blogger.com/atom/ns#' term='development'/><category scheme='http://www.blogger.com/atom/ns#' term='environment'/><title type='text'>A good (and cheap) development environment</title><content type='html'>&lt;p&gt;As a consultant you eventually end up having to meet all kinds of requirements for a development environment. Sometimes it’s easy – either your client wishes to use your firms own development environment (in my case a fairly advanced system with Rational ClearCase/ClearQuest and virtual servers), or the client already has a good development environment running.&lt;/p&gt;&lt;p&gt;However, more often than not, I’ve found that the client either completely lacks a standard development environment or, what’s there is missing out of much of todays available functionality - stuff that you really want in a modern development environment.&lt;/p&gt;&lt;p&gt;This article is for the situations where you as a consultant need to setup a development environment for a small to medium sized development project.&lt;/p&gt;&lt;p&gt;The goal of this environment is to:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;give strong, modern support to the development cycles&lt;/li&gt;&lt;li&gt;cheap&lt;/li&gt;&lt;li&gt;quick to setup&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;The following setup I’ve been using several Microsoft-based projects, the latest a sales support portal built on MOSS 2007.&lt;/p&gt;&lt;p&gt;So, what tools are needed?&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Source code management - Subversion&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;The true basics of a development environment is of course the source code management. Subversion is an open-source environment that truly rocks. It uses optimistic locking instead of the typical pessimistic locking used in Microsoft SourceSafe or Rational ClearCase. Optimistic locking allows two developers to work with the same file at the same time – no more “Hey &lt;insert&gt;, check in that bloody file NOW!” shouts across the office, or worse…&lt;/p&gt;&lt;p&gt;Basically, Subversion will work great (especially with TortoiseSVN), as long as team members commit their changes several times per day, and update their source just as often.&lt;/p&gt;&lt;p&gt;&lt;a href="http://subversion.tigris.org/"&gt;http://subversion.tigris.org/&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Build server - CruiseControl.Net&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;For those of you that have not jumped on the automatic build/continuous integration-train yet, don’t hesitate, do it now. Yes, now, not later. I promise that you won’t regret it for even a moment. CruiseControl.Net is an excellent tool that is quick and relatively easy to setup – and it’s free.&lt;/p&gt;&lt;p&gt;Combine CruiseControl with NAnt, NUnit, NCover, NDoc and FxCop and you have a very powerful automated build system going.&lt;/p&gt;&lt;p&gt;Setup one CC project for CI/Deployment and one for production. Configure production to label source control and brand source with an automated version tag and to build setup files automatically – this way you will be able to track all releases very easily. &lt;em&gt;You can write your own small C# code blocks in NAnt to do some custom branding to your source files.&lt;/em&gt;&lt;/p&gt;&lt;p&gt;In the latest MOSS 2007 project, I also let the CI build automatically deploy the latest source (a solution .wsp file) to the MOSS 2007 development server. This way, the team can easily see the latest source in action. Works great! &lt;em&gt;Well, once in a while a deployment fails due to a probable MOSS 2007 bug, but that’s the only challenge so far.&lt;/em&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://confluence.public.thoughtworks.org/display/CCNET"&gt;http://confluence.public.thoughtworks.org/display/CCNET&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Information sharing - Trac&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;A development environment will also need some way to share information between team members. Trac is free to use and gives the team a Wiki, integration with Subversion, and a simple ticket system. The ticket system works for assigning tasks and managing defects, but I would prefer a somewhat more complex system. However, it works, and since it’s so simple and quick to setup, it’s hard to complain.&lt;/p&gt;&lt;p&gt;&lt;a href="http://trac.edgewall.org/"&gt;http://trac.edgewall.org/&lt;/a&gt;&lt;/p&gt;&lt;p&gt; &lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;Using the above systems you will have a sound system that will work nice for at least team sizes of 8 or so – I have personally not used this setup for larger teams. The weak point for larger teams is probably Trac due to the fairly weak tickets system.&lt;/p&gt;&lt;p&gt;If you have any comments on these systems or wish to know more in terms of details or setup specifics, please contact me!&lt;/p&gt;&lt;p&gt;Best regards,&lt;br /&gt;Daniel&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3706294656317442171-8848421565703086858?l=www.terborn.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.terborn.com/feeds/8848421565703086858/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3706294656317442171&amp;postID=8848421565703086858' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3706294656317442171/posts/default/8848421565703086858'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3706294656317442171/posts/default/8848421565703086858'/><link rel='alternate' type='text/html' href='http://www.terborn.com/2007/09/good-and-cheap-development-environment.html' title='A good (and cheap) development environment'/><author><name>Terborn</name><uri>http://www.blogger.com/profile/08699582580311827918</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='21' src='http://2.bp.blogspot.com/_YZ6h0DIe-AY/SJ8hnRT_OsI/AAAAAAAAAR0/i0s6-3N1BUA/s1600-R/IMG_1119_lzn-2.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3706294656317442171.post-6199105974685342627</id><published>2007-09-02T13:23:00.000+02:00</published><updated>2007-09-02T22:19:37.336+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='personal'/><title type='text'>A new blog is born - just what the world needs</title><content type='html'>&lt;span style="font-family:arial;font-size:85%;"&gt;So, have I succumbed to the need of sharing my opinions, thoughts and knowledge with the rest of the world? Well, yes, I have. I'll just start here by apologizing for all the stupid stuff I'm liable to say on this blog in the future.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:arial;font-size:85%;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:arial;font-size:85%;"&gt;So, what will I talk about then? Since I am a computer geek working on the dark side, I will most likely share a bit from my professional life as a software architect working mainly with Microsoft products - for now with a focus on MOSS 2007.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:arial;font-size:85%;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:arial;font-size:85%;"&gt;However, I am, unfortunately for you, also the kind of person who may share a few tidbits about my personal thoughts and ideas. Just skip all posts marked "personal", all right?&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:arial;font-size:85%;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:arial;font-size:85%;"&gt;Best regards,&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:arial;font-size:85%;"&gt;Daniel&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3706294656317442171-6199105974685342627?l=www.terborn.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.terborn.com/feeds/6199105974685342627/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3706294656317442171&amp;postID=6199105974685342627' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3706294656317442171/posts/default/6199105974685342627'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3706294656317442171/posts/default/6199105974685342627'/><link rel='alternate' type='text/html' href='http://www.terborn.com/2007/09/new-blog-is-born-just-what-world-needs.html' title='A new blog is born - just what the world needs'/><author><name>Terborn</name><uri>http://www.blogger.com/profile/08699582580311827918</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='21' src='http://2.bp.blogspot.com/_YZ6h0DIe-AY/SJ8hnRT_OsI/AAAAAAAAAR0/i0s6-3N1BUA/s1600-R/IMG_1119_lzn-2.jpg'/></author><thr:total>2</thr:total></entry></feed>
