none
Pass arrays from JavaScript to C# via WebBrowser object

    Question

  • Hi,

     

    I have a WebBrowser object in WPF and I am using its ObjectForScripting property to handle communication from the website to the C# application.

     

    I have used this before with simple communication but now I want to do some more complex stuff. In essence I want to tell the application that an object has changed and pass all changed properties in an array. Preferably as an associated array. As an example let's say that my car has been repainted and got a new engine. So inside Javascript I do this:

     

    var newProperties = new Array();
    newProperties["color"] = "cyan";
    newProperties["top_speed"] = "200 mph";
    
    // UpdateObject(object type, object id, new properties)
    window.external.UpdateObject("car", 1337, newProperties);
    

     

     

    Now, inside the C# code I have something like:

     

    [ComVisibleAttribute(true)]
    public class MyBrowserInterface
    {
        public void UpdateObject(string type, int id, ???)
        {
            // find the object (my leet car) and
            // update its properties accordingly)
        }
    }
    

     

    Is this even possible or am I restricted to using arguments of basic types like string or integers?

     

    Thanks!


    Stoffi Music Player
    A simple approach to music
    www.stoffiplayer.com - blog.stoffiplayer.com - dev.stoffiplayer.com

    A free and open music application developed in C# using Windows Presentation Foundation.
    Saturday, October 22, 2011 1:47 PM

Answers

  • > pass all changed properties in an array
       

    in JavaScript, objects and arrays are almost identical to each other.
    so we can simply use object+properties and dynamic
     
    <Window x:Class="WpfApplication1.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            Width="800" Height="400"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
        <Grid>
            <WebBrowser x:Name="wb" />
        </Grid>
    </Window>
    
    
    using System.Runtime.InteropServices;
    using System.Windows;
    
    namespace WpfApplication1
    {
        public partial class MainWindow : Window
        {
            public MainWindow()
            {
                InitializeComponent();
                wb.Navigated += (s, e) => wb.ObjectForScripting = new Proxy();
                wb.NavigateToString(@"
                <html>
                <head>
                    <script language='javascript'>
                    function test()
                    {
                        var arr = {color:'cyan', top_speed: '200 mph'};
                        alert(window.external.getname(arr));
                    }
                    </script>
                </head>
                <body>hello <button onclick='test()'>test</button></body>
                </html>");
            }
        }
    
        [ComVisible(true)]
        public class Proxy
        {
            public string GetName(dynamic d)
            {
                var color = (string)d.color;
                var speed = (string)d.top_speed;
                return color + " " + speed;
            }
        }
    }
    


    • Proposed as answer by Malobukv Saturday, October 22, 2011 10:45 PM
    • Marked as answer by Ephracis Sunday, October 23, 2011 12:50 AM
    Saturday, October 22, 2011 10:44 PM

All replies

  • Try to specify class wich have properties same as keys in your associative array
    Saturday, October 22, 2011 2:21 PM
  • > pass all changed properties in an array
       

    in JavaScript, objects and arrays are almost identical to each other.
    so we can simply use object+properties and dynamic
     
    <Window x:Class="WpfApplication1.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            Width="800" Height="400"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
        <Grid>
            <WebBrowser x:Name="wb" />
        </Grid>
    </Window>
    
    
    using System.Runtime.InteropServices;
    using System.Windows;
    
    namespace WpfApplication1
    {
        public partial class MainWindow : Window
        {
            public MainWindow()
            {
                InitializeComponent();
                wb.Navigated += (s, e) => wb.ObjectForScripting = new Proxy();
                wb.NavigateToString(@"
                <html>
                <head>
                    <script language='javascript'>
                    function test()
                    {
                        var arr = {color:'cyan', top_speed: '200 mph'};
                        alert(window.external.getname(arr));
                    }
                    </script>
                </head>
                <body>hello <button onclick='test()'>test</button></body>
                </html>");
            }
        }
    
        [ComVisible(true)]
        public class Proxy
        {
            public string GetName(dynamic d)
            {
                var color = (string)d.color;
                var speed = (string)d.top_speed;
                return color + " " + speed;
            }
        }
    }
    


    • Proposed as answer by Malobukv Saturday, October 22, 2011 10:45 PM
    • Marked as answer by Ephracis Sunday, October 23, 2011 12:50 AM
    Saturday, October 22, 2011 10:44 PM
  • Oh, it was the "dynamic" part that I was looking for. Thanks!
    Stoffi Music Player
    A simple approach to music
    www.stoffiplayer.com - blog.stoffiplayer.com - dev.stoffiplayer.com

    A free and open music application developed in C# using Windows Presentation Foundation.
    Sunday, October 23, 2011 12:50 AM
  • Hi,

    I was trying this approuch but always get the following error:


    Microsoft.CSharp.RuntimeBinder.RuntimeBinderException was unhandled by user code
      HResult=-2146233088
      Message=Não é possível converter implicitamente tipo 'System.__ComObject' em 'string'
      Source=Anonymously Hosted DynamicMethods Assembly
      StackTrace:
           em CallSite.Target(Closure , CallSite , Object )
           em System.Dynamic.UpdateDelegates.UpdateAndExecute1[T0,TRet](CallSite site, T0 arg0)
           em GoogleInterop.GoogleProxy.SetReverseGeocode(Object GeoResult) na C:\dev\trash\Monitor2012\GoogleInterop\GoogleProxy.cs:linha 21
      InnerException:

    What am I doing wrong?

    Thanks

    Tuesday, April 10, 2012 11:53 PM
  • > I was trying this approuch but always get the following error: Microsoft.CSharp.RuntimeBinder.RuntimeBinderException
     
     
    what version of Visual Studio are you using?
    do you use exactly same code  provided above? if no, then please provide your code to repro the issue.
      
      

    Wednesday, April 11, 2012 12:30 AM
  • Hi,

    I tried the code above and it worked. Then I figured it out that I was missing a cast. Now it works fine.

    thanks

    Wednesday, April 11, 2012 1:32 PM