For all the power and flexibility that WCF provides, creating a basic web service in C# is easy enough. Essentially, it's just a POCO adorned with some special attributes. Doing the same thing in F#, then, should also be easy enough. I tried this:
#light
#I @"C:\Program Files\Reference Assemblies\Microsoft\Framework\v3.0\"
#r "System.ServiceModel.dll"
open System.ServiceModel
[<ServiceContract(ConfigurationName = "TestWebService", Namespace = "http://coyote-software.com/FSWCFTest")>]
[<ServiceBehavior(InstanceContextMode=InstanceContextMode.PerCall)>]
type public TestWebService =
class
[<OperationContract>]
member public x.TestMethod(s) = "Hello " + s;
end
Essentially, I've referenced the WCF assembly, and created a class with a single method, and added the needed ServiceContract, ServiceBehavior and OperationContract attributes. I compiled this into to a dll.
To test this, I needed to host it somewhere. I already have a console host application in C#, and so I used that for testing, and got this exception:
The service type provided could not be loaded as a service because it does not have a default (parameter-less) constructor.
Constructors in F# are a little different to C#, and a bit of hunting through the spec, and I had my solution:
type public TestWebService() =
Just a pair of missing parenthesis! This was going extremely well, so the next task is to call the method. For this we need to generate a client proxy with svcutil.exe. This generates C# code, but no reason not to use this, driven from an F# client. I compiled up the generated C# into a dll, and then referenced that from a simple F# console client:
#light
#I @"C:\Program Files\Reference Assemblies\Microsoft\Framework\v3.0\"
#I @"c:\Development Projects\Research\FSWCF\Client\bin\debug\"
#r "System.ServiceModel.dll"
#r "client.dll"open System
do
let service = new TestWebServiceClient()
let retVal = service.TestMethod "Nick"
printfn "%s" retVal
Console.ReadLine() |> ignore
This resulted in "Hello Nick" on the console. It was extremely simple to get this (albeit trivial) web service running.
What I've not done yet is pass a more complex data contract, but that will come with in the next step, using LINQ-to-Sql to grab some data, and pass that back to the client.