Looking into updating a slew of VB.NET API to C# for a client, and figured I should brush off my VB.NET before getting too serious.
And I figured that means I should make a console app, connect to a sample API URI at JsonPlaceholder, grab a collection of entities, serialize them, loop through, and access something on each individual entity instance. That's half (or more) of what any API does, right?
Oh wow. Slightly larger rabbit hole than I figured.
First, you can't make the top-level Main
sub Async
in VB.NET. DotNetPerls makes it sound like you can wait out an Async Sub
from the Sub Main
, but you can't.
From stackoverflow.com:
Sub
s should not be async. Event handlers are the only exception to that rule. You awaitTask
which can only be returned from aFunction
. If the intention is to make that interface async then all the members need to be functions that return aTask
or its derivative.
Can confirm.
The right answer is to set up an awaiter in a synchronous [sic] Sub Main
.
From stackoverflow.com:
You won't be able to do top-level
Await
in a console program. You can still make it work (preserving theAsync
onLoadData
) with the following changes:
- Change the signature of
LoadData
toPrivate Async Function LoadData() As Task
- Change the call in
Main
toLoadData.GetAwaiter().GetResult()
It is somewhat amazing how few upvotes these have gotten at SO. Aka "VB.NET was never super popular, relatively speaking [to C#], was it?"
Here's some working code.
Imports Newtonsoft.Json
Module Program
Public Sub Main()
Console.WriteLine("Hello World!")
DoStuff.GetAwaiter().GetResult()
Console.WriteLine("Done")
End Sub
Private Async Function DoStuff() As Task
Dim httpClient As New Net.Http.HttpClient
httpClient.BaseAddress = New Uri("https://jsonplaceholder.typicode.com/")
Try
Console.WriteLine("Starting")
' BaseAddress is strangely draconian:
' https://stackoverflow.com/a/23438417/1028230
'Dim result1 As String = Await webClient.GetStringAsync("https://jsonplaceholder.typicode.com/users/1/todos") ' if you don't use BaseAddress
Dim result1 As String = Await httpClient.GetStringAsync("users/1/todos")
Console.WriteLine("Ending")
Dim allTodos = JsonConvert.DeserializeObject(Of IEnumerable(Of Todo))(result1)
For Each element In allTodos
Console.Write(element.Id & "--")
Next
Catch ex As Exception
Console.WriteLine(ex.Message)
End Try
End Function
End Module
and the Todo
class looks like this:
Public Class Todo
'{
' "userId": 1,
' "id": 1,
' "title": "delectus aut autem",
' "completed": false
'},
Public Property UserId As Integer
Public Property Id As Integer
Public Property Title As String
Public Property Completed As Boolean
End Class
As I think I've mentioned before, a prof told me in college, "They're all different dialects of the same language." Or as a buddy on the ultimate team said, "It's all zeroes and ones." Nothing fancy going on here, but it does take a while to get your ears tuned to the new (ancient?) dialect.