I have a JSON object created using Newtonsoft JObject but I get a bad request error when I try to submit it if any of the properties have spaces, slashes, etc.
updatestring = "date=2/14/2019"
Dim jobjattr As New Newtonsoft.Json.Linq.JObject(
New Newtonsoft.Json.Linq.JProperty("description", "test"),
New Newtonsoft.Json.Linq.JProperty("source", updatestring)
)
Dim jobjdat As New Newtonsoft.Json.Linq.JObject(
New Newtonsoft.Json.Linq.JProperty("type", "synch_log"),
New Newtonsoft.Json.Linq.JProperty("id", "6278042e-ed64-0418-a651-5c574dc4f12b"),
New Newtonsoft.Json.Linq.JProperty("attributes", jobjattr)
)
Dim jobj As New Newtonsoft.Json.Linq.JObject(New Newtonsoft.Json.Linq.JProperty("data", jobjdat))
Dim jsonserializersettings As New Newtonsoft.Json.JsonSerializerSettings
jsonserializersettings.StringEscapeHandling = Newtonsoft.Json.StringEscapeHandling.EscapeNonAscii
Dim stringReq = Newtonsoft.Json.JsonConvert.SerializeObject(jobj, jsonserializersettings)
Dim byteData As Byte() = System.Text.Encoding.UTF8.GetBytes(stringReq)
httprequest.ContentLength = byteData.Length
Dim postreqstream As System.IO.Stream = .GetRequestStream()
postreqstream.Write(byteData, 0, byteData.Length)
postreqstream.Close()
incoming jobj = {"data":{"type":"synch_log","id":"6278042e-ed64-0418-a651-5c574dc4f12b","attributes":{"description":"test","source":"date=2/14/2019"}}}
after serialzation byteData still = {"data":{"type":"synch_log","id":"6278042e-ed64-0418-a651-5c574dc4f12b","attributes":{"description":"test","source":"date=2/14/2019"}}}
I would expect the / to be escaped.
any text string works fine
I have also tried jsonserializer settings as Default and EscapeHtml but with the same result.
Other characters cause the same eror. "datetoday" posts correctly but "date=today" and "date today" result in a 400 bad request error
The closest answer I have found is that maybe the object is being double escaped but I can't see how that would be.
Thank you everyone. Brian, you led me in the right direction. I failed to mention that it is an API call to SuiteCRM but your question got me thinking to look on the server side and it turns out there is an unresolved bug with the V8 API. I just assumed it was my code.
github bug report
Related
Please see part of the code used to save response as a string to resultData variable:
Using response As WebResponse = request.GetResponse()
Dim responseStream As IO.Stream = response.GetResponseStream()
Dim sr As New IO.StreamReader(responseStream)
resultData = sr.ReadToEnd()
It works correctly.
I have one case where the output is a binary file. How can I modify this code to save the reponse as a binary ResultData variable?
Thank you in advance for your support.
There is many ways to do that. This one, is one of those. (This one help you also to show the progress)
However (as advice) to monitoring progress there exists better approaches like Async methods etc.
In the example below I’m going to show you how to save e WebRequest as binary data.
Note that, I’m based on your code and what you want, but, as I said before there exists different better approaches.
'here the file you want to save
Dim LocalFilePath As String = "C:\Users\MyUser\Documents\FolderXYZ\yourfileName.extension"
Using reader As IO.Stream = request.GetResponse.GetResponseStream
Using writer As IO.Stream = New IO.FileStream(LocalFilePath, IO.FileMode.OpenOrCreate, IO.FileAccess.ReadWrite)
Dim b(1024 * 2) As Byte
Dim buffer As Integer = b.Length
Do While buffer <> 0
buffer = reader.Read(b, 0, b.Length)
writer.Write(b, 0, buffer)
writer.Flush()
Loop
End Using
End Using
On the following webpage I'd like to get all the titles of youtube videos in my listbox1
Dim webRequest As WebRequest = webRequest.Create("https://www.youtube.com/results?q=test")
Dim webresponse As WebResponse = webRequest.GetResponse()
Dim sr As System.IO.StreamReader = New System.IO.StreamReader(webresponse.GetResponseStream())
Dim youtube As String = sr.ReadToEnd
Dim r As New System.Text.RegularExpressions.Regex("title="".*""")
Dim matches As MatchCollection = r.Matches(youtube)
For Each itemcode As Match In matches
ListBox1.Items.Add(itemcode.Value.Split("""").GetValue(1))
However with this code I get the titles but also a bunch of other stuff...
YouTube provides an API which might be a better way to get this information. The specific call you want to make is documented here: https://developers.google.com/youtube/v3/docs/search/list.
In order to use the YouTube API you will need to create an API key. This can be done from the Google developers console. Once you have a key then you can make calls to YouTube to search videos, get video information etc
Using your code as the basis you could use something along these lines:
Dim url As String = "https://www.googleapis.com/youtube/v3/search?part=snippet&q=test&maxResults=50&key={YOUR-API-KEY}"
Dim webRequest As WebRequest = webRequest.Create(url)
Dim webresponse As WebResponse = webRequest.GetResponse()
Dim sr As System.IO.StreamReader = New System.IO.StreamReader(webresponse.GetResponseStream())
Dim youtube As String = sr.ReadToEnd
Dim r As New System.Text.RegularExpressions.Regex("""title"": "".*""")
Dim matches As MatchCollection = r.Matches(youtube)
For Each itemcode As Match In matches
ListBox1.Items.Add(itemcode.Value.Split(":").GetValue(1).Trim().TrimStart("""").TrimEnd(""""))
Next
The q parameter specifies the search query. This will get the first 50 matches to your search and put them in your drop down list.
If you want to stick with regular expression try the following
Dim r As New System.Text.RegularExpressions.Regex("title=""([^""]*)""")
Dim matches As MatchCollection = r.Matches(youtube)
For Each itemcode As Match In matches
ListBox1.Items.Add(itemcode.Groups(1))
Next
However a dedicated API is cleaner
I'm trying to set the user agent for a request with XmlRead. I googled a lot about this and couldn't find the answer. Here is my chunk of code:
Dim RssData As DataSet
Dim Title As String
Dim Url As String
Dim Stream As String
Dim buffer As Integer
RssData = New DataSet()
RssData.ReadXml("http://localhost/user_agent.php")
buffer = 0
For Each RssRow As DataRow In RssData.Tables("entry").Rows
Title = Microsoft.VisualBasic.Left(RssRow.Item("title").ToString, 30)
Stream += Title & vbCrLf
Next
LinkLabel3.Text = Stream
For Each RssRow As DataRow In RssData.Tables("entry").Rows
Title = Microsoft.VisualBasic.Left(RssRow.Item("title").ToString, 30)
Url = RssRow.Item("url").ToString
LinkLabel3.Links.Add(buffer, Title.Length, Url)
buffer = buffer + Title.Length + 2
Next
The part of the code that actually performs the web request is buried pretty deep so you'd have to inherit a bunch of code to do what you asked for. Instead, let me suggest a different path, download the XML on your own with code that's easy to set that header, and then load that into the dataset. The WebClient class lets you set arbitrary headers and has a simple DownloadString method. Once you've got that you can wrap it in a MemoryStream and pass that into ReadXml(). (I couldn't find a way to read the XML as a string, that's why I was forced to read it as Stream.)
''//Will hold our downloaded XML
Dim MyXml As String
''//Create a webclient to download our XML
Using WC As New System.Net.WebClient()
''//Manually set the user agent header
WC.Headers.Add("user-agent", "your user agent here")
''//Download the XML
MyXml = WC.DownloadString("http://localhost/user_agent.php")
End Using
''//Create our dataset object
Dim RssData As New DataSet()
''//There is no direct method to load XML as a string (at least that I could find) so we will
''// convert it to a byte array and load it into a memory stream
Dim Bytes As Byte() = System.Text.Encoding.UTF8.GetBytes(MyXml)
Using MS As New System.IO.MemoryStream(Bytes)
''//Load the stream into the reader
RssData.ReadXml(MS)
End Using
''//Your code continues normally here
In another question here at Stack Overflow, I came across a very helpful code snippet to send code to the Google Closure Compiler, which can minify JavaScript files pretty good.
The problem I'm facing however is that it returns no compiled code in cases I don't expect it to do so.
Code:
This works, i.e. returns minified code:
Dim script = "function test(name) {alert(name);}test('New user');"
This one, on the other hand, does not return anything. The statistics are sent, but no compiled data...:
Dim script = "function test(name) {alert(name);}"
Rest of the code which actually does the work:
Dim Data = String.Format(ClosureWebServicePOSTData, HttpUtility.UrlEncode(script))
_Result = New StringBuilder
_HttpWebRequest = DirectCast(WebRequest.Create(ClosureWebServiceURL), HttpWebRequest)
_HttpWebRequest.Method = "POST"
_HttpWebRequest.ContentType = "application/x-www-form-urlencoded"
'//Set the content length to the length of the data. This might need to change if you're using characters that take more than 256 bytes
_HttpWebRequest.ContentLength = Data.Length
'//Write the request stream
Using SW As New StreamWriter(_HttpWebRequest.GetRequestStream())
SW.Write(Data)
End Using
Dim response As WebResponse = _HttpWebRequest.GetResponse()
Using responseStream As Stream = response.GetResponseStream
Dim encoding As Encoding = System.Text.Encoding.GetEncoding("utf-8")
Using readStream As New StreamReader(responseStream, encoding)
Dim read(256) As Char
Dim count As Integer = readStream.Read(read, 0, 256)
While count > 0
Dim str As New String(read, 0, count)
_Result.Append(str)
count = readStream.Read(read, 0, 256)
End While
End Using
End Using
What could be the casue at all? I'm curious to know.
Possibly using the ADVANCED_OPTIMIZATIONS setting? The function may have been stripped because it is defined, but never used.
check out this page: closure compiler tutorial
I am trying to use a Web Service to return Json for a Collection of Users from a Database Table. I'm only new to .NET (< 1 week experience), and I don't want to use the UpdatePanel for AJAX. I have tried using the JavaScriptSerializer as well as Json.NET to serialize. Both cases seem to spawn an Infinite Loop.
What am I doing wrong? Is there a better way to do this? I appreciate any suggestions. Thanks.
Dim myUser As New HagarDB.Users
myUser.Read()
'Dim jsSerializer As New System.Web.Script.Serialization.JavaScriptSerializer
'Dim sbUsers As New System.Text.StringBuilder
'jsSerializer.Serialize(myUser, sbUsers)
Dim json = JsonConvert.SerializeObject(myUser, Formatting.Indented)
Thanks to RPM1984 for suggesting DataContractJsonSerializer. Here is the working code:
Public Function GetUsers() As String
Dim myUser As New HagarDB.Users
Dim jsonSerializer As New DataContractJsonSerializer(GetType(HagarDB.Users))
Dim stream As New MemoryStream()
myUser.Read()
jsonSerializer.WriteObject(stream, myUser)
Dim json As String = Encoding.[Default].GetString(stream.ToArray())
stream.Close()
Return json
End Function