views:

59

answers:

2

When using WebBrowser control I would like to pass an object from javascript code to C#.

Solution is known - using ObjectForScripting property of WebBrowser and invoking methods from javascript code using window.external.

I know how to do that, but I would like to create object with given type in javascript and pass it to C# without using object or dynamic. Example:

I would like to call from JS this method in C#:

public void Test(Foo foo)
{
    //do something
}

Where Foo is:

[ComVisible(true)]
public class Foo
{
    public string Bar;
}

I know how to call those methods:

public void Test2(object foo)
{
    //do something
}

public void Test3(dynamic foo)
{
    //do something
}

but I would like to use the first one - Test(Foo foo)

What should I do to make it possible to pass object of class Foo from JS to C# or how to cast JS object on the fly to C# Foo object?

+1  A: 

The type system is weaker in jscript, so you can't have early binding classes. I suggest you to make your class automatable and register your project's type library for late binding so it can be called in jscript via new ActiveXObject.

Sheng Jiang 蒋晟
+1  A: 

I found at least two solutions.

First, pretty obvious, is what Sheng Jiang suggested. To do that you (I?) need to create separate class library with those types:

[ComVisible(true)]
public interface IFoo
{
    string Bar { get; set; }
}

[ComVisible(true)]
public class Foo : IFoo
{
    public string Bar { get; set; }
}

This type library must be registered (Project/Properties/Build/Register for COM interop). Those types, especially interfaces, should be use in methods in exe which has the WebBrowser control. For example:

public string Bar(IFoo foo)
{
    return foo.Bar;
}

public IFoo Bar2()
{
    return new Foo() { Bar = "asdf" };
}

Now we can use those types in javascript:

var foo = new ActiveXObject("ClassLibrary1.Foo");
foo.Bar = "qwer";
alert(external.Bar(x));
var fooFromExternal = external.Bar2();
alert(fooFromExternal);
alert(external.Bar(fooFromExternal));

Unfortunately the class library has to be registered and you will get an ActiveX warning from IE.

Second solution is to not create class library. Instead of leaving those types in app exe. We still need interface IFoo if we want to pass objects from javascript to C#. And we need methods to create objects at C# side for javascript:

public IFoo CreateFoo()
{
    return new Foo() { Bar = "asdf" };
}

public string Bar(IFoo foo)
{
    return foo.Bar;
}

Javascript usage:

var foo = external.CreateFoo();
alert(foo.Bar);
foo.Bar = "qwer";
alert(external.Bar(foo));

We don't need to register anything for COM interop and there will be no ActiveX warning from IE.

prostynick