September 2007 - Posts

What a coincidence: this week I'm in Aarhus, Denmark for a SharePoint 2007 Development Training, and I've stumbled upon a very nice SharePoint tool, created by a Danish guy: Carsten Keutmann. The tool is named WSPBuilder and can be downloaded from the CodePlex site. Basically this tool can build a SharePoint solution file (WSP) in minutes. You just have to copy the contents for the WSP to a corresponding structure (e.g. 12\template\layouts, 12\template\features\yourfeature), run the tool and you've got yourself a splendid SharePoint solution!

Description from CodePlex:
No more manually creating the manifest.xml file.
No more manually specifying the DDF file.
No more using the makecab.exe application.

The WSPbuilder is a console application that creates SharePoint Solutions files based on a folder structure. WSPBuilder will automatically traverse a "12" folder structure and creates a SharePoint solution manifest.xml and the wsp file based on the files it finds. Therefore you do not need the knowledge of how to create a solution manifest.xml and wsp file any more. The folder structure that WSPBuilder uses to build the wsp file is actually the same folder stucture you will find in: "%Program Files%\Common Files\Microsoft Shared\web server extensions\12". So all that you have to do, is the create a \12 folder in your project and add your files to that folder matching the same structure as if you where to put them directly into the "%Program Files%\Common Files\Microsoft Shared\web server extensions\12" folder manually.

Thanks Carsten, if you happen to be in Aarhus this week, I'll buy you a beer! ;-)

UPDATE: Also read my follow-up post: http://weblogs.asp.net/jan/archive/2008/04/16/adding-breadcrumb-navigation-to-sharepoint-application-pages-the-easy-way.aspx

Application Pages in SharePoint 2007 are a great way to extend SharePoint’s default user interface for your custom SharePoint solutions. An application page is deployed once per Web server and it’s not possible to customize these pages per site (like the normal Site Pages). A good example of an Application Page is the default Site Settings page: every site has one, and it’s not customizable on a per site basis (although the contents can be different for sites). A very basic application page could look like:

<%@ Page MasterPageFile="~/_layouts/application.master"
    Inherits="Microsoft.SharePoint.WebControls.LayoutsPageBase"   
    Language="C#"%>
<asp:Content
    contentplaceholderid="PlaceHolderPageTitle" runat="server">
Jan's Page
</asp:Content>

<asp:Content
    contentplaceholderid="PlaceHolderPageTitleInTitleArea"
    runat="server">
Jan's Page   
</asp:Content>

<asp:Content
    contentplaceholderid="PlaceHolderMain"
    runat="server">
Jan's fantastic Application Page content goes here!
</asp:Content>

When this ASPX page is saved in the C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\LAYOUTS folder, it can be accessed from any site by making use of the following URL: http://siteurl/optionalsubsite/_layouts/pagename.aspx.

 

(More information about creating your own Application Pages can be found in Ted Pattison's excellent Visual How-To) As you can see, this page resembles the Site Settings page (or any other default Application Page) quite well. But there is one important thing missing: the breadcrumbs above the page title! Check for example the default Site Settings page:

You can’t fix this by adding a breadcrumb control (aka SiteMapPath control) to the Application Page, actually there is already a breadcrumb on the page (defined in the default master page), the issue is that the new Application page is simply not known by the navigation infrastructure. Luckily this is quite easy to solve: SharePoint uses the ASP.NET 2.0 navigation functionality, so you just have to update the site’s sitemap. This is an XML file containing the navigation hierarchy and is located in C:\Inetpub\wwwroot\wss\VirtualDirectories\wss.u2ucourse.com\_app_bin\layouts.sitemap. If you want that your Application Page behaves as a sub page of the Site Settings page (a common scenario for Application Pages), look for the siteMapNode of the settings page:

<siteMapNode title="$Resources:wss,settings_pagetitle" url="/_layouts/settings.aspx">

And add your own siteMapNode as a child element:

<siteMapNode title="Jan's Page" url="/_layouts/jan.aspx"/>

Et voila, the custom Application Page’s breadcrumb control will automatically display the correct breadcrumb links. Of course modifying the layouts.sitemap file manually is not very nice since a SharePoint environment could have more than one web application (potentially on different servers), so you’d have to edit a couple of files. But of course you can automate this as well, I’ll go into the details in a follow-up post.

UPDATE: Also read my follow-up post: http://weblogs.asp.net/jan/archive/2008/04/16/adding-breadcrumb-navigation-to-sharepoint-application-pages-the-easy-way.aspx 

[Thanks Yves for the tip!] Last summer I delivered two presentations on the Dutch Developer Days in Amsterdam. You can see both sessions from the MSDN's Showtime site:

Be aware that both sessions are in Dutch. I haven't watched the recording yet completly, it's really awkward to see yourself speaking in public... Anyway the recordings are very professional (multiple camera's),just like the rest of the event, so kudos to the Dutch guys for organizing this event!

Question: what is the easiest way to add a column to a list or document library in SharePoint 2007?
Answer: navigate to the list, from the Settings menu, choose Create Column.

Question: how do you add an existing Site Column to a list or document library?
Answer: navigate to the list, from the Settings menu, choose List/Document Library Settings, scroll down to the Columns section and click Add from existing site columns.

In the beta versions of SharePoint 2007 there was an easier way to add an existing Site Column to a list or document library because there was another menu item in the Settings menu: Add column from existing site columns. For those of you who are nostalgic about the beta's of Office 12, and want to have the menu item back: I've created simple feature to add the menu item:

<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="
http://schemas.microsoft.com/sharepoint/">
    <CustomAction
        Id="{F32CD702-0391-4b55-A8D6-7653650DEF95}"
        Location="Microsoft.SharePoint.StandardMenu"
        GroupId="SettingsMenu"
        RegistrationType="List"
        Sequence="0"
        ImageUrl="_layouts/images/menuaddcolumn.gif"
        Title="Add column from existing site columns"
        Description="Add an existing site column to store additional information about each item."
        Rights="ManageLists"
        >
        <UrlAction
            Url="javascript:window.location= '{SiteUrl}/_layouts/AddFieldFromTemplate.aspx?List={ListId}&amp;Source=' + window.location"/>
    </CustomAction>
</Elements>

The feature uses the Javascript tric which I explained yesterday (this feature was actually the reason for it). If you want to download the complete feature, packaged in a nice SharePoint Solution (WSP); just click here!

Here's a screenshot of the result:

The nice guys over at WROX have published an excerpt of my web part chapter from the Real World SharePoint 2007 book. It's only a small piece of the complete chapter, discussing the basic web part development stuff.

Web Parts are the building blocks of pages in SharePoint sites. Users of SharePoint sites can make use of those building blocks to determine what should be displayed on a specific page in a particular SharePoint site.

When you install SharePoint, you can make use of some out-of-the-box Web Parts straight away. Depending on whether you have Windows SharePoint Services (WSS) or Microsoft Office SharePoint Server (MOSS) as your SharePoint installation, you'll have more or less. Additionally, every SharePoint list and document library will have a Web Part counterpart that can display the contents of the corresponding list or document library.

Of course, the out-of-the-box Web Parts are not the only ones that you can use! Developers can build their own Web Parts as well and deploy them to the SharePoint server. End users won't notice the difference between the custom Web Parts and the out-of-the-box Web Parts, so Web Parts are a great way to extend SharePoint.

This article takes you through the basic steps to create your own Web Parts in various ways.
(read full excerpt here)

You can read an excerpt of Andrew's WCM chapter overe here.

With the introduction of the feature framework in SharePoint 2007, developers have some great opportunities to customize and enhance nearly everything in SharePoint. One of the things that's quite easy to do with the help of a feature, is to add and/or replace functionality in the web user interface of SharePoint site. This was typically very hard to do (in a nice way) for the previous version of SharePoint (remember having to edit a javascript file to add a menu item in the ECB?).

Let's take the following example of a feature's manifest file:

<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
    <CustomAction
        Id="{6FCB0F81-2105-4d9f-96BF-C48A19B8E439}"
        Title="My Link"
        Location="Microsoft.SharePoint.StandardMenu"
        GroupId="SettingsMenu">
        <UrlAction Url="_layouts/mypage.aspx"/>
    </CustomAction>
</Elements>

When activated, the feature will add a menu item to the Settings menu of any SharePoint list or document library. The menu item will have the title My Link, when clicked the user will navigate to the page mypage.aspx in the _layouts folder (the typical place to deploy your custom application pages).

If you build some functionality in the mypage.aspx, in many scenarios this page will need to know from which list the link originated. This can be done by using URL tokens in the UrlAction element:

<UrlAction Url="_layouts/mypage.aspx?listid={ListId}"/>

The {ListId} URL token will be automatically replaced with the ID of the list, in which the menu item is shown. In the mypage.aspx, you can retrieve the value of the listid parameter by making use of the QueryString. Once you've got the ID, the object model can be used to get a reference to the SPList instance of that list. According to the documentation on MSDN, the following URL tokens can be used:

  • ~site - Web site (SPWeb) relative link.
  • ~sitecollection - site collection (SPSite) relative link.
  • In addition, you can use the following tokens within a URL:
    • {ItemId} - Integer ID that represents the item within a list.
    • {ItemUrl} - URL of the item being acted upon. Only work for documents in libraries. [Not functional in Beta 2]
    • {ListId} - GUID that represents the list.
    • {SiteUrl} - URL of the Web site (SPWeb).
    • {RecurrenceId} - Recurrence index. This token is not supported for use in the context menus of list items.

Unfortunately there is no token that will give you the URL of the page on which the feature's link is being displayed. In many cases you want to have that URL to be able to redirect, after you've shown your custom functionality, to the originating page. SharePoint itself uses this technique a lot: in many URL's you'll find the Source parameter:

http://wss.u2ucourse.com/Lists/Links/NewForm.aspx?Source=http%3A%2F%2Fwss%2Eu2ucourse%2Ecom%2Fdefault%2Easpx

The URL above points to the NewForm.aspx for the a Links list. Normally when the user fill's out this form and clicks OK, this page redirects to the default view of the list. Because this link has the Source parameter, when the user clicks OK (or cancel), the page will redirect to the default.aspx instead. You can add the Source parameter to a lot of pages in SharePoint, giving you full control over the redirecting.

So the issue is: we want to include the URL of the originating page in the UrlAction element of the feature's CustomAction, but all we get are a bunch of ID's and some URL's that are not useful for this scenario. As usual peeking in the machine room of SharePoint itself can give you some good ideas to solve this issue. The SharePoint guys themselves sometimes use Javascript functions in the UrlAction, instead of ordinary hyperlinks. Thus with some clever use of Javascript, it's quite easy to solve the problem:

<UrlAction Url="javascript:window.location= '{SiteUrl}/_layouts/mypage.aspx?List={ListId}&amp;Source=' + window.location"/>

The actual link is a Javascript function that will navigate to a specific URL. This URL is a concatenation of the URL of the page to display (including for example the ID of the list as a parameter in the QueryString), and the Source parameter which is dynamically set the current page's URL. Et voila, the constructed link will point to your page, and the redirect will always point to the page you started from.

Extra: this tric can also be used to overcome a bug in SharePoint that causes a URL token of a CustomAction to be replaced only once. So if you have used the ListID token two times in a UrlAction element, only one of the token's will be replaced with the actual ID of the list. The user "FlatEric" (what's in a name?) explains this in the Community Content of the How to: Add Actions to the User Interface article on MSDN.

I found an ugly way to bypass this flaw:
<UrlAction Url="javascript:function process(){var site='{SiteUrl}';var item={ItemId};window.location.href=site+'/Lists/MyList/NewForm.aspx?ID='+item+'&amp;Source='+site+'/Lists/myOtherList/DispForm.aspx?ID='+item;};process();"/>

Two weeks ago the book Real World SharePoint 2007: Indispensable Experiences From 16 MOSS and WSS MVPs became available, I had the honour to work with a bunch of really smart guys and girls to create this book. There are 16 chapters in this book, all written by a SharePoint MVP based on his/her personal experiences and expertise. My chapter dives into web part development, the basics of web part development are covered as well as advanced scenarios like connectable web parts and the SmartPart.

If you want to read an excerpt: a part of the web content management chapter by Andrew Connell is available at the WROX website.

Wow, it has been a long time since my last post, five months to be precise! So it's about time to get started again... my colleagues have been bugging me a lot lately.

I've you're wondering what I've been doing in the past months: besides working and some holidays, I've been a ghostwriter for the blog of my little daughter (check out the photos of there if you want to see how much a baby can grow in five months).

More Posts