locked
How to Pass JS Callback Function to C# WinRT Component RRS feed

  • Question

  • Hi Guys,

    I am developing the C# WinRT Component DLL (based on C#-SQLite, https://code.google.com/p/csharp-sqlite/) that could be used by HTML5/Javascript based Windows Store Apps,

    Am currently stuck on passing a javascript callback function to WinRT Component for a callback for processing each row one by one from the component,

    Do let me know if you have any sample or something to help me out in this,

    Thanks in advance for your help,

    Best Regards,
    Jay

    Founder, JKL Technologies.


    Saturday, April 27, 2013 3:23 PM

All replies

  • Jay,

    What you'll actually want to do is rethink your architecture here. Async operations in WinJS are completed using Promises in order to avoid the ugly pyramiding of chained callbacks. Therefore what you probably want to do is have your WinRT component return an async operation (see here for details: http://msdn.microsoft.com/en-us/library/windows/apps/br211867.aspx) so that you can call your callback function, or do your post-operational processing in the returned promise object's .then or .done functions.

    Therefore if you were envisioning something like the below for your JavaScript...

    function callWinRT(callback) {
        WinRTComponent.processAsync(callback);
    }

    ...it *could* end up looking more like this:

    function callWinRT(callback) {
        WinRTComponent.processAsync().then(callback);
    }

    ...but more ideally you'd just return the promise itself and call .then or .done directly in the calling function:

    function callWinRT() { return WinRTComponent.processAsync(); }

    ...

    callWinRT.then(function onCompletedCallback(e) { ... });

    Let me know if I can clarify further!

    Sunday, April 28, 2013 1:02 AM
  • Hi,

    Thanks for your response,

    Yes, your answer was helpful. In our design we are already following the same principle of using AsyncOperations and Promises. In my RT Component I am accessing an embedded database file. So for operations such as OpenDatabase, ExecuteUpdate, ExecuteQuery (with one Row, one column results),  are all written with the usage as mentioned by you,

    Now, for processing sql queries which return multiple rows, we have to,

    1. Copy the Entire ResultSet to an Windows Runtime compatible object (like PropertySet) or

    2. We could implement a call back to process each and every row as and when they are read from the database.

    Now, the first option of copying the resultset is useful only when there are only few rows to be returned. As my resultset lists a lot of results for processing, I would like a callback function implemented in the javascript such that I can process each and every row as they are read.

    As part of the C#-SQLite RT Component such processing is necessary for my App.

    Now, this wrapper has been successfully implemented in the C++ RT Component which directly accesses SQLite C library. C#-SQLite is a C# equivalent of the same library, hence I am figuring out a way to implement a C# RT Component wrapper for my Javascript App.

    For reference,

    1. C++ SQLite RT Component Library (https://github.com/doo/SQLite3-WinRT)

    2. C#-SQLite - https://code.google.com/p/csharp-sqlite/ (this has only class libraries for C#-SQLite, compatible with RT but only for C# Windows 8 Apps)

    Thanks in advance for your guidance on how to accomplish this,

    Best Regards,

    Jay

    Monday, April 29, 2013 9:13 AM
  • You should not mix JS and a managed language because of the runtime overhead, as by MSFT recommendations.

    You could use https://github.com/doo/SQLite3-WinRT for JS apps out of the box.

    Monday, April 29, 2013 1:14 PM
  • Hi,

    I know SQLite3-WinRT, I have used it initially while developing this app, but this package doesn't offer password based encryption for the Database. Hence, I switched to C#-SQLite,

    I will be glad to switch back if someone has written a simple encryption (blowfish or AES) for SQLite-WinRT which is compatible to be a WinRT Component DLL. 

    P.S: I tried integrating SQLCipher Community Project into SQLite-WinRT for the same purpose, but it needed openssl to be included which is not compatible with Windows Runtime. 

    Thanks for the suggestion though, 

    I still need to work this out, can you guide me what I am doing wrong, I can attach the sample project if needed, HELP!

    Additional Code information - My Javascript Code:

    My.WinRT.Component.Object.processEachRowASyc(query, arguments, function(row) {
        /* Row specific processing */
    }).then(function(result) {
        /* Process after Entire Row processing is Complete */
    });

    My C# Code:

    namespace mydb
    {
        public void delegate MyJSCallback(string msg);
        public class Database {
    
            public static IAsyncOperation<Database> OpenDB(string dbFile)
            {
               /* Open DB */
            }
    
            public IAsyncOperation<Database> ProcessEachRowASync(string sql,[ReadOnlyArray()] object[] arg, MyJSCallback myJSCallback)
            {
                return Task<IDataReader>.Run(() =>
                {
                /* Query Processing */
                IDataReader reader = cmd.ExecuteReader();
                while (reader.Read())
                {
                   RowObject toRet = reader.GetMyRowObject();
                   myJSCallback(toRet);
                }
                return this;
    
                }).AsAsyncOperation();
            }
        }
    
    }

    The error faced,

    InvalidCastException Trying to TypeCast the Javascript Callback function to Delegate

    Best Regards,

    Jay

    Monday, April 29, 2013 2:37 PM
  • What's password based encryption doing in your scenario? Encrypting the whole database? Or single tables, or columns?

    Don't know C# but I would guess, like in C++ you would have to get a dispatcher to call back to JS. Which you should not do in the first place - mixing JS and C#, because C# drags in a lot of VM code on top of IE 10 JS engine. Its not recommended and will increase the memory footprint of your app which in turn increases the chance of your app being terminated when in background and the system needs more memory.

    Monday, April 29, 2013 3:00 PM
  • I use this to encrypt the database which is read-only and bundled with the App. I know we should not be mixing JS with C# but a decent database is only available with C#/C++/C implementation, which can scale well for bulk of read-only data to be stored.

    Believe writing the app with a database back-end will help us in the long-run. So would like a sample for writing a dispatcher if possible,

    A Sample App project to see what I am trying to achieve is provided in the following URL, http://sdrv.ms/18ff3Hl

    Make sure you turn on Debug Managed Code to see the error bugging me.

    Thanks in advance for your help,

    Best Regards,

    Jay



    Monday, April 29, 2013 3:31 PM
  • When I removed the IASyncOperation from the function, the js callback worked without issue.

    There seems to be a problem because I am having a blocking callback function sent as the parameter I believe. Can any one clarify how it can work with IASyncOperation present in my function.

    Regards,

    Jay

    Saturday, May 4, 2013 1:32 PM
  • I don't think that the C# implementation of SQLLite is going to pass store certification.  That's why they wrote a WinRT version.

    Matt Small - Microsoft Escalation Engineer - Forum Moderator
    If my reply answers your question, please mark this post as answered.

    NOTE: If I ask for code, please provide something that I can drop directly into a project and run (including XAML), or an actual application project. I'm trying to help a lot of people, so I don't have time to figure out weird snippets with undefined objects and unknown namespaces.

    Tuesday, May 7, 2013 4:11 PM
    Moderator