ComVisible class with a non ComVisible baseclass

In my previous post I was talking about using the WebBrowserControl in a WinForms application. I demonstrated how you can communicate to the JavaScript of the webpage loaded in the WebBrowserControl in your C# code and vice versa.

While using this code I ran into a problem myself. The Form which was made ComVisible had a baseclass which was not ComVisible. When I ran my code I had this great exception when calling the C# code from JavaScript:

NonComVisibleBaseClass was detected
A QueryInterface call was made requesting the default IDispatch interface of COM visible managed class ‘JYAG.WebControlInWinforms.GeekBrowser’. However since this class does not have an explicit default interface and derives from non COM visible class ‘JYAG.WebControlInWinforms.GeekBasePage’, the QueryInterface call will fail. This is done to prevent the non COM visible base class from being constrained by the COM versioning rules.

The simplest solution  is to make the baseclass ComVisible just as well. But in my case it was not an option to expose the baseclass to Com-components. So what can we do to make this work without having to make the baseclass ComVisible.  There are three easy steps to take to accomplish this.

Step 1 – Define a interface with the methods you’d like to call from JavaScript

First we define a Interface and put all the methods we want to reach through JavaScript in there. We make the interface ComVisible. I took the test-project of my previous post and added a IMapControlInteractable interface which contains just one method.

    [ComVisible(true)]
    public interface IMapControlInteractable
    {
        void ActivateControls();
    }

Step 2 – Give the ComVisible class the ClassInterfaceAttribute

To use the Interface in combination with the ComVisible attribute and effectivly let the JavaScript communicate with the C# code we give the class the ClassInterfaceAttribute and specify the type at ‘none’.

    [ClassInterface(ClassInterfaceType.None)]

Step 3 – Implement the Interface

The last thing we must do is implement the Interface. If we do so the code my look something like this.

    //Make class visible for COM so we can set the ObjectForScripting
    //Specify ClassInterfaceType.None to use the ComVisible Interface
    [ComVisible(true)]
    [ClassInterface(ClassInterfaceType.None)]
    public partial class GeekBrowser : GeekBasePage, IMapControlInteractable
    {

That’s all there is to it. Now our exception at runtime disappears and our code works. And our baseclass is not ComVisible.

Download this code in the adjusted test project.

For comments, questions  or suggestions contact me or leave a comment below.

    • ahem
    • May 20th, 2011

    Excellent!!

  1. Thanks for share this,MSDN sucks

    • Michael
    • January 14th, 2012

    Thanks,
    I used it for a different case and it worked too!

  1. No trackbacks yet.