bautista
bautista

Reputation: 794

Create Json in VB.net from string and use it in WebRequest

I'm trying to call openrouteservice api in vb.net and therefore tried to follow the documentation/examples. The example shows below code as working example:

Sub Main(args As String())
    Dim request = TryCast(System.Net.WebRequest.Create("https://api.openrouteservice.org/v2/directions/driving-car/gpx"), System.Net.HttpWebRequest)

    request.Method = "POST"

    request.Accept = "application/json, application/geo+json, application/gpx+xml, img/png; charset=utf-8"
    request.Headers.Add("Authorization", "xxxxMYKEYxxxx")
    request.Headers.Add("Content-Type", "application/json; charset=utf-8")

    Using writer = New System.IO.StreamWriter(request.GetRequestStream())
        Dim byteArray As Byte() = System.Text.Encoding.UTF8.GetBytes({"coordinates:[[8.681495,49.41461],[8.686507,49.41943],[8.687872,49.420318]]"})
        request.ContentLength = byteArray.Length
        writer.Write(byteArray)
        writer.Close()
    End Using
    Dim responseContent As String
    Using response = TryCast(request.GetResponse(), System.Net.HttpWebResponse)
        Using reader = New System.IO.StreamReader(response.GetResponseStream())
            responseContent = reader.ReadToEnd()
            Console.WriteLine(responseContent.ToString())
        End Using
    End Using
End Sub

The example shows that the content of the request body should be the following:

{"coordinates":[[8.681495,49.41461],[8.686507,49.41943],[8.687872,49.420318]]}

But when running the example i get the following error:

'The remote server returned an error: (500) Internal Server Error.'

So i figured that the request fails because of the invalid Json. My question is how to create a JSON resulting in the same as in the example-JSON provided above?

Upvotes: 1

Views: 11467

Answers (1)

Jimi
Jimi

Reputation: 32248

The API is expecting a JSON object, representing an array of arrays of double values, as the content of the HttpRequest, encoded as an UTF-8 string, sent as a byte array.

This collection can be represented by a List(Of List(Of Double) Property Type of a .Net class:

' Note that JavaScriptSrializer might ignore <JsonProperty>,
' so use lower case, since the Web API is case-sensitive
Friend Class MyObject
    <JsonProperty("coordinates")>
    Public Property coordinates As List(Of List(Of Double))
End Class

After this, we just need to fill the List:

Dim myobj = New MyObject() With {
    .Coordinates = New List(Of List(Of Double)) From {
        New List(Of Double)({8.681495, 49.41461}),
        New List(Of Double)({8.686507, 49.41943}),
        New List(Of Double)({8.687872, 49.420318})
    }
}

And serialize it, with either Json.Net (install the NuGet package via NuGet Package Manager) or JavaScriptSerializer (or any other JSON serializer available):

JavaScriptSerializer requires a Project reference to System.Web.Extension and to import System.Web.Script.Serialization.

' Using Json.Net
Dim Json As String = JsonConvert.SerializeObject(myobj)

' Or JavaScriptSerializer
Dim json = New JavaScriptSerializer().Serialize(myobj)

► The original code has more than one issue:

  • The webRequest.ContentLength is set too late: it needs to be set before the request sent
  • The StreamWriter used to write to the WebRequest Stream will compromise the process: it's not needed and it will be closed before the bytes are written to the Request Stream
  • Content-Type cannot be set using the Headers, we must use WebRequest.ContentType property
  • Added SecurityProtocolType.Tls12 in case this code is used in Windows 7 or a WM (in Windows 7, the default is SecurityProtocolType.Ssl3 Or SecurityProtocolType.Tls, thus TLS1.0, which isn't really used anymore, TLS1.2 is (still) the major player at this time)

Fixed original code, using JavaScriptSerializer to serialize the request data:

Replace Imports System.Web.Script.Serialization with Imports Newtonsoft.Json if you use Json.Net.

Imports System.IO
Imports System.Text
Imports System.Web.Script.Serialization

Dim myobj = New MyObject() With {
    .Coordinates = New List(Of List(Of Double)) From {
        New List(Of Double)({8.681495, 49.41461}),
        New List(Of Double)({8.686507, 49.41943}),
        New List(Of Double)({8.687872, 49.420318})
    }
}

Dim json As String = New JavaScriptSerializer().Serialize(myobj)

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12
Dim request = WebRequest.CreateHttp("https://api.openrouteservice.org/v2/directions/driving-car/gpx")

request.Method = "POST"
request.PreAuthenticate = True
request.Accept = "application/json, application/geo+json, application/gpx+xml, img/png; charset=utf-8"
request.Headers.Add("Authorization", "[Your API Key]")
request.ContentType = "application/json; charset=utf-8"

Dim jsonBytes = Encoding.UTF8.GetBytes(json)
request.ContentLength = jsonBytes.Length
Using reqStream = request.GetRequestStream()
    reqStream.Write(jsonBytes, 0, jsonBytes.Length)
End Using

Dim responseContent As String = String.Empty
Using response = DirectCast(request.GetResponse(), HttpWebResponse),
    responseStream = response.GetResponseStream(),
    reader = New StreamReader(responseStream)
    responseContent = reader.ReadToEnd()
End Using

Upvotes: 2

Related Questions