JavaScript

This guide describes how to access JavaScript on the loaded web page, execute JavaScript code, inject .NET objects to call .NET from JavaScript, and other features.

Executing JavaScript

DotNetBrowser allows accessing and executing JavaScript code on the loaded web page.

To access JavaScript, make sure that the web page is loaded completely and JavaScript is enabled.

To execute JavaScript code, use the IFrame.ExecuteJavaScript(string) method. This method returns a Task that can be used to obtain the execution result. Getting the Task.Result property or calling the Task.Wait() method blocks the execution of the current thread until the JavaScript execution is completed.

By default, the method returns a Task<object> that represents the result of the execution. The result is null if JavaScript returns null or undefined. The generic overload of this method performs a direct cast and throws a ClassCastException if there is a type mismatch. If you need to avoid this, use the non-generic overload in a combination with the safe cast, namely as operator.

The sample below executes the JavaScript code that returns a title of the document:

string title = frame.ExecuteJavaScript<string>("document.title").Result;

You can execute any JavaScript code:

double number = frame.ExecuteJavaScript<double>("123").Result;
bool boolean = frame.ExecuteJavaScript<bool>("true").Result;
string str = frame.ExecuteJavaScript<string>("'Hello'").Result;
IJsObject window = frame.ExecuteJavaScript<IJsObject>("window").Result;
IElement body = frame.ExecuteJavaScript<IElement>("document.body").Result;

Injecting JavaScript

You can inject a custom JavaScript code on the web page using the IBrowser.InjectJsHandler property. This handler is intended to inject:

  • a .NET object into JavaScript code;
  • a custom JavaScript code for further execution before any scripts are executed in the particular frame.

See the code sample below:

browser.InjectJsHandler = new Handler<FrameParameters>(args =>
{
    IJsObject window = args.Frame.ExecuteJavaScript<IJsObject>("window").Result;
    window.Properties["myObject"] = new MyObject();
});

The MyObject class may look like this:

public class MyObject
{
    public string SayHelloTo(string firstName) => "Hello " + firstName + "!";
}

When the property is set, you can call methods of the injected .NET object from JavaScript:

window.myObject.SayHelloTo('John');

This handler may be invoked several times for the same frame.

Avoid executing a JavaScript code that modifies the DOM tree of the web page being loaded. You must not use DotNetBrowser DOM API to remove the frame for which this handler is invoked, otherwise the render process crashes.

Type conversion

JavaScript and .NET work with different primitive types. DotNetBrowser implements an automatic type conversion from JavaScript to .NET types and vice versa.

JavaScript to .NET

The following rules are used to convert JavaScript into .NET types:

  • JavaScript numbers are converted to System.Double
  • JavaScript string - to System.String
  • JavaScript boolean - to System.Boolean
  • JavaScript null and undefined - to null
  • JavaScript objects get wrapped as IJsObject
  • JavaScript DOM Node objects get wrapped as both IJsObject and IEventTarget.

In the code sample above we know that the document.title is a string, so we use the generic method overload with the string type parameter.

.NET to JavaScript

The following rules are used to convert .NET into JavaScript types:

  • System.Double - is converted to JavaScript Number;
  • System.String - to JavaScript string;
  • System.Boolean - to JavaScript boolean;
  • .NET null - to JavaScript null;
  • IJsObject - to an appropriate JavaScript object;
  • IEventTarget - to an appropriate JavaScript DOM Node object;
  • System.Object will be wrapped into a JavaScript object.

DOM wrappers

According to the rules of the automatic type conversion, JavaScript DOM objects get wrapped as both IJsObject and IEventTarget. You can work with the JavaScript DOM objects using DotNetBrowser DOM API.

In the code sample below, we return the document that represents a JavaScript DOM object. In this case, the return value type can be set to IJsObject or IDocument:

IDocument document = frame.ExecuteJavaScript<IDocument>("document").Result;
IJsObject document = frame.ExecuteJavaScript<IJsObject>("document").Result;

Working with JsObject

To work with JavaScript objects from .NET code, use the IJsObject interface. This interface allows working with the object properties and calling its functions.

Properties

To get property names of a JavaScript object, including properties from the prototype objects, use the IJsObjectPropertyCollection.Names property:

IEnumerable<string> propertyNames = jsObject.Properties.Names;

To check whether JavaScript object has a specified property, use the IJsObjectPropertyCollection.Contains(string) method:

bool has = jsObject.Properties.Contains("<property-name>");

To get a value of the JavaScript object property by its name, use Properties[string]. See the code sample below:

IJsObject document = frame.ExecuteJavaScript<IJsObject>("document").Result;
object title = document.Properties["title"];

The return value is System.Object that can be set to the required type. For details, refer to the Type Conversion section.

You can remove a property using the following approach:

bool success = jsObject.Properties.Remove("<property-name>");

Functions

To call a function with the required name and arguments, use the Invoke(string methodName, object... args) method. The code sample below demonstrates how to call the document.getElementById() JavaScript function:

IJsObject element = document.Invoke("getElementById", "demo");

…which is equivalent to the following code in JavaScript:

var element = document.getElementById("demo");

The method throws JsException if an error occurs during the function execution.

Calling .NET from JavaScript

When you pass a System.Object as a property value or an argument while calling JavaScript function, the .NET object will be automatically converted/wrapped into a JavaScript object. It allows injecting .NET objects into JavaScript and invoking its public methods from the JavaScript code.

The code samples below demonstrates how to pass a .NET object as a property value and call its public method from JavaScript:

public class MyObject {

    public string SayHelloTo(string firstName) {
        return "Hello " + firstName + "!";
    }
}
IJsObject window = frame.ExecuteJavaScript<IJsObject>("window").Result;
window.Properties["MyObject"] = new MyObject();

After that, you can refer to the object and call its method from the JavaScript code:

console.log(window.MyObject.SayHelloTo("John"));

The Console output is as follows:

Hello John!

Type conversion

The JavaScript-.NET bridge provides automatic types conversion functionality when calling a public method of the injected .NET object from JavaScript.

The library automatically convert the given JavaScript Number to the required .NET type if it is possible. If we detect that the given number cannot be converted to, for example, a .NET byte without data loss, then the library throws an exception and notifies JavaScript that there is no appropriate .NET method. If the given value can be converted without data loss, then the library converts it and invokes the appropriate .NET method.

For example, if you inject the following .NET object into JavaScript:

public sealed class MyObject {

    public int Method(int intValue) {
        return intValue;
    }
}

After that, you can call it from JavaScript and pass the JavaScript Number value that can be converted to an Integer without data loss:

window.MyObject.method(123);

However, if you pass Double value that cannot be converted to an Integer without data loss, you get the following error:

window.MyObject.method(3.14); // <- error

Injecting delegates

The other way to call .NET from JavaScript is injecting delegates.

JavaScript-.NET bridge allows you to associate a delegate with a JavaScript property. Such a delegate will be treated as a function that can be invoked in JavaScript code.

For example, you can register a JavaScript function associated with the delegate using the following code:

IJsObject window = frame.ExecuteJavaScript<IJsObject>("window").Result;
if (window != null) {
    window.Properties["sayHello"] =  (Func<string, string>) ((args) => "Hello, " + args[0]);
}

Now, you can invoke this function in JavaScript the following way:

window.sayHello('John');

The type conversion rules do not apply to the delegates. The JavaScript Number is always interpreted as Double in this case.

Console messages

DotNetBrowser allows receiving all output messages sent to the Console using the console.log() JavaScript function. You can listen to the messages with the following levels:

  • DEBUG
  • LOG
  • WARNING
  • ERROR

To get a notification on the Console receives a message, use the ConsoleMessageReceived event. See the code sample below:

browser.ConsoleMessageReceived += (s, e) => {
    string consoleMessage = e.Message;
    ConsoleMessageReceivedEventArgs.MessageLevel level = e.Level;
};

Working with JSON

DotNetBrowser JS - .NET Bridge API allows converting a string that represents JSON to a JavaScript object/objects. The code sample below demonstrates how to create a JavaScript object from the JSON string:

string jsonString = "[123, \"Hello\"]";
IJsObject jsObject = browser.MainFrame.ParseJsonString<IJsObject>(jsonString);

If you try parsing the string value that doesn’t represent a valid JSON, a JsException is thrown.

In the code sample above, the "[123, \"Hello\"]" JSON string is converted into an appropriate JavaScript object. In this case, it will be converted to an array.

It is possible to convert IJsObject into a JSON string using the ToJsonString() extension method. It returns a string equivalent to JavaScript JSON.stringify() method:

string jsonRepresentation = jsObject.ToJsonString();
Go Top