How to write multiple records in a JSON file? - json.net

I cannot find this any where. I am using the newton JSON control and trying to loop through my records and write each record in one JSON file. Below is what I was trying but can't get it right. I get token path errors and all sorts. I don't know where to put the start and end for writing the JSON.
Thanks!
Warren
Dim sb As New StringBuilder()
Dim sw As New StringWriter(sb)
Using writer As JsonWriter = New JsonTextWriter(sw)
writer.Formatting = Formatting.Indented
writer.WriteStartObject()
Dim ConnString7 As String = "removed"
Dim SQLConn As New SqlConnection()
Dim SQLCmd As New SqlCommand()
SQLCmd.Connection = SQLConn
SQLConn.ConnectionString = ConnString7
SQLCmd.CommandType = CommandType.StoredProcedure
SQLCmd.CommandText = "Sproc_Here"
SQLConn.Open()
Dim reader As SqlDataReader
reader = SQLCmd.ExecuteReader()
While reader.Read()
MsgBox("Start")
writer.WritePropertyName("CardDate")
writer.WriteValue(reader("CardDate").ToString())
writer.WritePropertyName("EditDate")
writer.WriteValue(reader("EditDate").ToString())
writer.WritePropertyName("Activity")
writer.WriteValue(reader("Activity").ToString())
writer.WritePropertyName("Location")
writer.WriteValue(reader("Location").ToString())
MsgBox("End")
End While
reader.Close()
SQLConn.Close()
writer.WriteEnd()
writer.WriteEndObject()
MsgBox(sb.ToString)
Response.Clear()
Response.ContentType = "application/json; charset=utf-8"
Response.Write(sb.ToString)
Response.End()

Each record will become a JSON object, and you want to have multiple of them, so they need to be enclosed in a JSON array. So something like this:
Dim sb As New StringBuilder()
Dim sw As New StringWriter(sb)
Using writer As JsonWriter = New JsonTextWriter(sw)
writer.Formatting = Formatting.Indented
' ... code to set up SQLCmd omitted for brevity ...
Dim reader As SqlDataReader = SQLCmd.ExecuteReader()
writer.WriteStartArray()
While reader.Read()
writer.WriteStartObject()
writer.WritePropertyName("CardDate")
writer.WriteValue(reader("CardDate").ToString())
writer.WritePropertyName("EditDate")
writer.WriteValue(reader("EditDate").ToString())
writer.WritePropertyName("Activity")
writer.WriteValue(reader("Activity").ToString())
writer.WritePropertyName("Location")
writer.WriteValue(reader("Location").ToString())
writer.WriteEndObject()
End While
writer.WriteEndArray()
' ... code to close connection and write response omitted ...
End Using

Related

Emails' rich characters are mistranslated when read from database using MimeKit

I have a windows service written in VB.Net that downloads emails into MimeMessage objects, removes their attachments, and then writes the remains of the email to a SQL Server database. A separate ASP.Net application (using VB.Net) reads the email back into a MimeMessage object and returns it to the user upon request.
Something happens during this process that causes strange characters to appear in the output.
This question (Content encoding using MimeKit/MailKit) seemed promising, but changing the character encoding from ASCII to UTF8 etc didn't solve it.
Here’s the code that saves the email to the database:
Sub ImportEmail(exConnectionString As String)
Dim oClient As New Pop3Client()
' … email connection code removed …
Dim message = oClient.GetMessage(0)
Dim strippedMessage As MimeMessage = message
' … code to remove attachments removed …
Dim mem As New MemoryStream
strippedMessage.WriteTo(mem)
Dim bytes = mem.ToArray
Dim con As New SqlConnection(exConnectionString)
con.Open()
Dim com As New SqlCommand("INSERT INTO Emails (Body) VALUES (#RawDocument)", con)
com.CommandType = CommandType.Text
com.Parameters.AddWithValue("#RawDocument", bytes)
com.ExecuteNonQuery()
con.Close()
End Sub
And here’s the ASP.Net code to read it back to the user:
Private Sub OutputEmail(exConnectionString As String)
Dim BlobString As String = ""
Dim Sql As String = "SELECT Body FROM Emails WHERE Id = #id"
Dim com As New SqlClient.SqlCommand(Sql)
com.CommandType = CommandType.Text
com.Parameters.AddWithValue("#id", ViewState("email_id"))
Dim con As New SqlConnection(exConnectionString)
con.Open()
com.Connection = con
Dim da As New SqlClient.SqlDataAdapter(com)
Dim dt As New DataTable()
da.Fill(dt)
con.Close()
If dt.Rows.Count > 0 Then
Dim Row = dt.Rows(0)
BlobString = Row(0).ToString()
Dim MemStream As MemoryStream = GetMemoryStreamFromASCIIEncodedString(BlobString)
Dim message As MimeMessage = MimeMessage.Load(MemStream)
BodyBuilder.HtmlBody = message.HtmlBody
BodyBuilder.TextBody = message.TextBody
message.Body = BodyBuilder.ToMessageBody()
Response.ContentType = "message/rfc822"
Response.AddHeader("Content-Disposition", "attachment;filename=""" & Left(message.Subject, 35) & ".eml""")
Response.Write(message)
Response.End()
End If
End Sub
Private Function GetMemoryStreamFromASCIIEncodedString(ByVal BlobString As String) As MemoryStream
Dim BlobStream As Byte() = Encoding.ASCII.GetBytes(BlobString) ' **
Dim MemStream As MemoryStream = New MemoryStream()
MemStream.Write(BlobStream, 0, BlobStream.Length)
MemStream.Position = 0
Return MemStream
End Function
For example, let’s say the text below appears in the original email:
“So long and thanks for all the fish” (fancy quotes)
When read back, it appears as follows:
†So long and thanks for all the fishâ€
Other character replacements are as follows:
– (long dash) becomes –
• (bullets) become •
The problem is with the following snippet:
If dt.Rows.Count > 0 Then
Dim Row = dt.Rows(0)
BlobString = Row(0).ToString() ' <-- the ToString() is the problem
Dim MemStream As MemoryStream = GetMemoryStreamFromASCIIEncodedString(BlobString)
Dim message As MimeMessage = MimeMessage.Load(MemStream)
To fix the data corruption, what you need to do is this:
If dt.Rows.Count > 0 Then
Dim Row = dt.Rows(0)
Dim BlobString as Byte() = Row(0)
Dim MemStream As MemoryStream = new MemoryStream (BlobString, False)
Dim message As MimeMessage = MimeMessage.Load(MemStream)
You can also get rid of your GetMemoryStreamFromASCIIEncodedString function.
(Note: I don't know VB.NET, so I'm just guessing at the syntax, but it should be pretty close to being right)

Error to convert the binary to image

I try to import the image from mssql varbinary(max) column to iTextSharp.
But it always shows the error "NullReferenceException" on the "phrase.Add(imageChunk)"
My code is:
Dim conn As New SqlConnection(ConfigurationManager.ConnectionStrings("dbconnection").ConnectionString)
Dim q As String = "select top 1 pic_id from pic"
Dim cmd As SqlCommand = New SqlCommand(q, conn)
conn.Open()
Dim sr As SqlDataReader = cmd.ExecuteReader
While sr.Read
Dim byt() As Byte = CType(sr.Item("pic_id"), Byte())
Dim ms As MemoryStream = New MemoryStream(byt)
Dim sdi As System.Drawing.Image = System.Drawing.Image.FromStream(ms)
Dim img As Image = Image.GetInstance(sdi, ImageFormat.Jpeg)
Dim imageChunk As Chunk = New Chunk(img, 0, 0)
phrase.Add(imageChunk)
End While
The data type of that column is "varbinary(max)" and the data is like this: (0x89504E470D0A1A0A0000000D494....................)
Your variable "phrase" is not set, it's Nothing/null. Make sure to pass correct "phrase" to your method and it will quite likely fix your problem.

How to use ASPxFileManager 'SelectedFiles' property to attach files to MailMessage?

I am using DevExpress tools, specifically the FileManager which has a 'SelectedFiles' property which returns all the data needed to (add,insert,delete,retrieve, modify the record). However I can not figure out how to use the selectedfiles as a MailMessage.Attachment. The code below works to send the email, I've changed the credentials and host values for security. I just need some direction or thought on how to use the FileManager collection that is generated via 'SelectedFiles' and add them as an attachment to the email. I would really like to Zip the files if possible, but at this point simply attaching them is fine. Any thoughts?
Dim fileManager As ASPxFileManager = TryCast(sender, ASPxFileManager)
If ASPxFileManager1.SelectedFiles IsNot Nothing AndAlso ASPxFileManager1.SelectedFiles.Length > 0 Then
For i As Integer = 0 To ASPxFileManager1.SelectedFiles.Length - 1
Dim file = ASPxFileManager1.SelectedFiles.ToString
Dim attachments As New Attachment(fileManager.SelectedFiles.ToString)???
Next
End If
Try
Dim mail As New MailMessage("noreply", DropDownEdit.Text)
Dim smtp_Server As New SmtpClient("host") With {.Credentials = New Net.NetworkCredential("username", "password")}
mail.Subject = "SUBJECT"
mail.IsBodyHtml = False
mail.Body = "Testing"
smtp_Server.Send(mail)
successLabel.Text = "Your email was sent successfully."
Catch ex As Exception
End Try
End Sub
Dim attachments As New Attachment(ReadFile(ASPxFileManager1.SelectedFiles(i)), file)
mail.Attachments.Add(attachments)
The function below was needed to Read the bytes and then attach the items to the MailMessage.
Public Function ReadFile(file__1 As FileManagerFile) As System.IO.Stream
'This function allows us to pull the bytes from the DB value to render the file.
Dim filePath As String = (file__1.RelativeName)
Dim fileData As Byte()
Using con As New SqlConnection([Global].conn)
Dim sqlCmd As New SqlCommand()
sqlCmd.Connection = con
sqlCmd.Parameters.Add("#Name", SqlDbType.VarChar).Value = file__1.Name
sqlCmd.Parameters.Add("#APIKey", SqlDbType.Int).Value = Session("_UserAPIKey")
sqlCmd.CommandText = "SELECT STATEMENT"
con.Open()
Dim sqlReader As SqlDataReader = sqlCmd.ExecuteReader()
If sqlReader.HasRows Then
While sqlReader.Read()
fileData = CType(sqlReader(0), Byte())
End While
End If
End Using
Return New MemoryStream(fileData)
End Function

Using a stringbuilder as a parameter to a stored procedure and returning a dataset

I have a couple of problems relating to one of the parameters passing a number of values to a stored procedure and the result that comes back converting to dataset in order for this to be bound to an MS ReportViewer.
The error I am getting says that the the reader is closed.
My relevant code snippet is:
Dim _listOfSites As New StringBuilder()
Dim _resultDataSet As DataSet = New DataSet
Using _conn as New SqlConnection()
_conn.ConnectionString = _connString
Try
For i as Integer = 0 To _sites.Count - 1
_listOfSites.Append(_sites(i))
If _sites.Count > 1 Then
_listOfSites.Append(",")
End If
Next
_conn.Open()
Dim _sqlCommand as SqlCommand = New SqlCommand("GetResults", _conn)
_sqlCommand.Parameters.Add("#Sites", SqlDbType.Varchar).Value = _listOfSites
_sqlCommand.Parameters.Add("#Date", SqlDbType.Date).Value = _date
Dim _reader as SqlDataReader = _sqlCommand.ExecuteReader
While _reader.Read
_resultDataSet.Load(_reader, LoadOption.PreserveChanges, New String() {"RegionalResults"})
End While
_reader.Close()
Can anyone please help?
Thanks
Looks like you should not call _reader.Read as _resultDataSet.Load do it by itself and it could close the SqlDataReader. So instead of
Dim _reader as SqlDataReader = _sqlCommand.ExecuteReader
While _reader.Read
_resultDataSet.Load(_reader, LoadOption.PreserveChanges, New String() {"RegionalResults"})
End While
_reader.Close()
Just write
Using _reader as SqlDataReader = _sqlCommand.ExecuteReader
_resultDataSet.Load(_reader, LoadOption.PreserveChanges, New String() {"RegionalResults"})
End Using
Hope that helps

InvalidCastException when reading a BLOB object (PDF File) from an SQL Database

I'm having problems with an Invalid Cast Exception when I try and read a PDF from a database as a BLOB. I am able to write the files into the database no problems at all, however, when I try to retrieve them I just get InvalidCastException.
Here is the code I'm using:
Protected Sub btnPDF_Click(sender As Object, e As EventArgs) Handles btnPDF.Click
' Request.QueryString["docid"].ToString();
Dim docuid As String = "b39a443d-ccfd-47f4-b333-f12cd94683d6"
'Connection and Parameters
Dim param As SqlParameter = Nothing
Dim conn As SqlConnection = New SqlConnection(
ConfigurationManager.ConnectionStrings("menu").ToString())
Dim cmd As New SqlCommand("sp_getdoc", conn)
cmd.CommandType = CommandType.StoredProcedure
param = New SqlParameter("#docuid", SqlDbType.NVarChar, 100)
param.Direction = ParameterDirection.Input
param.Value = docuid
cmd.Parameters.Add(param)
'Open connection and fetch the data with reader
conn.Open()
Dim reader As SqlDataReader =
cmd.ExecuteReader(CommandBehavior.CloseConnection)
If reader.HasRows Then
reader.Read()
'
Dim doctype As String = reader("doctype").ToString()
Dim docname As String = reader("docname").ToString()
'
Response.Buffer = False
Response.ClearHeaders()
Response.ContentType = doctype
Response.AddHeader("Content-Disposition",
"attachment; filename=" + docname)
'
'Code for streaming the object while writing
Const ChunkSize As Integer = 1024
Dim buffer() As Byte = New Byte(ChunkSize) {}
Dim binary(reader("document")) As Byte
Dim ms As New MemoryStream(binary)
Dim SizeToWrite As Integer = ChunkSize
For i As Integer = 0 To binary.GetUpperBound(0) - 1 Step i = i + ChunkSize
If Not Response.IsClientConnected Then
Return
End If
If i + ChunkSize >= binary.Length Then
SizeToWrite = binary.Length - i
End If
Dim chunk(SizeToWrite) As Byte
ms.Read(chunk, 0, SizeToWrite)
Response.BinaryWrite(chunk)
Response.Flush()
Next
Response.Close()
End If
End Sub
I am encountering the problem specifically on the following line:
Dim binary(reader("document")) As Byte
It seems to think that binary is being passed an Integer. Is this something to do with the SQLReader? I'm not really sure at this point what the problem is.
Any help would be greatly appreciated.
Many Thanks,
Richard E Logan-Baker
*UPDATE*
I have since worked out the problem that I'm getting by changing the lines to:
Dim blob() As Byte
blob = reader.Item("document")
However, the PDF does not display inside firefox, and when I save the file (even though my DB is only 2MB~) it is quite happy at downloading over 40MB of data! Also, the file size reports as unknown. I am really stuck now.
*UPDATE*
I've now got the PDF to open in the browser, but there is no data being displayed and Adobe Acrobat says it has problems extracting the text/fonts from the file and that the PDF is broken somehow.
Here is my updated code now:
Protected Sub btnPDF_Click(sender As Object, e As EventArgs) Handles btnPDF.Click
' Request.QueryString["docid"].ToString();
Dim docuid As String = "ba32bf45-1b5c-451a-969c-290dc2cf9073"
'Connection and Parameters
Dim param As SqlParameter = Nothing
Dim conn As SqlConnection = New SqlConnection(
ConfigurationManager.ConnectionStrings("menu").ToString())
Dim cmd As New SqlCommand("sp_getdoc", conn)
cmd.CommandType = CommandType.StoredProcedure
param = New SqlParameter("#docuid", SqlDbType.NVarChar, 100)
param.Direction = ParameterDirection.Input
param.Value = docuid
cmd.Parameters.Add(param)
'Open connection and fetch the data with reader
conn.Open()
Dim reader As SqlDataReader =
cmd.ExecuteReader(CommandBehavior.CloseConnection)
If reader.HasRows Then
reader.Read()
'
Dim doctype As String = reader("doctype").ToString()
Dim docname As String = reader("docname").ToString()
'
Response.Buffer = False
Response.ClearHeaders()
Response.ContentType = doctype
Response.AddHeader("Content-Disposition",
"attachment; filename=" + docname)
'
'Code for streaming the object while writing
Const ChunkSize As Integer = 1024
Dim buffer() As Byte = New Byte(ChunkSize) {}
Dim blob() As Byte
blob = reader.Item("document")
Dim ms As New MemoryStream(blob)
Dim SizeToWrite As Integer = ChunkSize
For i As Integer = 0 To blob.GetUpperBound(0) - 1
If Not Response.IsClientConnected Then
Return
End If
If i + ChunkSize >= blob.Length Then
SizeToWrite = blob.Length - i
End If
Dim chunk(SizeToWrite) As Byte
ms.Read(chunk, 0, SizeToWrite)
Response.BinaryWrite(chunk)
Response.Flush()
i = i + ChunkSize
Next i
Response.Close()
End If
End Sub
I think your problem is coming from the way you are incrementing "i" inside the loop. After you increment it by the ChunkSize at the end of your For...Next statement, the "Next i" statement will increment it by 1 again. Try changing that line to:
i = i + ChunkSize - 1
Or alternatively you could add a "Step ChunkSize" at the end of the For statement and remove the line I'm referring to.

Resources