Options

Convert from System.IO.FileStream to InStream

wakestarwakestar Member Posts: 207
Hi there

I'm trying to load the FileStream of a file on the client with System.IO.File.OpenRead() into a InStream but I get the error:

Unable to convert from Runtime.NavDotNet to Nav.Runtime.NavInStream

FileStream := ClientFile.OpenRead(ClientFilePath);
InStr := FileStream;

I tried with different .NET Stream types and with COPYSTREAM but no luck so far... :-(
What am I missing here? Does anyone have a working example?

Best Answers

Answers

  • Options
    yukonyukon Member Posts: 361
    Hi,
    FileStream to MemoryStream(.Net) and then MemoryStream to Your Nav Stream.

    Regards
    Make Simple & Easy
  • Options
    wakestarwakestar Member Posts: 207
    Hi

    I tried that.. same error.

    Do you have a working example code?
  • Options
    yukonyukon Member Posts: 361
    Hi,
    Now I far from PC. I will update back to you if noon ans. Sorry for my this reply.

    Regards,
    Make Simple & Easy
  • Options
    wakestarwakestar Member Posts: 207
    no problem :wink:
  • Options
    mdPartnerNLmdPartnerNL Member Posts: 802
    Nice examples, what were you global variables?
  • Options
    yukonyukon Member Posts: 361
    Hi,

    Update with Global variables.

    Regards,
    Make Simple & Easy
  • Options
    mdPartnerNLmdPartnerNL Member Posts: 802
    Thx
  • Options
    wakestarwakestar Member Posts: 207
    edited 2016-01-28
    Hi yukon

    Thanks so far for the example!
    May i know why you need to pass FileStream to InStream.

    At the moment I'm playing around with Vjeko's DLL hell solution and try to reuse existing functions.

    If you look at the function InstallAssembly you'll notice that the first parameter is InStream.

    And in my case I'm implementing a new function which let's you pick an entire folder on the client and all of the *.dll files should be imported at once to the DotNet Assembly table. And I actually managed to get this working by uploading the files first to the service tier and then import them from there.
        FileMgt.UploadFileSilent(ClientFilePath,ServerFilePath);
        FileMgt.BLOBImportFromServerFile(TempBlob,ServerFilePath);
        TempBlob.Blob.CREATEINSTREAM(InStr);
        InstallDotNetAssembly(InStr,Asm,'');    
    

    BUT ... I then thought maybe I could use Streams to transfer from the client directly to the server without going through Upload and temporary folder. So in my case I would like to have all of the .NET assemblies defined as "RunOnClient=Yes" ...

    but now I get this:
    Microsoft Dynamics NAV

    This message is for C/AL programmers: Client/server communication, cannot serialize an instance of the following .NET Framework object: assembly Microsoft.Dynamics.Nav.Ncl, Version=7.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, type Microsoft.Dynamics.Nav.Runtime.NavBLOB+InternalStream.
    OK

    So that basically means that we cannot serialize this stuff and your example works as long as the file is already on the service tier... correct?
  • Options
    yukonyukon Member Posts: 361
    Hi,
    I haven't check Vjeko's post. So i cannot tell you what can be amend on your code base on your requirement. You cannot pass the Client Side Variable to Server side or Server Side Var to Client. You are trying to pass Client Side variable (RunOnClient=Yes) to Server side variable. This post is same as your error. https://community.dynamics.com/nav/f/34/t/186866

    Regards,
    Make Simple & Easy
  • Options
    wakestarwakestar Member Posts: 207
    Thanks for confirming that! Yes it's a bummer and I guess the solution is to use base64 strings. - Which is what I'll try next :-)
  • Options
    mdPartnerNLmdPartnerNL Member Posts: 802
    so why can't you just use the "..through Upload and temporary folder.." to get the file at the client location?
  • Options
    wakestarwakestar Member Posts: 207
    I could and it works. - But I'm trying to avoid the *files-pushing-around-between-temp-folders*
  • Options
    wakestarwakestar Member Posts: 207
    edited 2016-01-28
    Hi yukon,
    I like your code to the point where you have it in the dnetMemoryStreamServer.
    //dnetMemoryStreamServer := dnetMemoryStreamServer.MemoryStream(dnetMemoryStreamClient.GetBuffer); //Memory Stream Byte to make Server Memory Stream
    

    But I don't want to save the file on the server at all. It should go from MemoryStreamServer to directly into the InStream (BLOB-Field)


    btw. I appreciate your input!
  • Options
    yukonyukon Member Posts: 361
    wakestar wrote: »
    But I don't want to save the file on the server at all. It should go from MemoryStreamServer to directly into the InStream (BLOB-Field)

    I show you the code is how to pass Client Memory value to Server Memory if RunOnClient is different between two variable (Memory Stream). You can save to InStream(Blob-field) after you get MemoryStreamServer. For your requirement you may need to combine two example.
    //dnetMemoryStreamServer := dnetMemoryStreamServer.MemoryStream(dnetMemoryStreamClient.GetBuffer); //Memory Stream Byte to make Server Memory Stream
    

    I like to use above code because i can be reduce the variable (dnetArrayClient) and code. And then MemoryStream constructor allow me to do from byte.

    Regards,
    Make Simple & Easy
  • Options
    wakestarwakestar Member Posts: 207
    edited 2016-01-28
    Ah OK, I see what you mean.

    I'll have to do some testing and tuning but looks good so far.

    I like the solution because it's not doing any roundtrips through the temporary folders.

    BIG THANKS
  • Options
    mdPartnerNLmdPartnerNL Member Posts: 802
    edited 2016-01-29
    its a bit hard to understand for me...:) so in pseudo steps what you are trying to do:

    1.
    your opening a file on the client into memory

    2.
    and save it to a file on the server


    (but no use of temp files)
  • Options
    wakestarwakestar Member Posts: 207
    edited 2016-01-29
    Almost :-)

    1. correct

    2. not to file but to Temp.Blob field on a table.

    So in short: Get the file from the client and save it directly into some Blob field of a table without any temp files created anywhere ...

    The standard microsoft approach does round trips and pollutes the temporary folders before you have the file in your database. - Not a great solution IMHO.

  • Options
    mdPartnerNLmdPartnerNL Member Posts: 802
    ok, thx for clearing this up. If you can, please share the working code you used. Or publish in tips :smile:
  • Options
    wakestarwakestar Member Posts: 207
    as soon as I'm really sure what I'm doing ;-)
  • Options
    wakestarwakestar Member Posts: 207
    I did some testing and I ran into OutOfMemory-Exception when importing around 15 files each 10mb.
    I guess the problem is described here: http://stackoverflow.com/questions/13053739/when-is-getbuffer-on-memorystream-ever-useful

    But for importing a bunch of smaller files (dlls) I haven't seen any issues yet.

    The code is prototypical ... use it at own risk :-)
    https://gist.github.com/wakestar/4200f18e8a71584cb9b9
  • Options
    mdPartnerNLmdPartnerNL Member Posts: 802
    I was looking to this download http://mibuso.com/downloads/nav-object-renumbering-tool

    I thought the source was related and maybe of use..
Sign In or Register to comment.