In the previous two articles of this series, we have learned how to call JavaScript functions from C#. Now, as a logical continuation, we are going to learn how to call C# methods from JavaScript in our Blazor WebAssembly application.

To download the source code for this article, visit the Call C# Methods from JavaScript repository

If you want to see complete navigation for this series, you can visit our Blazor WebAssembly Page and find all of the articles from this series and many other articles as well.

We are going to divide this article into the following sections:

Let’s get started.

Preparing Files and Components

Before we start with the main topic of this article, we have to create additional files and components and also to add some modifications to the existing files.

So, let’s start with a JavaScript file creation in the scripts folder. We are going to name this file jsExamples2.

Then, let’s import this file in the index.html file:

<script src="scripts/jsExamples2.js"></script>

In the previous articles, we didn’t have to do this because we used the JSObjectReference class to import the JS module only when we needed it. But now, since we are going to show you how to call C# methods from JavaScript, we have to import the js file.

Now, let’s create the CallDotNetFromJavaScript.razor and CallDotNetFromJavaScript.razr.cs files in the Pages folder:

Component to Call C# methods from JavaScript in the Pages folder

Let’s just modify the .razor file, by adding just a route directive and a heading:

@page "/dotnetinjs"

<h2>Call DotNet From JavaScript</h2>
<br />

Okay. Now we can modify the Index.razor file:

@page "/"

<h3>
    Use the following links to explore different examples 
    of using a JS code with .NET in Blazor WebAssembly Project:
</h3>

<ul>
    <li>
        <a href="/jsindotnet">
            How to call JavaScript code from .NET
        </a>
    </li>
    <li>
        <a href="/dotnetinjs">
            How to call .NET code from JavaScript
        </a>
    </li>
</ul>

This is a simple navigation link to our previously created component.

If we start our application and click this link, we are going to be navigated to the CallDotNetFromJavaScript component.

Excellent.

All the preparations are over and we can move on to the main topic of this article.

Calling a Static C# Method From JavaScript

The first thing we have to do is to create a new static method in the CallDotNetFromJavaScript.razor.cs file:

public partial class CallDotNetFromJavaScript
{
    [JSInvokable]
    public static string CalculateSquareRoot(int number)
    {
        var result = Math.Sqrt(number);

        return $"The square root of {number} is {result}";
    }
}

So, this is a very basic logic for calculating the square root of a number. The important part is the [JSInvokable] attribute. This attribute indicates that this method is invokable by the JavaScript code.

Now, let’s run our app, navigate to this new component, open the developer tools window (F12), and type DotNetin the console:

Showing the properties from the DotNet object in a browser

The DotNet object is an object we use to call static C# methods from JavaScript. As you can see it contains two properties – invokeMethod and invokeMethodAsync – that we can use to call static C# methods. In our example, we are going to use the async one.

That said, let’s get back to our project and modify the jsExamples2.js file:

var jsFunctions = {};

jsFunctions.calculateSquareRoot = function () {
    const number = prompt("Enter your number");

    DotNet.invokeMethodAsync("BlazorWasmJSInteropExamples", "CalculateSquareRoot", parseInt(number))
        .then(result => {
            var el = document.getElementById("string-result");
            el.innerHTML = result;
        });
}

Here, we create a global jsFunctions object and assign the calculateSquareRoot function. In this function, we prompt the user to enter a number and then use the DotNet object and the invokeMethodAsync function to call our method from .NET. In this function, we pass three arguments. The first one is the Assembly name, the second one is the name of the method, and the last one is the parameter expected in the c# method.

You can add additional checks on the number variable if you want (Is it a number, is it null…).

An additional thing to mention here is that the invokeMethodAsync function returns a promise. So, we use the .then function to subscribe to that promise. Inside, we just fetch the element with the string-result id and store the result in it.

Lastly, we have to modify the CallDotNetFromJavaScript.razor file:

<div class="row">
    <div class="col-md-4">
        <h4>Calling static method from JS</h4>
    </div>
    <div class="col-md-2">
        <button type="button" class="btn btn-success" onclick="jsFunctions.calculateSquare()">
            Calculate
        </button>
    </div>
    <div class="col-md-4">
        <span id="string-result" class="form-text"></span>
    </div>
</div>

The main thing to notice here is that we are not using the @onclick event handler because we are not calling the method from the .cs file. What we do is calling the javascript function and thus the onclick event handler.

So, as soon as we click the Calculate button, the prompt window will appear. We are going to enter 25 and click Ok:

Successfully call c# methods from javascript

There we go. We have a response from the C# method.

Using Custom Identifiers to Call C# Methods from JavaScript

While calling static C# methods from JavaScript, we have to provide an identifier as an argument for the invokeMethodAsync function. The identifier for this static method in the javascript function is the combination of the assembly name and the name of the method:

DotNet.invokeMethodAsync("BlazorWasmJSInteropExamples", "CalculateSquareRoot", parseInt(number))

The identifier must be unique across the entire assembly. So, having another class with the same-named method in the same assembly won’t work.

Having two methods with the same name is quite common in C#. To support that with JavaScript, we have to use a different overload of the JSInvokable attribute that accepts the identifier parameter:

[JSInvokable("CalculateSquareRootWithJustResult")]
public static string CalculateSquareRoot(int number, bool justResult)
{
    var result = Math.Sqrt(number);

    return !justResult ?
        $"The square root of {number} is {result}" :
        result.ToString();
}

As you can see, we are providing a different identifier for this method.

Now, in the JavaScript file, we can create a similar call with a different identifier:

jsFunctions.calculateSquareRootWithJustResult = function () {
    const number = prompt("Enter your number");

    DotNet.invokeMethodAsync("BlazorWasmJSInteropExamples", "CalculateSquareRootWithJustResult", parseInt(number), true)
        .then(result => {
            var el = document.getElementById("result");
            el.innerHTML = result;
        });
}

You can see we invoke a new method identifier with the additional bool parameter.

Finally, we can create an HTML markup for this:

<div class="row">
    <div class="col-md-4">
        <h4>Calling static method from JS with Custom Identifier</h4>
    </div>
    <div class="col-md-2">
        <button type="button" class="btn btn-success" onclick="jsFunctions.calculateSquareRootWithJustResult()">
            Calculate
        </button>
    </div>
    <div class="col-md-4">
        <span id="result" class="form-text"></span>
    </div>
</div>

Excellent.

If we start our app, navigate to the component, and click any button on the page, we will see that both works but with different results.

Calling C# Instance Methods From JavaScript

Up until now, we’ve been calling static C# methods from JavaScript, but we can do the same with the non-static ones. For this situation, the flow is a bit different. We have to pass the DotNetObjectReference to the JavaScript function and then use it in that function to call the C# instance method.

Let’s see this with an example where we are going to show how to display the mouse coordinates on the screen.

First of all, we have to create a method in our class file that will send the DotNetObjectReference instance to the JavaScript function:

public partial class CallDotNetFromJavaScript
{
    [Inject]
    public IJSRuntime JSRuntime { get; set; }

    ...

    private async Task SendDotNetInstanceToJS()
    {
        var dotNetObjRef = DotNetObjectReference.Create(this);
        await JSRuntime.InvokeVoidAsync("jsFunctions.showMouseCoordinates", dotNetObjRef);
    }		
}

So here, we inject the IJSRuntime service and create the SendDotNetInstanceToJS method. Inside this method, we create a new DotNetObjectReference instance using the Create method. The DotNetObjectReference static class comes from the Microsoft.JSInterop namespace. Then, we use the JSRuntime property and call the JS function passing our instance to it.

Now, it is obvious that we need the JS funciton named showMouseCoordinates:

jsFunctions.showMouseCoordinates = function (dotNetObjRef) {
    dotNetObjRef.invokeMethodAsync("ShowCoordinates",
        {
            x: window.event.screenX,
            y: window.event.screenY
        }
    );
}

The dotNetObjRef parameter is the one we accepted from the C# invocation, and it contains two methods invokeMethodAsync and invokeMethod – the same as the DotNet object does, wich we used to call static C# methods. So, as  you can see, we are using the async method to invoke the C# method named ShowCoordinates and as an argument we pass an object containing two properties the X and Y coordinates.

JSInvokable Method and Additional Logic

Now, let’s get back to the class file:

public partial class CallDotNetFromJavaScript
{
    private MouseCoordinates _coordinates = new MouseCoordinates();

    [Inject]
    public IJSRuntime JSRuntime { get; set; }

    ...

    private async Task SendDotNetInstanceToJS()
    {
        var dotNetObjRef = DotNetObjectReference.Create(this);
        await JSRuntime.InvokeVoidAsync("jsFunctions.showMouseCoordinates", dotNetObjRef);
    }
        
    [JSInvokable]
    public void ShowCoordinates(MouseCoordinates coordinates)
    {
        _coordinates = coordinates;
        StateHasChanged();
    }
}

public class MouseCoordinates
{
    public int X { get; set; }
    public int Y { get; set; }
}

Here, we create another MouseCoordinates class with the X and Y properties. We are keeping it in the same file due to the sake of simplicity.

Then in the main class, we create the MouseCoordinates instance and create the ShowCoordinates method which accepts the coordinates parameter from the JavaScript function. We can see that this function has the [JSInvokable] attribute. Also in this method, we instantiate our _coordinates object and call the StateHasChanged method to rerender our component.

HTML Markup

Finally, let’s add the required HTML markup:

<div class="row">
    <div class="col-md-4">
        <h4>Calling instance method from JS </h4>
    </div>
    <div class="col-md-2">
        <button type="button" class="btn btn-success" @onclick="SendDotNetInstanceToJS">
            Send Instance
        </button>
    </div>
    <div class="col-md-4">
        <p id="coordinates" style="height: 200px; width: 400px;	background-color: #d6d8d6;
            text-align:center; font-size:20px;">
            @_coordinates.X - @_coordinates.Y
        </p>
    </div>
</div>

So, once we click the Send Instance button, we are going to call the SendDotNetInstanceToJS method from our C# class. That method is going to create DotNetObjectReference instance and send it to the JS function. In the JS function, we create an object with two (X, Y) properties, and we call the ShowCoordinates method passing that object. Finally, this method initializes the _coordinates object that we use to show the X and Y coordinates on the screen:

Calling C# Instance Method from JavaScript example

Also, you can click anywhere on the button and different values will be displayed in the gray box.

But let’s improve this solution a bit.

Improving Solution

What we want is to send the instance to the JS function by clicking the Send Instance button, but also to be able to move our mouse inside the gray box and see different coordinate values.

To do that, we have to modify the showMouseCoordinates function in the JS file:

jsFunctions.registerMouseCoordinatesHandler = function (dotNetObjRef) {
    function mouseCoordinatesHandler() {
        dotNetObjRef.invokeMethodAsync("ShowCoordinates",
            {
                x: window.event.screenX,
                y: window.event.screenY
            }
        );
    };

    mouseCoordinatesHandler();

    document.getElementById("coordinates").onmousemove = mouseCoordinatesHandler;
}

Now we have the registerMouseCoordinatesHandler function that accepts the dotNetObjRef parameter. In this function, we have another function that is almost the same as the one we had previously, just with a new name mouseCoordinatesHandler and without a parameter. Then, we call this mouseCoordinatesHandler function once to show the coordinates right away. After that, we attach the onmousemove event handler to the gray box. This onmousemove event handler will trigger the mouseCoordinatesHandler function every time our mouse move.

Now, all we have to do is to go back to the class file and modify the SendDotNetInstanceToJS method, to call a different JS function:

private async Task SendDotNetInstanceToJS()
{
    var dotNetObjRef = DotNetObjectReference.Create(this);
    await JSRuntime.InvokeVoidAsync("jsFunctions.registerMouseCoordinatesHandler", dotNetObjRef);
}

At this point, we can start our application and navigate to the component. As soon as we click the Send Instance button, we are going to see the coordinates in the gray box. But also, as soon as we hover over the gray box with our mouse, the coordinates will start to change. We can move the pointer inside the gray box to see different coordinate values:

Call C# methods from JavaScript with Mosue Coordinates Displayed on the screen

Excellent.

Conclusion

So, there you go.

We have learned how to call static C# methods from JavaScript and also how to do the same but with the instance methods. Also, we have learned how to change identifiers for our methods if we want to overload some of them.

In the next article, we are going to learn how to use JSInterop in Razor Class Libraries and how to use browser functionalities.

So, see you there.