Tuesday, July 7, 2009
Google Wave
If you have not heard of or seen the Google Wave demo yet, drop everything and go here:
http://wave.google.com/
You won't regret it.
Azure Services Platform
I almost wish it wasn't summer and nice weather...
And of course I am particularily interested in the Microsoft SharePoint Services part.
Not checked it out yet? Please go here: http://www.microsoft.com/azure/
Monday, June 1, 2009
Re-use when executing elevated code
Challenge
However, when using SPSecurity.RunWithElevatedPrivileges 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 open a site (sometimes at least), open a web, and set AllowUnsafeUpdates on both site and web. And you still need to ensure that disposing works correctly.
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 SPContext.Current.Web).
Solution
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.
A delegate
public delegate void WebCodeDelegate(SPWeb elevatedWeb);
The reusable code block
public static void ExecuteElevatedCode(Guid siteId, Guid webId, WebCodeDelegate webCode)Calling the reusable code
{
SPSecurity.RunWithElevatedPrivileges(delegate()
{
// Use "using" to automatically release site resources.
using (SPSite site = new SPSite(siteId))
{
site.AllowUnsafeUpdates = true;
// Open a web. Be sure to release resources!
SPWeb elevatedWeb = site.OpenWeb(webId);
try
{
elevatedWeb.AllowUnsafeUpdates = true;
// Execute delegate.
webCode(elevatedWeb);
}
finally
{
// Release web resources.
elevatedWeb.Dispose();
}
}
});
}
ExecuteElevatedCode(siteId, process.Id, delegate(SPWeb elevatedWeb)
{
SPList elevatedList = elevatedWeb.Lists[PROCESS_WEB_LIST_NAME];
SPListItem item = elevatedList.Items[0];
item[GUID_STATUS] = "status";
item[GUID_ERROR_DESCRIPTION] = "description";
item.Update();
});
Other examples of overloads
// Executes elevated code on the root web of the current site collection.
public static void ExecuteElevatedCode(WebCodeDelegate webCode)
// Executes elevated code on the root web of the specified site collection.
public static void ExecuteElevatedCode(SPSite site, WebCodeDelegate webCode)
// Executes elevated code on the specified web.
public static void ExecuteElevatedCode(SPWeb web, WebCodeDelegate webCode)
// Executes elevated code on the specified web (using the url as reference to the web).
public static void ExecuteElevatedCode(Guid siteId, string webUrl, WebCodeDelegate webCode)
// Executes elevated code on the specified list.
public static void ExecuteElevatedCode(SPList list, ListCodeDelegate listCode)
// Executes elevated code on the specified item.
public static void ExecuteElevatedCode(SPListItem item, ListItemCodeDelegate listItemCode)
So, that's it. Hope it'll be of help to someone!
Monday, February 2, 2009
Custom PublishingConsole
- It is difficult if not impossible to make it look just the way you'd like.
- The accessibility aspects of the control are bad. It simply does not comply with W3C or WCAG standards.
- 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.

How it's done
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.
Here's how:
In the page layout .aspx file, add the following code:
<%@ Register Tagprefix="PublishingWebControls" Namespace="Microsoft.SharePoint.Publishing.WebControls" Assembly="Microsoft.SharePoint.Publishing, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %><!-- Edit mode support without PublishingConsole --> <PublishingWebControls:PublishingContext id="mPublishingContext" runat="server" />
<PublishingWebControls:EditModePanel runat="server" id="mEditContent" PageDisplayMode="Edit" SuppressTag="true"> <PublishingWebControls:SaveBeforeNavigationControl id="mSaveBeforeNavigation" runat="server" ></PublishingWebControls:SaveBeforeNavigationControl> </PublishingWebControls:EditModePanel>
The above code generates the required standard controls. The "save before navigation" control is of course only required when in edit mode.
Create a web control that somehow gives your users the ability to send commands such as check out, check in, undo check out, publish and so on.
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.
A command includes the following:
- Name/Title/Description information, depending on your needs
- Logic for determining visibility and enabled states, depending on your needs (I used delegates for these purposes myself)
- Client-side javascript
- Logic for performing the action (I used a delegate here as well)
Define code behind methods for the commands. Please see below for examples of code I used for some typical commands. 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 & AOP caching and so. ;-)
Check outA javascript is required here to get the user interface to switch to edit mode. Add the following javascript to your button's "onclick"-event:
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'
The code behind-logic should be similar to this:
public void CheckOut()
{
SPListItem item = SPContext.Current.ListItem;
if (item.File.Level != SPFileLevel.Checkout)
{
PublishingPage page = PublishingPage.GetPublishingPage(item);
page.CheckOut();
}
SPContext.Current.FormContext.SetFormMode(SPControlMode.Edit, true);
}
Undo check out
The code behind-logic should be similar to this:
public void UndoCheckOut()
{
SPListItem item = SPContext.Current.ListItem;
if (item.File.Level == SPFileLevel.Checkout)
{
item.File.UndoCheckOut();
CleanRedirect();
}
}
The CleanRedirect() method is necessary to remove the edit mode from the user interface. Microsoft themselves to something similar (according to the Reflector):
private static void CleanRedirect()
{
HttpContext context = HttpContext.Current;
SPUtility.Redirect(context.Request.Url.AbsoluteUri, SPRedirectFlags.Default, context);
}
Check in
The code behind-logic should be similar to this:
public void CheckIn(SPListItem item)
{
SPListItem item = SPContext.Current.ListItem;
if (item.File.Level == SPFileLevel.Checkout)
{
PublishingPage page = PublishingPage.GetPublishingPage(item);
page.CheckIn(string.Empty);
CleanRedirect();
}
}
Publish
The code behind-logic should be similar to this:
public void Publish(SPListItem item)
{
// Note: You could add an automatic check in here, now it is
// only possible to publish after a manual check in.
if (item.File.Level != SPFileLevel.Checkout)
{
item.File.Publish(string.Empty);
CleanRedirect();
}
}
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. :-)
Wednesday, December 3, 2008
Deploying a file to the "_layouts" folder
In my current project, we've had an issue with deploying to SharePoint's _layouts folder. Using a module in the Elements.xml file only creates a ghosted database copy which won't work for example a custom login page, which is what I wanted to deploy.
Now, at this small conferance in Malmö, Sweden, I met Tobias Zimmergren who said something along the lines of "But why don't you just use the RootFiles-element in your manifest.xml file? I do that all the time.".
So, yea, I felt stupid sure, but... The next day I also had an auto-deployed custom login page to the _layouts-folder. :-)
The code is very easy...
In your xyz.ddf-file you'll put something along the lines of:
.Set DestinationDir="Layouts"
Features\XyzSecurity\Page\XyzLoginPage.aspx
In your manifest.xml you'll write something similar to:
<TemplateFile Location="Layouts\XyzLoginPage.aspx"/>
</TemplateFiles>
Very nice!
Sunday, November 23, 2008
TFS and Scrum
In an earlier post 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!
But first, a sneak peek on the result. This is the normal dashboard view where the developer interact with the Scrum-process:

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! :-)
So, how is this environment created?
This is the products we've used:
- Visual Studio Team Suite 2008
- SQL Server 2005
- MOSS 2007
- Team Foundation Server 2008
- Scrum for Team System
- Visual Studio Team System 2008 Web Access
- Scrum Dashboard
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. :-)
All in all, this environment works like a charm and I'm very pleased.
Drawbacks
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.
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.
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.
Screens

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...)
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.Summary
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!
Adapting Scrum
- Fixed price
- Fairly fixed functionality
- The client prefers a RUP-like delivery
- A virtual team - i.e. team members are distributed across the globe
- The entire team shares responsibility (flat organization)
- Very detailed project status always available
- Challenges detected very quickly
- More freedom = more innovation
- The process is very visual
- There are great tools available to support the process!
The client prefers a RUP-like interface
We divided the project into the four phases: Inception, Elaboration, Construction and Transition.
The Inception phase worked as one would expect for a project that starts with a bid stage.
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.
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.
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.
Fixed price and functionality
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.
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".
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.
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.
Virtual team
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.
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.
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. More on this environment in a later post.
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!
