Get Asynchronous HttpResponse through Silverlight (F#)

Posted by jack2010 on Stack Overflow See other posts from Stack Overflow or by jack2010
Published on 2010-06-08T20:15:35Z Indexed on 2010/06/08 20:42 UTC
Read the original article Hit count: 543

I am a newbie with F# and SL and playing with getting asynchronous HttpResponse through Silverlight. The following is the F# code pieces, which is tested on VS2010 and Window7 and works well, but the improvement is necessary. Any advices and discussion, especially the callback part, are welcome and great thanks.

module JSONExample
open System
open System.IO 
open System.Net 
open System.Text 
open System.Web 
open System.Security.Authentication 
open System.Runtime.Serialization 


[<DataContract>] 
type Result<'TResult> = { 
    [<field: DataMember(Name="code") >] 
    Code:string 
    [<field: DataMember(Name="result") >] 
    Result:'TResult array
    [<field: DataMember(Name="message") >] 
    Message:string 
    } 

// The elements in the list
[<DataContract>] 
type ChemicalElement = { 
    [<field: DataMember(Name="name") >] 
    Name:string 
    [<field: DataMember(Name="boiling_point") >] 
    BoilingPoint:string 
    [<field: DataMember(Name="atomic_mass") >] 
    AtomicMass:string 
} 



//http://blogs.msdn.com/b/dsyme/archive/2007/10/11/introducing-f-asynchronous-workflows.aspx
//http://lorgonblog.spaces.live.com/blog/cns!701679AD17B6D310!194.entry
type System.Net.HttpWebRequest with
    member x.GetResponseAsync() =
        Async.FromBeginEnd(x.BeginGetResponse, x.EndGetResponse)


type RequestState () = 
    let mutable request : WebRequest = null
    let mutable response : WebResponse = null
    let mutable responseStream : Stream = null
    member this.Request with get() = request and set v = request <- v
    member this.Response with get() = response and set v = response <- v
    member this.ResponseStream with get() = responseStream and set v = responseStream <- v

let allDone = new System.Threading.ManualResetEvent(false)


let getHttpWebRequest (query:string) = 
    let query = query.Replace("'","\"") 
    let queryUrl = sprintf "http://api.freebase.com/api/service/mqlread?query=%s" "{\"query\":"+query+"}" 

    let request : HttpWebRequest = downcast WebRequest.Create(queryUrl) 
    request.Method <- "GET" 
    request.ContentType <- "application/x-www-form-urlencoded" 
    request


let GetAsynResp (request : HttpWebRequest) (callback: AsyncCallback) = 
    let myRequestState = new RequestState()
    myRequestState.Request <- request
    let asyncResult = request.BeginGetResponse(callback, myRequestState)
    ()


// easy way to get it to run syncrnously w/ the asynch methods
let GetSynResp (request : HttpWebRequest) : HttpWebResponse  =      
    let response = request.GetResponseAsync() |> Async.RunSynchronously  
    downcast response

let RespCallback (finish: Stream -> _) (asynchronousResult : IAsyncResult) =
        try
            let myRequestState : RequestState = downcast asynchronousResult.AsyncState 
            let myWebRequest1 : WebRequest = myRequestState.Request
            myRequestState.Response <- myWebRequest1.EndGetResponse(asynchronousResult)
            let responseStream = myRequestState.Response.GetResponseStream()
            myRequestState.ResponseStream <- responseStream
            finish responseStream
            myRequestState.Response.Close() 
            ()
        with 
        | :? WebException as e
            -> printfn "WebException raised!"
               printfn "\n%s" e.Message
               printfn "\n%s" (e.Status.ToString())
               ()
        | _ as e
            -> printfn "Exception raised!"
               printfn "Source : %s" e.Source
               printfn "Message : %s" e.Message
               ()

let printResults (stream: Stream)= 
    let result = 
        try 
            use reader = new StreamReader(stream) 
            reader.ReadToEnd(); 
        finally 
            ()

    let data = Encoding.Unicode.GetBytes(result); 
    let stream = new MemoryStream() 
    stream.Write(data, 0, data.Length); 
    stream.Position <- 0L 

    let JsonSerializer = Json.DataContractJsonSerializer(typeof<Result<ChemicalElement>>) 
    let result = JsonSerializer.ReadObject(stream) :?> Result<ChemicalElement> 

    if result.Code<>"/api/status/ok" then 
        raise (InvalidOperationException(result.Message)) 
    else 
        result.Result |> Array.iter(fun element->printfn "%A" element) 

let test =
    // Call Query (w/ generics telling it you wand an array of ChemicalElement back, the query string is wackyJSON too –I didn’t build it don’t ask me!
    let request = getHttpWebRequest "[{'type':'/chemistry/chemical_element','name':null,'boiling_point':null,'atomic_mass':null}]"
    //let response = GetSynResp request 
    let response = GetAsynResp request (AsyncCallback (RespCallback printResults))
    () 

ignore(test)
System.Console.ReadLine() |> ignore

© Stack Overflow or respective owner

Related posts about Silverlight

Related posts about JSON