Showing posts with label Windows Workflow Foundation. Show all posts
Showing posts with label Windows Workflow Foundation. Show all posts

Thursday, June 11, 2009

F# and WCF

I recently had to implement some self hosted workflows on WF that leverages WCF for inter-process communication.  I’ve found the book Learning WCF by Michele Bustamante helpful for learning and implementing WCF parts of the code and Pro WF by Bruce Bukovics useful for implementing the workflows.  I became curious on how  to implement WCF in F#.  I suspect that WCF services in F# is probably one more likely scenarios for me to introduce F# usage in the corporate environment.  

For the following sample code, I took the last example with DataGrid and stripped out the portion that retrieves a list of Person from the database and implemented it as a WCF hosted on a separate executable.  There are many other blogs on F# and WCF including those by Ray Vernagus, Nick Holmes and Ted Neward.  This blogs were immensely helpful in aiding me to build my own example.

The blog entry by Ray Vernagus seemed to indicate that I needed to define my data contract for Person record with DataContract attribute.  It did not seem like that is necessary in this simple scenario.  However, when I ran my example client code, I did get the following error:

stdin(0,1): error FS0082: Could not resolve this reference. Could not locate the assembly "PersonService.XmlSerializers.dll". Check to make sure the assembly exists on disk. If this reference is required by your code, you may get compilation errors. (Code=MSB3245)
stopped due to error

The client code still works and subsequent runs does not generate this error.  I was unable to track down what caused this error message and what impact it has on the application.  Even after I added the DataContract attributes to Person type, I still get the same error message.  However, I did not see any impact to the client application due to this error.  I got this error with version 1.9.6.2 of the F# compiler.  My next step would be to try this out with VS2010 beta version of F# compiler.

Here’s the WCF server code that serves up a list of Person:


#light

namespace WCF.Test

open System
open System.Data.Common
open System.Data.Sql
open System.Data.SqlClient
open System.ServiceModel
open System.Runtime.Serialization

type Person =
{FirstName:string;
LastName:string;
Email:string;
PhoneNumber:string}

module DB =
let connString = @"Data Source=.\SQLEXPRESS;Initial Catalog=AdventureWorks;Integrated Security=True;"
let conn = new SqlConnection(connString)
let query () =
seq { use conn = new SqlConnection(connString)
do conn.Open()
use comm = new SqlCommand("SELECT top 50 * FROM Person.Contact",conn)
use reader = comm.ExecuteReader()
while reader.Read() do
yield ({FirstName = reader.GetString 3;
LastName = reader.GetString 5;
Email = reader.GetString 7;
PhoneNumber = reader.GetString 9}) }

[<ServiceContract()>]
type IPersonService = interface
[<OperationContract()>]
abstract GetPersons: unit -> Person array
end

[<ServiceBehavior(Name="PersonService",InstanceContextMode=InstanceContextMode.Single)>]
type PersonService() =
interface IPersonService with
member v.GetPersons () =
Console.WriteLine("Retrieving people list...")
DB.query() |> Seq.to_array


do
Console.WriteLine("PersonService")
let serviceType = typeof<PersonService>
let address = new Uri("http://localhost:28888/PersonService")
let host = new ServiceHost(serviceType,[|address|])
host.Open()
Console.WriteLine("Press <ENTER> to terminate the host application")
Console.ReadLine() |> ignore
host.Close()

Here’s the configuration file for the WCF service:


<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<!-- here is the base address of our service -->
<appSettings>
<add key ="baseAddress" value="http://localhost:28888/PersonService"/>
</appSettings>
<system.serviceModel>
<services>
<service name="WCF.Test.PersonService" behaviorConfiguration="PersonServiceBehaviors">
<endpoint address="http://localhost:28888/PersonService"
binding="basicHttpBinding"
contract="WCF.Test.IPersonService"/>
<endpoint contract="IMetadataExchange" binding="mexHttpBinding" address="mex" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="PersonServiceBehaviors" >
<serviceMetadata httpGetEnabled="true" />
<serviceDebug httpHelpPageEnabled="true"
includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>

Here’s the client code:


#light
#I @"C:\Program Files\Reference Assemblies\Microsoft\Framework\v3.0"
#I @"C:\WINNT\Microsoft.NET\Framework\v2.0.50727"
#r @"WindowsBase.dll"
#r @"PresentationCore.dll"
#r @"PresentationFramework.dll"
#r @"C:\Program Files\WPF Toolkit\v3.5.40320.1\WPFToolkit.dll"
#r @"c:\dev\webservice\PersonService.dll" // Generated with wsdl tool

open Microsoft.Windows.Controls
open System
open System.Windows
open System.Windows.Controls

let service = new PersonService()
let persons = service.GetPersons()

let win = new Window(Title="Test DataGrid w/WCF")

let datagrid = DataGrid()
datagrid.HeadersVisibility <- DataGridHeadersVisibility.Column
datagrid.ItemsSource <- persons


win.Content <- new ScrollViewer(Content=datagrid)
win.Show()



Tuesday, September 09, 2008

Exploring SharePoint 2007 Object Model with F#

I have been busy with other things that detracted from continued efforts in working with F# and WPF. While I've been busy, I found out that F# 1.9.6 has been released. After quick perusal of F# 1.9.6 release notes, I realized my previously posted codes will break during compilation. Two immediate items that I noticed are:

  • IEnumerable.* are deleted
  • base is now a keyword

I haven't had time to scour my previously posted F# code and correct it to work with F# 1.9.6 so be forewarned if you're trying to compile my previously posted F# code with the new F# compiler. Hopefully, sometime in the future I'll be able to correct the posted code so it compiles and runs with the new F# compiler.

Lately, I have been exploring other pieces of Microsoft technologies such SharePoint 2007, InfoPath 2007, Windows Workflow Foundation, and Excel Services with the goal of crafting a strategy on how to best leverage these technologies in a corporate environment. I needed a way to get up to speed quickly in the SharePoint environment and wanted a way to interactively explore the Windows SharePoint Services (WSS) object model.

I immediately thought of using F# interactive as way to explore WSS object model. I fired up the new F# 1.9.6 interactive shell and wanted to follow the example codes in the book Inside Microsoft Windows SharePoint Services 3.0 by Ted Pattison and Daniel Larson.

Before I could try out the examples in the aforementioned book, I had to created a MOSS 2007 system in a Virtual PC environment based on the instructions by Tony Zink in his post How to Create a MOSS 2007 VPC Image: The Whole 9 Yards .

One problem that I ran into while trying out the examples from the book is that I'm unable to iterate through SPListCollection. SPListCollection does not implement IEnumerable and I do not know an equivalent foreach capability in F#. As a workaround, I implemented the SPListCollectionAdapter as described by Asfar Sadewa in his blog entry linq-ing splistcollection. After implementing this adapter, I can now iterate through SPListCollection as shown in the following example:


Exploring WSS Object Model with F#

#light
#I @"C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\ISAPI"
#r @"Microsoft.SharePoint.dll"
#r @"c:\dev\F#\SharePoint\SharePointUtility.dll"

open Microsoft.SharePoint
open SharePoint.Utility

let path="http://localhost/"
let collection = new SPSite(path)
let site = collection.RootWeb
let lists = SPListCollectionAdapter(site.Lists)
Seq.iter (fun (x:SPList) -> printf "%s\n" x.Title) lists

I was highly encouraged by this initial success. I next tried to implement a simple hello world SharePoint feature as shown in the following code:


Building Test Hello World Sharepoint Feature

#light
namespace HelloWorld

open System
open Microsoft.SharePoint

// From Chapter 1 of Inside Microsoft Windows SharePoint Services 3.0 by Ted Pattison & Daniel Larson
type FeatureReceiver() =
class
inherit SPFeatureReceiver()


override this.FeatureInstalled _ = ()
override this.FeatureUninstalling _ = ()

override this.FeatureActivated (properties:SPFeatureReceiverProperties) =
let site = properties.Feature.Parent :?> SPWeb
site.Properties.["OriginalTitle"] <- site.Title
site.Properties.Update()
site.Title <- "Hello World"
site.Update()

override this.FeatureDeactivating (properties:SPFeatureReceiverProperties) =
let site = properties.Feature.Parent :?> SPWeb
site.Title <- site.Properties.["OriginalTitle"]
site.Update()
end

I was delighted that this worked flawlessly in SharePoint 2007. It looks like I can go back to using some F# in exploring SharePoint 2007.