This example is taken from dotnet/fsharp documentation and it's outdated for this reason - "This construct is deprecated. WebRequest, HttpWebRequest, ServicePoint, and WebClient are obsolete. Use HttpClient instead." https://learn.microsoft.com/en-us/dotnet/fsharp/language-reference/async-expressions
How would this example look using HttpClient?
Just to mention I'm new to web development but I do understand what async expressions are, just having trouble converting the example to be using HttpClient.
open System.Net
open Microsoft.FSharp.Control.WebExtensions
let urlList = [ "Microsoft.com", "http://www.microsoft.com/"
"MSDN", "http://msdn.microsoft.com/"
"Bing", "http://www.bing.com"
]
let fetchAsync(name, url:string) =
async {
try
let uri = new System.Uri(url)
let webClient = new WebClient()
let! html = webClient.AsyncDownloadString(uri)
printfn "Read %d characters for %s" html.Length name
with
| ex -> printfn "%s" (ex.Message);
}
let runAll() =
urlList
|> Seq.map fetchAsync
|> Async.Parallel
|> Async.RunSynchronously
|> ignore
runAll()
Here is some code from one of my projects. You may want to deal with errors differently, but I guess you can extract what you need.
EDIT: I also added some simple error handling and made the example complete.
open System.Net
open System.Net.Http
[<RequireQualifiedAccess>]
module Web =
let private http = new HttpClient(Timeout = System.TimeSpan.FromSeconds 40.)
type WebError =
| HttpErrorCode of HttpStatusCode * Body: string
| HttpNetworkIssue of string
| HttpTimeout
let getStringAsync (url: string) =
async {
try
let! response = http.GetAsync url |> Async.AwaitTask
let! body = response.Content.ReadAsStringAsync() |> Async.AwaitTask
if response.IsSuccessStatusCode then return Ok body
else return Error (HttpErrorCode (response.StatusCode, body))
with
| :? System.Threading.Tasks.TaskCanceledException -> return Error HttpTimeout
| ex -> return Error (HttpNetworkIssue ex.Message)
}
module Test =
let urlList = [ "Microsoft.com", "http://www.microsoft.com/"
"MSDN", "http://msdn.microsoft.com/"
"Bing", "http://www.bing.com"
]
let checkSite (name, url:string) =
async {
let! res = Web.getStringAsync url
match res with
| Ok html ->
printfn "Read %d characters for %s" html.Length name
| Error (Web.HttpErrorCode(code, body)) ->
printfn $"ERROR: http error code {code} with body {body}"
| Error (Web.HttpNetworkIssue(s)) ->
printfn $"ERROR: network issue: {s}"
| Error (Web.HttpTimeout) ->
printfn $"ERROR: timeout"
}
let runAll() =
urlList
|> Seq.map checkSite
|> Async.Parallel
|> Async.RunSynchronously
|> ignore
runAll()