Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

boundEvent Error #2715

Closed
ByErdem opened this issue Apr 4, 2019 · 18 comments
Closed

boundEvent Error #2715

ByErdem opened this issue Apr 4, 2019 · 18 comments
Labels

Comments

@ByErdem
Copy link

ByErdem commented Apr 4, 2019

When I first open WebBrowser, I can catch any javascript event on the browser side, but when I go to another address I can't add the boundEvent event again and I get a javascript error on the console side: Cannot read property 'raiseEvent' of undefined. Can you show me a solution, thanks in advance for your interest.

public void InitCefBrowser(string url)
{
    CefSharpSettings.FocusedNodeChangedEnabled = true;
    CefSharpSettings.LegacyJavascriptBindingEnabled = true;

    CefBrowser = new ChromiumWebBrowser(url)
    {
        
        BrowserSettings =
                    {
                        DefaultEncoding = "UTF-8"
                    },
        JsDialogHandler = new JsDialogHandler(),


        Dock = DockStyle.Fill,
    };

    Panel1.Controls.Add(CefBrowser );
    CefBrowser .FrameLoadEnd += Browser_FrameLoadEnd;

    eventObject = new ScriptedMethodsBoundObject();
    eventObject.EventArrived += OnJavascriptEventArrived;
    CefBrowser .RegisterJsObject("boundEvent", eventObject, options: BindingOptions.DefaultBinder);
}

private void OnJavascriptEventArrived(string eventName, object eventData)
{
        var jsonString = eventData.ToString();
        var serializer = new JavaScriptSerializer();
        var dataDict = serializer.Deserialize<Dictionary<string, object>>(jsonString);

        switch (eventName)
        {
            case "click":
                {
                    Invoke(new MethodInvoker(() =>
                    {
                        if (dataDict["Path"] != null)
                            TextBox1.Text = dataDict["Path"].ToString();
                    }));

                    break;
                }
        }
}


private void Browser_FrameLoadEnd(object sender, FrameLoadEndEventArgs e)
{
    string scripts = File.ReadAllText(Application.StartupPath + @"\javascript\events.js", Encoding.UTF8);
    CefBrowser.ExecuteScriptAsync(scripts);

    try
    {
        CefBrowser.ShowDevTools();
    }
    catch (Exception ex) { }

}

private void BtnGoToPage_Click(object sender, EventArgs e)
{
    CefBrowser.Load(TxtUrl.Text);
}

Javascript return result:
window.boundEvent.raiseEvent("click", "Test");

@amaitland
Copy link
Member

Objects registered using RegisterJsObject and RegisterAsyncJsObject will be automatically bound in the first render process that's created for a ChromiumWebBrowser instance. If you perform a cross-site navigation a process switch will occur and bound objects will no longer be automatically available

http://cefsharp.github.io/api/71.0.0/html/P_CefSharp_CefSharpSettings_LegacyJavascriptBindingEnabled.htm

You can only use LegacyJavascriptBinding for single page applications or those that only navigate to a single domain.

See #2246

https://github.com/cefsharp/CefSharp/wiki/General-Usage#3-how-do-you-expose-a-net-class-to-javascript

You can use http://cefsharp.github.io/api/71.0.0/html/M_CefSharp_JavascriptBindingExtensions_EnsureObjectBoundAsync.htm to register an object in c# then execute additional scripts upon it's completion.

@ByErdem
Copy link
Author

ByErdem commented Apr 5, 2019

Really I didn't understand anything. Can't I use for more than one pages? I have to do this. Isn't there another way? If there is any way can you write a sample code related with this?

@ByErdem
Copy link
Author

ByErdem commented Apr 5, 2019

Alex, can you add such a feature. I want able to use this at every domain.

@amaitland
Copy link
Member

Can't I use for more than one pages?

The Legacy version is only for single page applications or those that only use a single domain (cross-domain navigation is not supported for Legacy Javascript Binding).

Isn't there another way?

Yes, use the newer JavaScript binding implementation that is detailed in https://github.com/cefsharp/CefSharp/wiki/General-Usage#3-how-do-you-expose-a-net-class-to-javascript

If there is any way can you write a sample code related with this?

The source contains one example already see

await CefSharp.BindObjectAsync('boundEvent');

can you add such a feature.

The newer Javascript Binding v2 is that feature, it replaced what is now referred to Legacy Javascript Binding which is no longer workable for cross-domain navigation. If https://bitbucket.org/chromiumembedded/cef/pull-requests/147/allow-synchronously-sending-extra_info-to/diff is ever merged into CEF then it will be possible to rewrite the Legacy implementation. The PR has been open for over a year, I wouldn't get my hopes up of this happening.

@ByErdem
Copy link
Author

ByErdem commented Apr 5, 2019

Hello Again,
Actually, I didn't understand many things and I prepared an example to make don't you tired. Please can you edit this? Just I want a small example.

I removed package files frome here. And this is more small size file.
https://drive.google.com/open?id=11MdWhihJtwcsZmAZFAXsv32ZkYzTee8s

This is contains all package files. You can open whichever you want.
https://drive.google.com/open?id=1nkUZ40ySrRTtVFFVRpNVa7iSusM6oIjc

Thanks in advance for your interest.

@amaitland
Copy link
Member

Please no binary (zip, etc) links, fork the MinimalExample and push your changes to GitHub. (Alternatively use a code sharing service list Gist or Pastebin).

As per https://github.com/cefsharp/CefSharp/blob/master/ISSUE_TEMPLATE.md#bug-report please no binaries. You will have to provide an example in an open way, github, pastebin, etc.

I didn't understand many things

What don't you understand? Did you read https://github.com/cefsharp/CefSharp/wiki/General-Usage#3-how-do-you-expose-a-net-class-to-javascript

For reference this issue will be closed as invalid as the behaviour you are seeing is the expected one.

@amaitland
Copy link
Member

@amaitland
Copy link
Member

You might find https://gist.github.com/amaitland/48adad9c7f2c57f6c17fad39b2747d00 useful also.

@ByErdem
Copy link
Author

ByErdem commented Apr 8, 2019

Hello Alex,
I wrote this codes and run. But I getting this error: "boundAsync.div is not function". You think, where I'm doing wrong?

//Javascript Codes

(async function()
{
	await CefSharp.BindObjectAsync("boundAsync");
	var message="This is a test";
	boundAsync.div(message);

})();
//C# Codes

        ChromiumWebBrowser browser;
        bool status = false;

    public class BoundObject
    {
        public class AsyncBoundObject
        {
            //We expect an exception here, so tell VS to ignore
            [DebuggerHidden]
            public void Error()
            {
                throw new Exception("This is an exception coming from C#");
            }

            //We expect an exception here, so tell VS to ignore
            [DebuggerHidden]
            public string Div(string message)
            {
                return message;
            }
        }
    }

        public void InitCefBrowser()
        {
            if (!status)
            {
                browser = new ChromiumWebBrowser(textBox1.Text)
                {

                    BrowserSettings =
                            {
                                DefaultEncoding = "UTF-8"
                            },
                    JsDialogHandler = new JsDialogHandler(),


                    Dock = DockStyle.Fill,
                };

                panel1.Controls.Add(browser);
                browser.FrameLoadEnd += Browser_FrameLoadEnd;
                status = true;
            }
            else
            {
                browser.Load(textBox1.Text);
            }

            var eventObject = new ScriptedMethodsBoundObject();
            eventObject.EventArrived += OnJavascriptEventArrived;

            try
            {
                browser.JavascriptObjectRepository.Register("boundAsync", new BoundObject(), isAsync: true, options: BindingOptions.DefaultBinder);
            }
            catch (Exception) { }


            browser.JavascriptObjectRepository.ResolveObject += (sender, e) =>
            {
                var repo = e.ObjectRepository;
                if (e.ObjectName == "boundAsync2")
                {
                    BindingOptions bindingOptions = null; //Binding options is an optional param, defaults to null
                    bindingOptions = BindingOptions.DefaultBinder; //Use the default binder to serialize values into complex objects, CamelCaseJavascriptNames = true is the default

                    bindingOptions = new BindingOptions { CamelCaseJavascriptNames = false, Binder = (IBinder)BindingOptions.DefaultBinder }; //No camelcase of names and specify a default binder
                    repo.Register("boundAsync2", new AsyncBoundObject(), isAsync: true, options: bindingOptions);
                }
            };
        }

        private void button1_Click(object sender, EventArgs e)
        {
            InitCefBrowser();

        }

@ray007
Copy link

ray007 commented Apr 8, 2019

Try

boundAsync.Div(message);

@ByErdem
Copy link
Author

ByErdem commented Apr 8, 2019

I tried and I getting same error.
"Uncaught (in promise) TypeError: boundAsync.Div is not a function"

@ray007
Copy link

ray007 commented Apr 8, 2019

I guess you already did try removing the [DebuggerHidden] attribute?

@ByErdem
Copy link
Author

ByErdem commented Apr 8, 2019

I didn't try yet. I will try. So, did you try such a this?

@ByErdem
Copy link
Author

ByErdem commented Apr 8, 2019

Now I tried, not working. I getting same error.

@ray007
Copy link

ray007 commented Apr 8, 2019

Try interactive with developer tools what functions/properties you can find on window.boundAsync.

@amaitland
Copy link
Member

I've created a working example at https://github.com/cefsharp/CefSharp.MinimalExample/tree/demo/javascriptbinding

You can review commit cefsharp/CefSharp.MinimalExample@2febd68 to see what changes I made.

There are two html pages, in the JavascriptBinding\html folder, they show slightly different options, basically the same concept.

@amaitland
Copy link
Member

I wrote this codes and run. But I getting this error: "boundAsync.div is not function". You think, where I'm doing wrong?

@ByErdem Your binding BoundObject as boundAsync. BoundObject has no methods, it contains a nested class called AsyncBoundObject. Delete one of those classes and simplify your code.

@ByErdem
Copy link
Author

ByErdem commented Apr 10, 2019

Https://github.com/cefsharp/CefSharp.MinimalExample/tree/demo/javascriptbinding adresinde çalışan bir örnek oluşturdum

Hangi değişiklikleri yaptığımı görmek için commit cefsharp / CefSharp.MinimalExample @ 2febd68 sayfasını inceleyebilirsiniz .

İki html sayfası var, JavascriptBinding\htmlklasörde, temelde aynı konsept olan biraz farklı seçenekler gösteriliyor.

It looks like an example I want. I'il check this out. Thank you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants