SyntaxHighlighter

Monday, November 15, 2010

Consuming OData Feed from F#

Sadly, there is no tooling around generating an OData service proxy in F# (that I know of).
In order to work around it I created a new C# class library project and used C# to generate a service proxy to any OData feed. I decided to use Netflix.com and Nerd Dinner.com as examples. Once I had the proxies
in C# I built an ODataServiceProxies.dll and referenced it in a F# script file.


#r @"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.ServiceModel.dll"
#r @"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Data.Services.dll"
#r @"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Data.Services.Client.dll"
#r @"D:\ODev Solutions\ODataServices\ODataServiceProxies\bin\Debug\ODataServiceProxies.dll"


open System
open System
open System.Linq
open System.Reflection
open System.Collections
open System.ServiceModel
open System.ServiceModel.Syndication
open System.Xml
open System.Collections.Generic
open System.Data.Services
open ODataServiceProxies.NerdDinner
open ODataServiceProxies.NetflixCatalog
open System.ServiceModel.Activation
      
let netflix = new NetflixCatalog(new Uri("http://odata.netflix.com/v1/Catalog/"))
(*Showing some movie titles from netflix feed*)
netflix.Titles.AsQueryable()
    |> Seq.iter(fun t -> printfn "%s" t.Name)

(*Showing some nerd dinners from NerdDinner.com feed*)
let nerddinner = new NerdDinnerEntities(new Uri("http://www.nerddinner.com/Services/OData.svc/"))
nerddinner.Dinners.AsQueryable()
    |> Seq.iter(fun d -> printfn "%s" d.Description)

Very Cool!! I love F#!

More F# Findings

I spend quite a bit of time reading other F# related content mainly from experts of the field.
It's definitely a great way to learn, but sometimes I get really annoyed when people put out some really great F# code only to visualize it with a sad presentation framework like Windows Forms. People... it's 2010 soon to be 2011! We need to start educating everyone on better presentation. I've decided to side track the MATLAB series and just start posting some random findings of mine through playing around in scripts with WPF and Silverlight. The hope is that someone will see something and get something out of it. If not, then at least I can contribute to more F# with WPF and Silverlight content out in the inner webs.

This first discovery is Silverlight related. I'm working on a side project and came across a need to draw a path. So I turned to the following article and decided to re-think and re-do it in F#.

Special thanks to Tomas Petricek for the Utils module logic to lookup Xaml elements in F#.

( Utils.fs )

module Utils
open System.Windows.Controls

let (?) (this : Control) (prop : string) : 'T =
  this.FindName(prop) :?> 'T


( Main.fs )
namespace DrawingAPath

open Utils
open System
open System.Windows
open System.Windows.Controls
open System.Windows.Ink
open System.Windows.Input
open System.Windows.Media



type MainView() as this = 
    inherit UserControl()
    let uri = new System.Uri("/DrawingAPath;component/MainView.xaml", UriKind.Relative)
    do Application.LoadComponent(this, uri)

    let mutable s = new Stroke()
    let inkP: InkPresenter = this?inkP
    let pv: ListBox = this?PointsViewer

    let AddPoints (pX: float, pY: float, device: StylusDevice) = 
            s.StylusPoints.Add(device.GetStylusPoints(this?inkP))
    
    let DefineInkStroke (ev: MouseButtonEventArgs) = 
        inkP.CaptureMouse() |> ignore
        s = new Stroke() |> ignore
        s.StylusPoints.Add(ev.StylusDevice.GetStylusPoints(inkP))
        s.DrawingAttributes.Color = Colors.White |> ignore
        inkP.Strokes.Add(s)


    let DisplayPointsForPath (ev: MouseButtonEventArgs) =
        let points =
            s.StylusPoints
                |> Seq.map(fun sp -> String.Format("X: {0} Y:{0}",sp.X,sp.Y))
        pv.ItemsSource <- points
        s <- null


    do 
      inkP.MouseLeftButtonDown.Add(fun ev -> DefineInkStroke ev)
    do
      inkP.MouseLeftButtonUp.Add(fun ev -> DisplayPointsForPath ev )            
    do 
      inkP.MouseMove
          |> Event.map(fun me -> 
                let pos = me.GetPosition(this?LayoutRoot)
                pos.X, pos.Y, me.StylusDevice)

          |> Event.filter( fun (pX , pY, sd) -> 
                                pX > 0.0 && pX < 300.0 && pY > 0.0 && pY < 195.0)
          |> Event.add(AddPoints)