prostynick
prostynick

Reputation: 6219

Two-Way Communication Between HTML in .Net WebBrowser and WinForms application

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?

Upvotes: 1

Views: 2521

Answers (2)

prostynick
prostynick

Reputation: 6219

I found at least two solutions.

First, pretty obvious, is what Sheng Jiang suggested. You need to create a 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 used 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 the app exe. We still need interface IFoo if we want to pass objects from javascript to C#. And we need methods to create objects on the 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.

Upvotes: 1

Sheng Jiang 蒋晟
Sheng Jiang 蒋晟

Reputation: 15261

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.

Upvotes: 1

Related Questions