Sunday, September 14, 2008

Building a Simple Hello World SharePoint Web Parts with F#

I'm working through the examples in the book Inside Microsoft Windows SharePoint Services 3.0 by Ted Pattison and Daniel Larson and wanted to build a simple hello world web part in F# before attempting the more complicated RssViewWebPart as explained in the book. I start by generating the configuration files DemoWebParts.webpart, feature.xml, and elements.xml.


DemoWebParts.webpart file

<webParts>
<webPart xmlns="http://schemas.microsoft.com/WebPart/v3">
<metaData>
<type name="DemoWebParts.HelloWorldWebPart" />
<importErrorMessage>Cannot import this Web Part.</importErrorMessage>
</metaData>
<data>
<properties>
<!-- standard Web Part properties -->
<property name="ChromeType" type="chrometype">Default</property>
<property name="Title" type="string">Demo Hello World Web Part</property>
<property name="Description" type="string">Simple example to demonstrate F# in SharePoint</property>
<property name="CatalogIconImageUrl" type="string">
/_layouts/images/msxmll.gif
</property>
<property name="AllowConnect" type="bool">True</property>
<property name="ExportMode" type="exportmode">All</property>

<!-- custom Web Part properties -->
<property name="XmlUrl" type="string">
http://blogs.msdn.com/MainFeed.aspx?Type=AllBlogs
</property>
</properties>
</data>
</webPart>
</webParts>

feature.xml file

<Feature
Id="973F298A-96D3-4d7c-B07A-56925FA13CFF"
Title="Demo Webpart using F#"
Description="Demo webpart using F# based on Chapter 4 of Inside Windows SharePoint Services (Pattison/Larson)"
Hidden="FALSE"
Scope="Site"
ImageUrl="actionssettings.gif"
xmlns="http://schemas.microsoft.com/sharepoint/">
<ElementManifests>
<ElementManifest Location="elements.xml"/>
</ElementManifests>
</Feature>

elements.xml file

<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
<Module Name="DemoWebParts" Path="dwp"
List="113" Url="_catalogs/wp" RootWebOnly="true">

<File Url="HelloWebPart.webpart" Type="GhostableInLibrary" >
<Property Name="Group" Value="F# Demo Web Parts"
</File
</Module>
</Elements>

The F# source file DemoWebParts.fs contains just a single class HelloWorldWebPart that inherits from WebPart.


DemoWebParts.fs


#light

namespace DemoWebParts

open System.Web.UI
open System.Web.UI.WebControls.WebParts

type HelloWorldWebPart() =
class
inherit WebPart()

override this.CreateChildControls () =
base.CreateChildControls()
new LiteralControl("Hello, world!") |> this.Controls.Add

end

[<Assembly: System.Reflection.AssemblyVersion("1.0.0.0")>]
[<Assembly: System.Security.AllowPartiallyTrustedCallersAttribute>]
do()

I need to strong name the created assembly. The following are the command line parameters I used to generate the dll file.

sn.exe -k DemoWebParts.snk

fsc -a --keyfile DemoWebParts.snk -I "C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\ISAPI" -r "Microsoft.SharePoint.dll" DemoWebPart.fs

I then copy all the files to the bin folder of the SharePoint website.

I then need to configure the web.config of the SharePoint site to add a new entry to the SafeControls node in the web.config in order to register the assembly and namespace as safe.


<SafeControl Assembly="DemoWebParts, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b89a761d055b9ae3" Namespace="DemoWebParts" TypeName="*" Safe="True" />

The assembly value can be easily pulled by using Lutz Roeder's .NET Reflector tool, which apparently has been acquired by Redgate.

After you copied the dll file along with the configuration files, you then want to navigate to the New Web Part Gallery page which is located at http:///_layouts/NewDwp.aspx.

Select the new web part and click on Populate Gallery Button.

Voila...a F# webpart working in SharePoint!

3 comments:

DkmS said...
This comment has been removed by the author.
DkmS said...

Microsoft F# Compiler, (c) Microsoft Corporation, All Rights Reserved
F# Version 1.9.6.2, compiling for .NET Framework Version v2.0.50727

DemoWebParts.fs(14,3): error FS0010: Unexpected keyword 'do' in definition

John Liao said...

Seems to work for me. I do get a warning though. Here's my compiler output:

Microsoft F# Compiler, (c) Microsoft Corporation, All Rights Reserved
F# Version 1.9.6.2, compiling for .NET Framework Version v2.0.50727

DemoWebParts.fs(1,1): warning FS0191: Main module of program is empty: nothing will happen when it is run.