Results 1 to 9 of 9

Thread: [RESOLVED] How to transmit a CLASS to another app (serialize?)

  1. #1

    Thread Starter
    MS SQL Powerposter szlamany's Avatar
    Join Date
    Mar 2004
    Location
    Connecticut
    Posts
    18,263

    Resolved [RESOLVED] How to transmit a CLASS to another app (serialize?)

    I've got this class

    Code:
    Public Class FSObject
    
        Private _FileString As String
        Public Property FileString As String
            Get
                Return _FileString
            End Get
            Set(ByVal value As String)
                _FileString = value
            End Set
        End Property
    
        Private _FileId As String
        Public Property FileId As String
            Get
                Return _FileId
            End Get
            Set(ByVal value As String)
                _FileId = value
            End Set
        End Property
    
        Private _FileIndex As String
        Public Property FileIndex As String
            Get
                Return _FileIndex
            End Get
            Set(ByVal value As String)
                _FileIndex = value
            End Set
        End Property
    And I just added this FILECONTENT property
    Code:
        Private _FileContent As Byte()
        Public Property FileContent As Byte()
            Get
                Return _FileContent
            End Get
            Set(ByVal value As Byte())
                ReDim _FileContent(value.Length)
                _filecontent = value
            End Set
        End Property
    End Class
    Important thing to note is the FILECONTENT property - it will be a huge byte array of the file contents.

    I create the object like this

    Code:
    For Each file As String In files
        Dim MyThread As Thread ' simple new thread
        Dim newFS As FSObject = New FSObject() 'new FSObject which is a file object I made up
                    ' used because i needed to keep the name and index matched so the callback function had something to work with
    
        newFS.FileString = file 'this is just the name of it
        newFS.FileIndex = FileList.Count 'this is the objects position in the array, so the callback function knows where it is
    
        Using fs As New FileStream(file, FileMode.Open, FileAccess.Read, FileShare.Read)
            length = fs.Length
            Dim buffer(length) As Byte
            length = fs.Read(buffer, 0, length)
            newFS.FileContent = buffer
        End Using
    
        FileList.Add(newFS) 'just adding NewFS to file List so work function knows about it and the draw function knows about it
    
        MyThread = New Thread(AddressOf CallQuery) 'Standard Thread Stuff, Giving it the address of a function which is the function that calls the HTTPApp
        MyThread.Start(newFS) 'And starting the thread. The newFS is an object the thread will pass to the called function - can only be one argument
    
    Next
    Now in the CALLQUERY function I used to just send the filename - now I want to send the entire class object - since it has the file contents - to the receiving app

    Code:
        Private Sub CallQuery(ByVal FSOb As FSObject)
            Dim prefixes() As String = {"http://localhost:8080/HttpListener/"}
            Dim request As WebRequest = WebRequest.Create(prefixes(0))
            request.Method = "POST"
            request.ContentType = "application/x-www-form-urlencoded"
            Dim bytes() As Byte
            Dim sendString As String = FSOb.FileString + "|" + FSOb.FileIndex
            bytes = System.Text.Encoding.ASCII.GetBytes(sendString)
            request.ContentLength = bytes.Length
    
            Try
                Dim outputstream As Stream = request.GetRequestStream()
                outputstream.Write(bytes, 0, bytes.Length)
    
                Dim response As WebResponse = request.GetResponse()
                Dim datastream As Stream = response.GetResponseStream()
                Dim reader As New StreamReader(datastream)
                Dim responseFromServer As String = reader.ReadToEnd()
    
                outputstream.Close()
                reader.Close()
                response.Close()
    
                AnswerBack(responseFromServer) 'calling the callback function with the response from the server
                'As far as i understand this calls the AnswerBack function with the InvokeRequired set true and nothing else fance or weird.
    
            Catch ex As Exception
                MessageBox.Show(ex.Message, "GetRequestStream")
            End Try
        End Sub
    Instead of sending SENDSTRING - I would like to send the entire FSOb object.

    Can I serialize this object and then make it materialize again in the receiving app??

    *** Read the sticky in the DB forum about how to get your question answered quickly!! ***

    Please remember to rate posts! Rate any post you find helpful - even in old threads! Use the link to the left - "Rate this Post".

    Some Informative Links:
    [ SQL Rules to Live By ] [ Reserved SQL keywords ] [ When to use INDEX HINTS! ] [ Passing Multi-item Parameters to STORED PROCEDURES ]
    [ Solution to non-domain Windows Authentication ] [ Crazy things we do to shrink log files ] [ SQL 2005 Features ] [ Loading Pictures from DB ]

    MS MVP 2006, 2007, 2008

  2. #2
    Junior Member phytax's Avatar
    Join Date
    Feb 2012
    Posts
    19

    Re: How to transmit a CLASS to another app (serialize?)

    Sure you can :-)

    here is a link which is a good intro:

    http://vbnetsample.blogspot.com/2007...s-to-file.html
    May the SOURCE be with you +---

    Rate if this was helpful

    http://INTRALUX.de

  3. #3

    Thread Starter
    MS SQL Powerposter szlamany's Avatar
    Join Date
    Mar 2004
    Location
    Connecticut
    Posts
    18,263

    Re: How to transmit a CLASS to another app (serialize?)

    Wow - that was going so well. I serialized the object - all looked good in the "sending" app.

    And the receiving app got the data - but it's unhappy that it doesn't know about the "program that sent it"

    I added the same CLASS to the receiving app (HttpApp.exe)

    PicDragDrop.exe is the sending app. See the image below.
    Attached Images Attached Images  

    *** Read the sticky in the DB forum about how to get your question answered quickly!! ***

    Please remember to rate posts! Rate any post you find helpful - even in old threads! Use the link to the left - "Rate this Post".

    Some Informative Links:
    [ SQL Rules to Live By ] [ Reserved SQL keywords ] [ When to use INDEX HINTS! ] [ Passing Multi-item Parameters to STORED PROCEDURES ]
    [ Solution to non-domain Windows Authentication ] [ Crazy things we do to shrink log files ] [ SQL 2005 Features ] [ Loading Pictures from DB ]

    MS MVP 2006, 2007, 2008

  4. #4
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    40,104

    Re: How to transmit a CLASS to another app (serialize?)

    That's not sufficient, and it won't work in this case as it stands. The problem is that there is more serialized into that thing than just the class information. The Assembly information is in there, and it can't be deserialized by any other assembly. Therefore, you would serialize with one program and find that you couldn't deserialize with another program.

    I had this issue for some robot code because the brain was distributed as different programs on different computers. The messages flying (via UDP) between the different apps that made up the brain contained some complicated data. Therefore, I wanted to be able to transmit serialized classes, but I couldn't do it because what was serialized from one brain app couldn't be deserialized by a different part of the brain.

    The solution was to build a class library that contains the serialization and deserialization code, along with the classes that I wanted to send. Then any app could reference this dll and do whatever serialization and deserialization was needed, because it was the dll assemblage information that was being included into the serialization package. Of course, having all the classes declared in the same class library was just a convenience for that situation, because all brain apps would need to know about those types so that they could deal with the data. The same might be true for you, or you might find some other arrangement of definitions in class libraries that will work, but you can't simply serialize in one app and deserialize in a different one because of the assemblage information contained in the serialized bytes.

    EDIT: Crossed up your post, but this still answers the question fairly well.
    My usual boring signature: Nothing

  5. #5

    Thread Starter
    MS SQL Powerposter szlamany's Avatar
    Join Date
    Mar 2004
    Location
    Connecticut
    Posts
    18,263

    Re: How to transmit a CLASS to another app (serialize?)

    [edit] I see we cross posted - were you suggesting this wasn't going to work even before I got the exact error you described??? [/edit]

    Ok - so I would need to partition this stuff into a class in and of itself - with the code to do the serialization and deserialization within that class - returning the FSOb object out to main code? And taking the streams (either file or request.inputstream) as properties to work on?

    And then make that a dll and have both app's reference it?

    Seems simple enough - but before I go hog wild here.

    Is the serialization adding a lot of BYTES to the size of this transmission? I could certainly transmit two POST's to the receiving app - one with the filename as TEXT and one with the FILECONTENTS as a stream.

    Am I going overboard for no good reason here?

    *** Read the sticky in the DB forum about how to get your question answered quickly!! ***

    Please remember to rate posts! Rate any post you find helpful - even in old threads! Use the link to the left - "Rate this Post".

    Some Informative Links:
    [ SQL Rules to Live By ] [ Reserved SQL keywords ] [ When to use INDEX HINTS! ] [ Passing Multi-item Parameters to STORED PROCEDURES ]
    [ Solution to non-domain Windows Authentication ] [ Crazy things we do to shrink log files ] [ SQL 2005 Features ] [ Loading Pictures from DB ]

    MS MVP 2006, 2007, 2008

  6. #6
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    40,104

    Re: How to transmit a CLASS to another app (serialize?)

    Yeah, I think that would be going overboard. I forget the exact size of that extra stuff, but I did go look at it when I was working on that robot code. There isn't much there. I was concerned because UDP packets have to be fairly small, and I was afraid that some of my classes were getting too large, so I looked at the packets byte by byte prior to deserialization. While I forget the size of that extra stuff, I seem to remember that it was a matter of one or two dozen bytes, or so. Trivial, in any case.

    EDIT: Oh, and I should add that my last post was written without seeing the post where you got that exact error.
    My usual boring signature: Nothing

  7. #7

    Thread Starter
    MS SQL Powerposter szlamany's Avatar
    Join Date
    Mar 2004
    Location
    Connecticut
    Posts
    18,263

    Re: How to transmit a CLASS to another app (serialize?)

    @shaggy_hiker - just to clarify you think IT IS A GOOD IDEA to serialize this CLASS for transmission as opposed to doing a double POST of filename and then file contents??

    *** Read the sticky in the DB forum about how to get your question answered quickly!! ***

    Please remember to rate posts! Rate any post you find helpful - even in old threads! Use the link to the left - "Rate this Post".

    Some Informative Links:
    [ SQL Rules to Live By ] [ Reserved SQL keywords ] [ When to use INDEX HINTS! ] [ Passing Multi-item Parameters to STORED PROCEDURES ]
    [ Solution to non-domain Windows Authentication ] [ Crazy things we do to shrink log files ] [ SQL 2005 Features ] [ Loading Pictures from DB ]

    MS MVP 2006, 2007, 2008

  8. #8
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    40,104

    Re: How to transmit a CLASS to another app (serialize?)

    The addition of those few bytes is trivial. Whether it is a good idea in your case, I can't quite say. The serialization in a dll technique works, and the total size may well be lower than what you would get with two posts. Of course, it does mean creating a dll and referencing it on both sides. Therefore, it is a transmission technique that requires shared knowledge between the two apps (the contents of the dll is available to both, so you can't very well change one without changing the other). If that is a price you are willing to pay, then the size of the serialized packet will probably be smaller and the serialization/deserialization faster, than any alternative.
    My usual boring signature: Nothing

  9. #9

    Thread Starter
    MS SQL Powerposter szlamany's Avatar
    Join Date
    Mar 2004
    Location
    Connecticut
    Posts
    18,263

    Re: How to transmit a CLASS to another app (serialize?)

    Thank you so much - this has worked out perfectly.

    Created this as a class library project - my original class for holding the data

    Code:
    <System.Serializable()> _
    Public Class FSObject
    
        ' Empty constructor required for serialization.
        Public Sub New()
        End Sub
    
        Private _FileString As String
        Public Property FileString As String
            Get
                Return _FileString
            End Get
            Set(ByVal value As String)
                _FileString = value
            End Set
        End Property
    
        Private _FileId As String
        Public Property FileId As String
            Get
                Return _FileId
            End Get
            Set(ByVal value As String)
                _FileId = value
            End Set
        End Property
    
        Private _FileIndex As String
        Public Property FileIndex As String
            Get
                Return _FileIndex
            End Get
            Set(ByVal value As String)
                _FileIndex = value
            End Set
        End Property
    
        Private _FileContent As Byte()
        Public Property FileContent As Byte()
            Get
                Return _FileContent
            End Get
            Set(ByVal value As Byte())
                ReDim _FileContent(value.Length)
                _FileContent = value
            End Set
        End Property
    End Class
    And a new class within the class library to do the serialization/deserialization

    Code:
    Imports System.IO
    Imports System.Runtime.Serialization.Formatters.Binary
    
    Public Class Class2
    
        Public Sub Serialize(ByRef FSOb As FSObject, ByRef ms As MemoryStream)
            Dim bf As New BinaryFormatter()
            bf.Serialize(ms, FSOb)
        End Sub
    
        Public Sub Deserialize(ByRef FSOb As FSObject, ByRef st As Stream)
            Dim bf As New BinaryFormatter()
            FSOb = bf.Deserialize(st)
        End Sub
    
    End Class
    Compile that into a DLL and referenced it in both the SENDING and RECEIVING apps

    The sending app CallQuery function now looks like this

    Code:
        Private Sub CallQuery(ByVal FSOb As FSObject)
            Dim prefixes() As String = {"http://localhost:8080/HttpListener/"}
            Dim request As WebRequest = WebRequest.Create(prefixes(0))
    
            request.Method = "POST"
            request.ContentType = "application/x-www-form-urlencoded"
    
            Dim ms As New MemoryStream()
    
            Dim cl2 As New Class2
            cl2.Serialize(FSOb, ms)
    
            request.ContentLength = ms.Length
    
            Try
                Dim outputstream As Stream = request.GetRequestStream()
    
                'outputstream.Write(bytes, 0, bytes.Length)
                outputstream.Write(ms.ToArray, 0, ms.Length)
    
                Dim response As WebResponse = request.GetResponse()
                Dim datastream As Stream = response.GetResponseStream()
                Dim reader As New StreamReader(datastream)
                Dim responseFromServer As String = reader.ReadToEnd()
    
                outputstream.Close()
                reader.Close()
                response.Close()
    
                AnswerBack(responseFromServer) 'calling the callback function with the response from the server
                'As far as i understand this calls the AnswerBack function with the InvokeRequired set true and nothing else fance or weird.
    
            Catch ex As Exception
                MessageBox.Show(ex.Message, "GetRequestStream")
            End Try
        End Sub
    And the receiving app does this to get the data back out

    Code:
        Private Sub GetContextCallBack(ByVal result As IAsyncResult)
            'Dim listener As HttpListener = CType(result.AsyncState, HttpListener)
            m_asyncCount += 1
            Dim acHold As Integer = m_asyncCount
            Console.WriteLine("In Callback with " & m_asyncCount.ToString & "...")
            If m_listener.IsListening Then
                Dim context As HttpListenerContext = m_listener.EndGetContext(result)
    
                m_listener.BeginGetContext(New AsyncCallback(AddressOf GetContextCallBack), Nothing)
    
                Dim request As HttpListenerRequest = context.Request
    
                Dim response As HttpListenerResponse = Nothing
                Try
                    Dim requestContext = ""
                    Dim returnString = ""
                    Dim blnPost As Boolean = False
                    If context.Request.HttpMethod = "POST" Then
                        blnPost = True
                        Dim inputstream As Stream = context.Request.InputStream()
                        Dim cl2 As New Class2
                        Dim FSOb As New FSObject
                        cl2.Deserialize(FSOb, inputstream)
                        'returnString = Mid(requestContext, InStr(requestContext, "|") + 1)
                        returnString = FSOb.FileIndex.ToString
                        Using fs As New FileStream("D:\ACS Desktop\Doc Management\testcopy.doc", FileMode.Create, FileAccess.ReadWrite, FileShare.None)
                            fs.Write(FSOb.FileContent, 0, FSOb.FileContent.Length)
                        End Using
    I even created a TESTCOPY.DOC file with the STREAM to make sure I could open the document in WORD - worked exactly as I hoped.

    I can't even believe that I just sent a WORD document - serialized with a bunch of metadata - through an HTTP post and re-created it as a WORD document on the receiving side!

    It's like I just built a Star Trek transporter!

    This forum is GREAT!!!!
    Last edited by szlamany; Feb 21st, 2012 at 05:44 PM.

    *** Read the sticky in the DB forum about how to get your question answered quickly!! ***

    Please remember to rate posts! Rate any post you find helpful - even in old threads! Use the link to the left - "Rate this Post".

    Some Informative Links:
    [ SQL Rules to Live By ] [ Reserved SQL keywords ] [ When to use INDEX HINTS! ] [ Passing Multi-item Parameters to STORED PROCEDURES ]
    [ Solution to non-domain Windows Authentication ] [ Crazy things we do to shrink log files ] [ SQL 2005 Features ] [ Loading Pictures from DB ]

    MS MVP 2006, 2007, 2008

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width