none
Catch events in javascript from .NET usercontrol works in C# but not in VB.NET

    Question

  • Hello all,

    I've created a .NET usercontrol and embedded it in an HTML page using the implementation found here

     

    http://support.microsoft.com/default.aspx?scid=kb;en-us;305624

    The Control Library was coded in VB.NET 2005.

    I can access my properties and methods from javascript with no problem.  I tried to raise events in my UserControl and catch them in the HTML with javascript but I couldn't get it to work.  Here are some methods I tried.

    <script FOR="uc1" EVENT="MyEvent">
    alert("event fired");
    </script>

    as well as

    I even read that VBScript "automagically" handles it by letting you define a script like this

    Sub ObjectName_EventName

    End Sub.

    This didn't work.  So after digging around I found many tutorials (all for C#) that helped me to understand that I had the COM-interop messed up.  So I wrote an example library from the following tutorial.

    http://www.cisco-cert.com/dotnet_general/574541-How-to-fire-Javascript-events-from-a--NET-winforms-user-control-back-to-Javascript-in-IE

    Here is my code.

    using System;

    using System.Collections.Generic;

    using System.ComponentModel;

    using System.Drawing;

    using System.Data;

    using System.Text;

    using System.Windows.Forms;

    // required for COM interoperability features

    using System.Runtime.InteropServices;

    // exposes events to the outside world through COM

    [assembly: ClassInterface(ClassInterfaceType.AutoDual)]

    namespace EventTestLib

    {

    // establish which public variables will be available through COM

    public interface ImyControlCOMIncoming {

    string MyData { get; set; }

    }

    // interface for the Event - the guid is a random number (you can

    // write code to generate it)

    // the DispId a number of your own choosing - the typical format is

    // 0x6002000n (each event

    // you expose will need it's own DispId)

    [ComVisible(true)]

    [Guid("8D0F8BF7-4E5D-4549-82C4-B6E1E8FCA0EA")]

    [InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]

    public interface ImyControlCOMEvents {

    [DispId(0x60020000)]

    void MyEvent();

    }

    // Control class, implementing the required interfaces

    [ComVisible(true)]

    [ClassInterface(ClassInterfaceType.None),

    ComSourceInterfaces(typeof(ImyControlCOMEvents))]

    [GuidAttribute("3D3D5023-AA90-47a7-B135-785EDFD03AF9")]

    public partial class myControl : UserControl, ImyControlCOMIncoming

    {

    // delegate and event declaration

    public delegate void MyEventHandler();

    public event MyEventHandler MyEvent;

     

    // when called within the control, DoMyEvent raises the event

    protected void DoMyEvent()

    {

    // only raise if the event is registered against something

    if (MyEvent != null)

    {

    MyEvent();

    }

    }

    public myControl()

    {

    InitializeComponent();

    }

    // button click

    private void MyButton_Click(Object sender, EventArgs e)

    {

    }

    // public property

    private string _MyData;

    public string MyData

    {

    get { return _MyData; }

    set { _MyData = value; }

    }

    private void btnFireEvent_Click(object sender, EventArgs e)

    {

    // call the event

    DoMyEvent();

    }

    }

    }

    And just as the tutorial says.. it works.  The event is fired and captured in javascript.  So, since the languages aren't *too different (or so I thought).  I tried to port the lib to VB.NET.  The code is shown below and for some reason it doesn't work.  Does anyone have any insight into what could be the difference?  Thanks in advance.

    Imports System

    Imports System.Collections.Generic

    Imports System.ComponentModel

    Imports System.Drawing

    Imports System.Data

    Imports System.Text

    Imports System.Windows.Forms

    ' required for COM interoperability features

    Imports System.Runtime.InteropServices

    ' exposes events to the outside world through COM

    <Assembly: ClassInterface(ClassInterfaceType.AutoDual)>

    ' establish which public variables will be available through COM

    public interface ImyControlCOMIncoming

    Property MyData as String

    End Interface

    ' interface for the Event - the guid is a random number (you can

    ' write code to generate it)

    ' the DispId a number of your own choosing - the typical format is

    ' 0x6002000n (each event

    ' you expose will need it's own DispId)

    <ComVisible(true)> _

    <Guid("69F023FE-9545-415e-A47D-CA7D2C158AA0")> _

    <InterfaceType(ComInterfaceType.InterfaceIsIDispatch)> _

    public interface ImyControlCOMEvents

    <DispId(266)> _

    Event MyEvent()

    End Interface

    ' Control class, implementing the required interfaces

    <ComVisible(true)> _

    <ClassInterface(ClassInterfaceType.None), ComSourceInterfaces(GetType(ImyControlCOMEvents))> _

    <GuidAttribute("7B88178C-18C4-499c-8745-F4A5F8447CBD")> _

    public class myControl

    Implements ImyControlCOMIncoming

    ' delegate and event declaration

    public event MyEvent

    ' when called within the control, DoMyEvent raises the event

    Sub DoMyEvent()

    ' only raise if the event is registered against something

    RaiseEvent MyEvent

    End Sub

    ' public property

    private _MyData as String

    public property MyData as String implements ImyControlCOMIncoming.MyData

    Get

    return _MyData

    End Get

    Set(ByVal value as String)

    _MyData = value

    End Set

    End Property

    Private Sub Button1_Click( ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

    DoMyEvent()

    End Sub

    Public Sub New()

    ' This call is required by the Windows Form Designer.

    InitializeComponent()

    ' Add any initialization after the InitializeComponent() call.

    End Sub

    End Class

     

    Tuesday, December 05, 2006 1:40 PM

Answers

  • Well, the common sense approach failed me.  I could not do a side by side port and get this to work in vb.net.

    However, after much research, I found an article from microsoft that has a working example.

    I had to modify the assembly to wrap it as active X instead of downloading the dll from the server but the event fires.

     

    Here is a link for anyone that is interested.

     

    Thanks

     

    http://support.microsoft.com/kb/316516

    Monday, December 11, 2006 4:02 AM

All replies

  • I keep looking over the code and the only differences I can see are as follows

    C#

    [ClassInterface(ClassInterfaceType.None),

    ComSourceInterfaces(typeof(ImyControlCOMEvents))]

    VB.NET

    <ClassInterface(ClassInterfaceType.None), ComSourceInterfaces(GetType(ImyControlCOMEvents))> _

    C# uses typeof() which returns only boolean in vb.net.

     

    The next difference is

    C#

    // delegate and event declaration

    public delegate void MyEventHandler();

    public event MyEventHandler MyEvent;

    VB.NET

    public event MyEvent

     

    VB.NET doesn't need a delegate..

     

    Am I missing something?

     

    Thursday, December 07, 2006 9:09 AM
  • Did you ever get this working? I NEED to do the same thing....

    Cheers,
    Owen

    Thursday, December 07, 2006 4:39 PM
  • Owen, Could you try to implement the C# version of my example to see if it works for you..

     

    It does for me we just need to figure out what's different about vb.net..

    Thursday, December 07, 2006 7:20 PM
  • Well, the common sense approach failed me.  I could not do a side by side port and get this to work in vb.net.

    However, after much research, I found an article from microsoft that has a working example.

    I had to modify the assembly to wrap it as active X instead of downloading the dll from the server but the event fires.

     

    Here is a link for anyone that is interested.

     

    Thanks

     

    http://support.microsoft.com/kb/316516

    Monday, December 11, 2006 4:02 AM
  • I'm trying to do this exact thing in C#. You said you got it to work, so I was wondering if you could help me troubleshoot my app real quickly.

    Here's my situation ->

    My DLL has been building and working fine, I can load it in IE and interact with it fine.

    The event is being captured fine in C#, I can verify this.

    Where I'm in the dark is that I have no idea whether my event is being properly exposed to COM or not. Is there a better way to test this that I just don't know about? I just feel like it's one little thing I'm missing, but I have no way to tell and I'm tired of looking in 1000 different directions.

    Also, could security be stopping me? And is the mscorcfg step completely necessary? Thanks in advance.

    Below is a snippet that shows how I'm trying to expose it to COM. I generated the GUIDs, so they should be fine.

    using System;
    using System.Collections;
    using System.ComponentModel;
    using System.Drawing;
    using System.Data;
    using System.Windows.Forms;
    using Microsoft.Ink;
    using System.Runtime.InteropServices;

    [assembly: ClassInterface(ClassInterfaceType.AutoDual)]
    namespace InkAreaCtrl
    {

      

        public delegate void OnCursorDownHandler();

       
        [ComVisible(true)]
        [GuidAttribute("496BCF90-FFBA-4ffa-A11F-29EA7DE45791")]
        [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIDispatch)]
        public interface ControlEvents
        {
            [DispIdAttribute(0x60020000)]
            void OnCursorDown();
        }


       
        [ComVisible(true)]
        [GuidAttribute("160D33BD-AAF3-4d85-8B2A-65FF83EF687E")]
        [ClassInterface(ClassInterfaceType.AutoDispatch), ComSourceInterfaces(typeof(ControlEvents))]
        public class InkCtrl : System.Windows.Forms.UserControl
        {.....etc.....


    If I didn't explain my problem well enough, please email me and I will elaborate.


               
    Wednesday, December 20, 2006 4:36 PM
  • I have tried this example backwards and forwards and I still cannot get it to work.  I have isolated the problem to it failing to load the object that was specified in the classid attribute of the object tag by having it render html.

     

    The problem is, I have no idea why it fails and I have no clue how to determine why it does.  My html file is in a particular directory and my dll is in another directory, and I am using a relative path from the HTML document to reference it and I am pretty damn sure it's correct.

     

    So, how do I figure out why this particular file is not loading.  This is really frustrating that there are no solutions I can find on the web for this.

     

    Thanks.

    Thursday, July 19, 2007 4:35 AM
  • I just wrote an article about that issue.

    you can check it out at http://www.codeproject.com/KB/dotnet/NetHtmlEventHandler.aspx

     

    you can also get the code from http://www.logonce.com/code_samples/HtmlEventProxy

     

    Hope it helps

     

    Sharon Salmon

    http://www.logonce.com

     

     

    Saturday, May 03, 2008 7:54 PM
  • I, too, wrote an article about this that might be useful:

    http://seanmcilvenna.com/blog/10-review/12-webappdeskappcommunication

    Thanks,
    Sean
    Monday, May 18, 2009 11:24 PM