5 people like it.
Like the snippet!
Walkthrough: Creating an Asynchronous HTTP Handler
The Microsoft tutorial Walkthrough: Creating an Asynchronous HTTP Handler did not describe how to use IHttpAsyncHandler from F#.
It was also a bit complicated, because it did not show how to do it from Visual Studio.
Here is the Visual Studio F# version.
1. Create empty ASP.NET Web Application. Call it FSharpHttpAsyncHandler.
2. Add a F# library project to the solution. Call it FSharpHttpAsyncHandler.Lib.
3. Add the following code to Library1.fs in FSharpHttpAsyncHandler.Lib
4. Add a reference to System.Web in FSharpHttpAsyncHandler.Lib
5. Add a reference to FSharpHttpAsyncHandler.Lib in FSharpHttpAsyncHandler.
6. Add the following to Web.config in FSharpHttpAsyncHandler.
7. In the Web tab of the project properties of FSharpHttpAsyncHandler, set Start url to http://localhost://whatever.SampleAsync
8. Run debug.
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
|
// Library1.fs content
namespace FSharpHttpAsyncHandler.Lib
open System
open System.Web
open System.Threading
type AsynchOperation (callback:AsyncCallback, context:HttpContext, state:Object) as this =
let _callback:AsyncCallback = callback
let _context:HttpContext = context
let _state:Object = state
let mutable _completed:bool = false
interface IAsyncResult with
member x.IsCompleted
with get() =
_completed
member x.AsyncWaitHandle
with get() =
null
member x.AsyncState
with get() =
_state
member x.CompletedSynchronously
with get() =
false
member x.StartAsyncTask(workItemState:Object) :unit =
_context.Response.Write("<p>Completion IsThreadPoolThread is " + (Thread.CurrentThread.IsThreadPoolThread).ToString() + "</p>\r\n")
_context.Response.Write("Hello World from Async Handler!")
_completed <- true
_callback.Invoke(this:>IAsyncResult)
member x.StartAsyncWork() =
ThreadPool.QueueUserWorkItem(new WaitCallback(x.StartAsyncTask), null)
type HTTPAsyncHandler () =
interface IHttpAsyncHandler with
member x.IsReusable
with get() =
false
member x.BeginProcessRequest(context:HttpContext, cb:AsyncCallback, extraData:Object):IAsyncResult =
context.Response.Write("<p>Begin IsThreadPoolThread is " + (Thread.CurrentThread.IsThreadPoolThread).ToString() + "</p>\r\n")
let asynch:AsynchOperation = new AsynchOperation(cb, context, extraData)
asynch.StartAsyncWork()|> ignore
asynch:>IAsyncResult
member x.ProcessRequest(context:HttpContext):unit =
raise (new System.InvalidOperationException())
member x.EndProcessRequest((result:IAsyncResult)):unit =
()
(* Web.config
<?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true"/>
</system.web>
<system.webServer>
<validation validateIntegratedModeConfiguration="false"/>
<modules runAllManagedModulesForAllRequests="true"/>
<handlers>
<add name="FunctionalHandler" preCondition="integratedMode" verb="*" path="*" type="FSharpHttpAsyncHandler.Lib.HTTPAsyncHandler, FSharpHttpAsyncHandler.Lib"/>
</handlers>
</system.webServer>
</configuration>
*)
|
namespace System
namespace System.Web
namespace System.Threading
Multiple items
type AsynchOperation =
interface IAsyncResult
new : callback:AsyncCallback * context:HttpContext * state:Object -> AsynchOperation
member StartAsyncTask : workItemState:Object -> unit
member StartAsyncWork : unit -> bool
Full name: FSharpHttpAsyncHandler.Lib.AsynchOperation
--------------------
new : callback:AsyncCallback * context:HttpContext * state:Object -> AsynchOperation
val callback : AsyncCallback
type AsyncCallback =
delegate of IAsyncResult -> unit
Full name: System.AsyncCallback
val context : HttpContext
Multiple items
type HttpContext =
new : wr:HttpWorkerRequest -> HttpContext + 1 overload
member AddError : errorInfo:Exception -> unit
member AllErrors : Exception[]
member Application : HttpApplicationState
member ApplicationInstance : HttpApplication with get, set
member Cache : Cache
member ClearError : unit -> unit
member CurrentHandler : IHttpHandler
member CurrentNotification : RequestNotification with get, set
member Error : Exception
...
Full name: System.Web.HttpContext
--------------------
HttpContext(wr: HttpWorkerRequest) : unit
HttpContext(request: HttpRequest, response: HttpResponse) : unit
val state : Object
Multiple items
type Object =
new : unit -> obj
member Equals : obj:obj -> bool
member GetHashCode : unit -> int
member GetType : unit -> Type
member ToString : unit -> string
static member Equals : objA:obj * objB:obj -> bool
static member ReferenceEquals : objA:obj * objB:obj -> bool
Full name: System.Object
--------------------
Object() : unit
val this : AsynchOperation
type bool = Boolean
Full name: Microsoft.FSharp.Core.bool
type IAsyncResult =
member AsyncState : obj
member AsyncWaitHandle : WaitHandle
member CompletedSynchronously : bool
member IsCompleted : bool
Full name: System.IAsyncResult
val x : AsynchOperation
override AsynchOperation.IsCompleted : bool
Full name: FSharpHttpAsyncHandler.Lib.AsynchOperation.IsCompleted
val mutable _completed : bool
override AsynchOperation.AsyncWaitHandle : WaitHandle
Full name: FSharpHttpAsyncHandler.Lib.AsynchOperation.AsyncWaitHandle
override AsynchOperation.AsyncState : obj
Full name: FSharpHttpAsyncHandler.Lib.AsynchOperation.AsyncState
val _state : Object
override AsynchOperation.CompletedSynchronously : bool
Full name: FSharpHttpAsyncHandler.Lib.AsynchOperation.CompletedSynchronously
member AsynchOperation.StartAsyncTask : workItemState:Object -> unit
Full name: FSharpHttpAsyncHandler.Lib.AsynchOperation.StartAsyncTask
val workItemState : Object
type unit = Unit
Full name: Microsoft.FSharp.Core.unit
val _context : HttpContext
property HttpContext.Response: HttpResponse
HttpResponse.Write(ch: char) : unit
HttpResponse.Write(obj: obj) : unit
HttpResponse.Write(s: string) : unit
HttpResponse.Write(buffer: char [], index: int, count: int) : unit
Multiple items
type Thread =
inherit CriticalFinalizerObject
new : start:ThreadStart -> Thread + 3 overloads
member Abort : unit -> unit + 1 overload
member ApartmentState : ApartmentState with get, set
member CurrentCulture : CultureInfo with get, set
member CurrentUICulture : CultureInfo with get, set
member DisableComObjectEagerCleanup : unit -> unit
member ExecutionContext : ExecutionContext
member GetApartmentState : unit -> ApartmentState
member GetCompressedStack : unit -> CompressedStack
member GetHashCode : unit -> int
...
Full name: System.Threading.Thread
--------------------
Thread(start: ThreadStart) : unit
Thread(start: ParameterizedThreadStart) : unit
Thread(start: ThreadStart, maxStackSize: int) : unit
Thread(start: ParameterizedThreadStart, maxStackSize: int) : unit
property Thread.CurrentThread: Thread
property Thread.IsThreadPoolThread: bool
val _callback : AsyncCallback
AsyncCallback.Invoke(ar: IAsyncResult) : unit
member AsynchOperation.StartAsyncWork : unit -> bool
Full name: FSharpHttpAsyncHandler.Lib.AsynchOperation.StartAsyncWork
type ThreadPool =
static member BindHandle : osHandle:nativeint -> bool + 1 overload
static member GetAvailableThreads : workerThreads:int * completionPortThreads:int -> unit
static member GetMaxThreads : workerThreads:int * completionPortThreads:int -> unit
static member GetMinThreads : workerThreads:int * completionPortThreads:int -> unit
static member QueueUserWorkItem : callBack:WaitCallback -> bool + 1 overload
static member RegisterWaitForSingleObject : waitObject:WaitHandle * callBack:WaitOrTimerCallback * state:obj * millisecondsTimeOutInterval:uint32 * executeOnlyOnce:bool -> RegisteredWaitHandle + 3 overloads
static member SetMaxThreads : workerThreads:int * completionPortThreads:int -> bool
static member SetMinThreads : workerThreads:int * completionPortThreads:int -> bool
static member UnsafeQueueNativeOverlapped : overlapped:NativeOverlapped -> bool
static member UnsafeQueueUserWorkItem : callBack:WaitCallback * state:obj -> bool
...
Full name: System.Threading.ThreadPool
ThreadPool.QueueUserWorkItem(callBack: WaitCallback) : bool
ThreadPool.QueueUserWorkItem(callBack: WaitCallback, state: obj) : bool
type WaitCallback =
delegate of obj -> unit
Full name: System.Threading.WaitCallback
member AsynchOperation.StartAsyncTask : workItemState:Object -> unit
Multiple items
type HTTPAsyncHandler =
interface IHttpAsyncHandler
new : unit -> HTTPAsyncHandler
Full name: FSharpHttpAsyncHandler.Lib.HTTPAsyncHandler
--------------------
new : unit -> HTTPAsyncHandler
type IHttpAsyncHandler =
member BeginProcessRequest : context:HttpContext * cb:AsyncCallback * extraData:obj -> IAsyncResult
member EndProcessRequest : result:IAsyncResult -> unit
Full name: System.Web.IHttpAsyncHandler
val x : HTTPAsyncHandler
override HTTPAsyncHandler.IsReusable : bool
Full name: FSharpHttpAsyncHandler.Lib.HTTPAsyncHandler.IsReusable
override HTTPAsyncHandler.BeginProcessRequest : context:HttpContext * cb:AsyncCallback * extraData:obj -> IAsyncResult
Full name: FSharpHttpAsyncHandler.Lib.HTTPAsyncHandler.BeginProcessRequest
val cb : AsyncCallback
val extraData : obj
val asynch : AsynchOperation
member AsynchOperation.StartAsyncWork : unit -> bool
val ignore : value:'T -> unit
Full name: Microsoft.FSharp.Core.Operators.ignore
override HTTPAsyncHandler.ProcessRequest : context:HttpContext -> unit
Full name: FSharpHttpAsyncHandler.Lib.HTTPAsyncHandler.ProcessRequest
val raise : exn:Exception -> 'T
Full name: Microsoft.FSharp.Core.Operators.raise
Multiple items
type InvalidOperationException =
inherit SystemException
new : unit -> InvalidOperationException + 2 overloads
Full name: System.InvalidOperationException
--------------------
InvalidOperationException() : unit
InvalidOperationException(message: string) : unit
InvalidOperationException(message: string, innerException: exn) : unit
override HTTPAsyncHandler.EndProcessRequest : result:IAsyncResult -> unit
Full name: FSharpHttpAsyncHandler.Lib.HTTPAsyncHandler.EndProcessRequest
val result : IAsyncResult
More information