Asynchronous Controller Helper

The snippet declares a helper for creating asynchronous controllers for ASP.NET MVC 3. It declares a new base class for asynchronous actions that exposes a computation builder for writing actions using F# asynchronous workflows.

Copy Source
Copy Link
Tools:

Asynchronous Utilities for ASP.MVC

 1: /// A computation builder that is almost the same as stnadard F# 'async'.
 2: /// The differnece is that it takes an ASP.NET MVC 'AsyncManager' as an
 3: /// argumnet and implements 'Run' opration, so that the workflow is 
 4: /// automatically executed after it is created (using the AsyncManager)
 5: type AsyncActionBuilder(asyncMgr:Async.AsyncManager) = 
 6: 
 7:   (Boilerplate code that exposes 'async' operations)
 8: 
 9:   /// Run the workflow automatically using ASP.NET AsyncManager
10:   member x.Run(workflow) = 
11:     // Specify that there is some pending computation running
12:     asyncMgr.OutstandingOperations.Increment() |> ignore
13:     async { // Run the asynchronous workflow 
14:             let! res = workflow
15:             // Store the result of the workflow, so that it 
16:             // is passed as an argument to 'Completed' method.
17:             asyncMgr.Parameters.["result"] <- res
18:             // Notify the manager that the workflow has completed
19:             asyncMgr.OutstandingOperations.Decrement() |> ignore }
20:     |> Async.Start
21:      
22: 
23: /// An F# specific asynchronous controller that provides 
24: /// member 'AsyncAction' as a simple way of creating 
25: /// asynchronous actions (hiding 'AsyncManager').
26: type FSharpAsyncController() = 
27:   inherit AsyncController()
28:   member x.AsyncAction = 
29:     // Create new asynchronous builder using the current AsyncManager
30:     new AsyncActionBuilder(x.AsyncManager)

Sample Asynchronous Controller

 1: [<HandleError>]
 2: type MainController() =
 3:   inherit FSharpAsyncController()
 4: 
 5:   // Standard synchronous action that just renders view
 6:   member x.Index() = x.View()
 7: 
 8:   // Asynchronous action that uses F# asynchronous workflows
 9:   // to download a web page and then returns the length (in bytes)
10:   member x.LengthAsync(url:string) = x.AsyncAction {
11:     let wc = new WebClient()
12:     let! html = wc.AsyncDownloadString(url)
13:     return html.Length }
14: 
15:   // Called after the completion of workflow created by 'LengthAsync'
16:   // (the result of the workflow is passed as parameter named 'result')
17:   member x.HelloCompleted(result:int) =
18:     // Pass the result to the View
19:     x.ViewData.Model <- result
20:     x.View()
type AsyncActionBuilder =
  class
    new : asyncMgr:'a -> AsyncActionBuilder
    member Bind : v:Async<'k> * f:('k -> Async<'l>) -> Async<'l>
    member Combine : a:Async<unit> * b:Async<'j> -> Async<'j>
    member Delay : f:(unit -> Async<'i>) -> Async<'i>
    member For : s:seq<'g> * f:('g -> Async<unit>) -> Async<unit>
    member Return : v:'h -> Async<'h>
    member ReturnFrom : a:Async<'f> -> Async<'f>
    member Run : workflow:Async<'a> -> unit
    member TryFinally : a:Async<'e> * b:(unit -> unit) -> Async<'e>
    member TryWith : a:Async<'d> * b:(exn -> Async<'d>) -> Async<'d>
    member Using : r:'b * f:('b -> Async<'c>) -> Async<'c> (requires 'b :> IDisposable)
    member While : c:(unit -> bool) * f:Async<unit> -> Async<unit>
    member Zero : unit -> Async<unit>
  end

Full name: Snippet.AsyncActionBuilder

A computation builder that is almost the same as stnadard F# 'async'.
 The differnece is that it takes an ASP.NET MVC 'AsyncManager' as an
 argumnet and implements 'Run' opration, so that the workflow is
 automatically executed after it is created (using the AsyncManager)

val asyncMgr : 'a
Multiple items
type Async<'T>

Full name: Microsoft.FSharp.Control.Async<_>

--------------------

type Async
with
  static member AsBeginEnd : computation:('Arg -> Async<'T>) -> ('Arg * AsyncCallback * obj -> IAsyncResult) * (IAsyncResult -> 'T) * (IAsyncResult -> unit)
  static member AwaitEvent : event:IEvent<'Del,'T> * ?cancelAction:(unit -> unit) -> Async<'T> (requires delegate and 'Del :> Delegate)
  static member AwaitIAsyncResult : iar:IAsyncResult * ?millisecondsTimeout:int -> Async<bool>
  static member AwaitTask : task:Threading.Tasks.Task<'T> -> Async<'T>
  static member AwaitWaitHandle : waitHandle:Threading.WaitHandle * ?millisecondsTimeout:int -> Async<bool>
  static member CancelDefaultToken : unit -> unit
  static member Catch : computation:Async<'T> -> Async<Choice<'T,exn>>
  static member FromBeginEnd : beginAction:(AsyncCallback * obj -> IAsyncResult) * endAction:(IAsyncResult -> 'T) * ?cancelAction:(unit -> unit) -> Async<'T>
  static member FromBeginEnd : arg:'Arg1 * beginAction:('Arg1 * AsyncCallback * obj -> IAsyncResult) * endAction:(IAsyncResult -> 'T) * ?cancelAction:(unit -> unit) -> Async<'T>
  static member FromBeginEnd : arg1:'Arg1 * arg2:'Arg2 * beginAction:('Arg1 * 'Arg2 * AsyncCallback * obj -> IAsyncResult) * endAction:(IAsyncResult -> 'T) * ?cancelAction:(unit -> unit) -> Async<'T>
  static member FromBeginEnd : arg1:'Arg1 * arg2:'Arg2 * arg3:'Arg3 * beginAction:('Arg1 * 'Arg2 * 'Arg3 * AsyncCallback * obj -> IAsyncResult) * endAction:(IAsyncResult -> 'T) * ?cancelAction:(unit -> unit) -> Async<'T>
  static member FromContinuations : callback:(('T -> unit) * (exn -> unit) * (OperationCanceledException -> unit) -> unit) -> Async<'T>
  static member Ignore : computation:Async<'T> -> Async<unit>
  static member OnCancel : interruption:(unit -> unit) -> Async<IDisposable>
  static member Parallel : computations:seq<Async<'T>> -> Async<'T []>
  static member RunSynchronously : computation:Async<'T> * ?timeout:int * ?cancellationToken:Threading.CancellationToken -> 'T
  static member Sleep : millisecondsDueTime:int -> Async<unit>
  static member Start : computation:Async<unit> * ?cancellationToken:Threading.CancellationToken -> unit
  static member StartAsTask : computation:Async<'T> * ?taskCreationOptions:Threading.Tasks.TaskCreationOptions * ?cancellationToken:Threading.CancellationToken -> Threading.Tasks.Task<'T>
  static member StartChild : computation:Async<'T> * ?millisecondsTimeout:int -> Async<Async<'T>>
  static member StartChildAsTask : computation:Async<'T> * ?taskCreationOptions:Threading.Tasks.TaskCreationOptions -> Async<Threading.Tasks.Task<'T>>
  static member StartImmediate : computation:Async<unit> * ?cancellationToken:Threading.CancellationToken -> unit
  static member StartWithContinuations : computation:Async<'T> * continuation:('T -> unit) * exceptionContinuation:(exn -> unit) * cancellationContinuation:(OperationCanceledException -> unit) * ?cancellationToken:Threading.CancellationToken -> unit
  static member SwitchToContext : syncContext:Threading.SynchronizationContext -> Async<unit>
  static member SwitchToNewThread : unit -> Async<unit>
  static member SwitchToThreadPool : unit -> Async<unit>
  static member TryCancelled : computation:Async<'T> * compensation:(OperationCanceledException -> unit) -> Async<'T>
  static member CancellationToken : Async<Threading.CancellationToken>
  static member DefaultCancellationToken : Threading.CancellationToken
end

Full name: Microsoft.FSharp.Control.Async
member x.Bind(v, f) = async.Bind(v, f)
member x.Combine(a, b) = async.Combine(a, b)
member x.Delay(f) = async.Delay(f)
member x.Return(v) = async.Return(v)
member x.For(s, f) = async.For(s, f)
member x.ReturnFrom(a) = async.ReturnFrom(a)
member x.TryFinally(a, b) = async.TryFinally(a, b)
member x.TryWith(a, b) = async.TryWith(a, b)
member x.Using(r, f) = async.Using(r, f)
member x.While(c, f) = async.While(c, f)
member x.Zero() = async.Zero()
val x : AsyncActionBuilder
member AsyncActionBuilder.Run : workflow:Async<'a> -> unit

Full name: Snippet.AsyncActionBuilder.Run

Run the workflow automatically using ASP.NET AsyncManager
val workflow : Async<'a>
val ignore : 'T -> unit

Full name: Microsoft.FSharp.Core.Operators.ignore
val async : AsyncBuilder

Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.async
val res : 'a
static member Async.Start : computation:Async<unit> * ?cancellationToken:Threading.CancellationToken -> unit
type FSharpAsyncController =
  class
    inherit obj
    new : unit -> FSharpAsyncController
    member AsyncAction : ('a -> 'b)
  end

Full name: Snippet.FSharpAsyncController

An F# specific asynchronous controller that provides
 member 'AsyncAction' as a simple way of creating
 asynchronous actions (hiding 'AsyncManager').

member FSharpAsyncController.AsyncAction : ('a -> 'b)

Full name: Snippet.FSharpAsyncController.AsyncAction
type MainController =
  class
    inherit FSharpAsyncController
    new : unit -> MainController
    member HelloCompleted : result:int -> 'a
    member Index : unit -> 'c
    member LengthAsync : url:string -> 'b
  end

Full name: Snippet.MainController

  type: MainController
  inherits: FSharpAsyncController
val x : MainController

  type: MainController
  inherits: FSharpAsyncController
member MainController.Index : unit -> 'c

Full name: Snippet.MainController.Index
member MainController.LengthAsync : url:string -> 'b

Full name: Snippet.MainController.LengthAsync
val url : string

  type: string
  implements: IComparable
  implements: ICloneable
  implements: IConvertible
  implements: IComparable<string>
  implements: seq<char>
  implements: Collections.IEnumerable
  implements: IEquatable<string>
Multiple items
val string : 'T -> string

Full name: Microsoft.FSharp.Core.Operators.string

--------------------

type string = String

Full name: Microsoft.FSharp.Core.string

  type: string
  implements: IComparable
  implements: ICloneable
  implements: IConvertible
  implements: IComparable<string>
  implements: seq<char>
  implements: Collections.IEnumerable
  implements: IEquatable<string>
property FSharpAsyncController.AsyncAction: 'a -> 'b
type WebClient =
  class
    inherit System.ComponentModel.Component
    new : unit -> System.Net.WebClient
    member BaseAddress : string with get, set
    member CachePolicy : System.Net.Cache.RequestCachePolicy with get, set
    member CancelAsync : unit -> unit
    member Credentials : System.Net.ICredentials with get, set
    member DownloadData : string -> System.Byte []
    member DownloadData : System.Uri -> System.Byte []
    member DownloadDataAsync : System.Uri -> unit
    member DownloadDataAsync : System.Uri * obj -> unit
    member DownloadFile : string * string -> unit
    member DownloadFile : System.Uri * string -> unit
    member DownloadFileAsync : System.Uri * string -> unit
    member DownloadFileAsync : System.Uri * string * obj -> unit
    member DownloadString : string -> string
    member DownloadString : System.Uri -> string
    member DownloadStringAsync : System.Uri -> unit
    member DownloadStringAsync : System.Uri * obj -> unit
    member Encoding : System.Text.Encoding with get, set
    member Headers : System.Net.WebHeaderCollection with get, set
    member IsBusy : bool
    member OpenRead : string -> System.IO.Stream
    member OpenRead : System.Uri -> System.IO.Stream
    member OpenReadAsync : System.Uri -> unit
    member OpenReadAsync : System.Uri * obj -> unit
    member OpenWrite : string -> System.IO.Stream
    member OpenWrite : System.Uri -> System.IO.Stream
    member OpenWrite : string * string -> System.IO.Stream
    member OpenWrite : System.Uri * string -> System.IO.Stream
    member OpenWriteAsync : System.Uri -> unit
    member OpenWriteAsync : System.Uri * string -> unit
    member OpenWriteAsync : System.Uri * string * obj -> unit
    member Proxy : System.Net.IWebProxy with get, set
    member QueryString : System.Collections.Specialized.NameValueCollection with get, set
    member ResponseHeaders : System.Net.WebHeaderCollection
    member UploadData : string * System.Byte [] -> System.Byte []
    member UploadData : System.Uri * System.Byte [] -> System.Byte []
    member UploadData : string * string * System.Byte [] -> System.Byte []
    member UploadData : System.Uri * string * System.Byte [] -> System.Byte []
    member UploadDataAsync : System.Uri * System.Byte [] -> unit
    member UploadDataAsync : System.Uri * string * System.Byte [] -> unit
    member UploadDataAsync : System.Uri * string * System.Byte [] * obj -> unit
    member UploadFile : string * string -> System.Byte []
    member UploadFile : System.Uri * string -> System.Byte []
    member UploadFile : string * string * string -> System.Byte []
    member UploadFile : System.Uri * string * string -> System.Byte []
    member UploadFileAsync : System.Uri * string -> unit
    member UploadFileAsync : System.Uri * string * string -> unit
    member UploadFileAsync : System.Uri * string * string * obj -> unit
    member UploadString : string * string -> string
    member UploadString : System.Uri * string -> string
    member UploadString : string * string * string -> string
    member UploadString : System.Uri * string * string -> string
    member UploadStringAsync : System.Uri * string -> unit
    member UploadStringAsync : System.Uri * string * string -> unit
    member UploadStringAsync : System.Uri * string * string * obj -> unit
    member UploadValues : string * System.Collections.Specialized.NameValueCollection -> System.Byte []
    member UploadValues : System.Uri * System.Collections.Specialized.NameValueCollection -> System.Byte []
    member UploadValues : string * string * System.Collections.Specialized.NameValueCollection -> System.Byte []
    member UploadValues : System.Uri * string * System.Collections.Specialized.NameValueCollection -> System.Byte []
    member UploadValuesAsync : System.Uri * System.Collections.Specialized.NameValueCollection -> unit
    member UploadValuesAsync : System.Uri * string * System.Collections.Specialized.NameValueCollection -> unit
    member UploadValuesAsync : System.Uri * string * System.Collections.Specialized.NameValueCollection * obj -> unit
    member UseDefaultCredentials : bool with get, set
  end

Full name: System.Net.WebClient

  type: WebClient
  implements: ComponentModel.IComponent
  implements: IDisposable
  inherits: ComponentModel.Component
  inherits: MarshalByRefObject
member MainController.HelloCompleted : result:int -> 'a

Full name: Snippet.MainController.HelloCompleted
val result : int

  type: int
  implements: IComparable
  implements: IFormattable
  implements: IConvertible
  implements: IComparable<int>
  implements: IEquatable<int>
  inherits: ValueType
Multiple items
val int : 'T -> int (requires member op_Explicit)

Full name: Microsoft.FSharp.Core.Operators.int

--------------------

type int<'Measure> = int

Full name: Microsoft.FSharp.Core.int<_>

  type: int<'Measure>
  implements: IComparable
  implements: IConvertible
  implements: IFormattable
  implements: IComparable<int<'Measure>>
  implements: IEquatable<int<'Measure>>
  inherits: ValueType


--------------------

type int = int32

Full name: Microsoft.FSharp.Core.int

  type: int
  implements: IComparable
  implements: IFormattable
  implements: IConvertible
  implements: IComparable<int>
  implements: IEquatable<int>
  inherits: ValueType

More information

Link: http://fssnip.net/4z
Posted: 2 years ago
Author: Tomas Petricek (website)
Tags: async, asynchronous workflows, asp.net, web, mvc