Working with the Blazor JavaScript Interop
Tags: aspnetcore, programming, javascript, webdev
Published: 2019-07-08 17:17:49

---
title: Working with the Blazor JavaScript Interop
published: true
tags: aspnetcore,programming,javascript,web-development
canonical_url: https://blog.logrocket.com/working-with-the-blazor-javascript-interop-3c2a8d0eb56c
---

![](https://cdn-images-1.medium.com/max/1024/1*9VnQHM6JhrXhm6otyaMVmQ.png)

In this article, we’ll look at Blazor, a single-page web app framework built on .NET that runs in the browser with WebAssembly. We’ll get an understanding of how Blazor handles JavaScript calls, why it’s necessary, and how it’s used.

As WebAssembly ( abbreviated Wasm) is gaining momentum it’s important to understand the current capabilities. WebAssembly lacks the ability to directly access the Browser’s DOM API, however, it can make calls to JavaScript. Because of this shortcoming JavaScript is still very much a part of web development.

[![](https://cdn-images-1.medium.com/max/1024/1*GPjaPKNNUYHU8EsA3Z0JGA.png)](https://logrocket.com/signup/)

### **Blazor, Mono, and WebAssembly**

WebAssembly (Wasm) is a binary instruction format that is designed to provide a compilation target for high-level languages like C#. Recently Microsoft began experimenting with WebAssembly to [bring .NET to the browser using the Mono run-time](https://www.mono-project.com/news/2017/08/09/hello-webassembly/). Mono provides the basic plumbing allowing .NET libraries (.dll’s) to run on WebAssembly.

![](https://cdn-images-1.medium.com/max/1024/1*VdBE4STMMqP_9g7EKZsEJw.jpeg)<figcaption>A block diagram of the Blazor &amp; Browser relationship</figcaption>

Blazor features a component architecture, routing, a virtual DOM, and a JavaScript Interoperability (interop) API. Through the JavaScript interop a Blazor app can invoke JavaScript functions from .NET and C# methods from JavaScript code.  
   
To call into JavaScript from .NET the _IJSRuntime_ abstraction is used. The current instance of IJSRuntime is resolved by making a call to _JSRuntime.Current_. From this instance we can call the _InvokeAsync<T>_ method passing in the first argument as an identifier to the corresponding JavaScript function we would like to invoke, this function must be available on the global scope of _window_. Additional arguments may be passed through to the JavaScript function provided they are JSON serialize-able as well as the return type _Task<T>_.
```jsx
using Microsoft.JSInterop;
public class ExampleJsInterop
{
  public static Task<T> MethodName(TArgs args)
  {
    // Implemented in exampleJsInterop.js
    return JSRuntime.Current.InvokeAsync<T>("scope.jsMethod", args);
  }
}
```
### JavaScript Interop

Since Blazor is built upon Mono and WebAssembly and therefore has no direct access to the browser’s DOM API, it must marshal calls through JavaScript when it needs DOM access. The inclusion of JavaScript in the stack is not only beneficial in terms of necessity, but also flexibility.  
   
**Backwards compatibility**   
   
Including JavaScript in the stack enables Blazor applications to utilize existing JavaScript libraries. This includes UI libraries like [Bootstrap](https://github.com/chanan/BlazorStrap), [Toastr.js](https://github.com/sotsera/sotsera.blazor.toaster), a toast notification library, and [Chart.js](http://www.chartjs.org/) for simple charting components.

In addition, full-featured commercial UI libraries such as [Kendo UI](https://www.telerik.com/kendo-ui) could potentially be ported to Blazor. These “ports” essentially provide a C# API surface for interacting with the underlying JavaScript while providing a migration path for users.  
   
**Mind the gap**  
   
Because Blazor is new and experimental, the interop allows developers to fall back on JavaScript when there are shortcomings of WebAssembly itself, or because the Blazor framework is not yet mature.  
   
For example, if we wanted to use a standard window _prompt()_ method, there is no native support in Blazor to do this. However, a simple API can be created using the JavaScript interop to add support for this functionality.  
   
We’ll start by creating a JavaScript file with the method we would like to invoke from our application.

For the function to be visible to Blazor, we’ll need to add it to the scope of _window_. As a best practice, additional namespaces can be added using a module pattern, this protects our methods from conflicting with other code on the scope of _window_. Within our namespace, we define a function to call the native window _prompt()_ method.
```jsx
window.myNamespace = {
    showPrompt: function (message) {
    return prompt(message, 'Type anything here');
  },
    anotherFunction: function(args) { 
    // do stuff 
  }
};
```
Next, we need to invoke the JavaScript _showPrompt_ function from within C# using the _JSRuntime.Current.InvokeAsync_ method. A C# function _PromptAsync_ provides a nice abstraction that can be used within the Blazor application. Developers using the abstraction will not need to understand the underlying JavaScript implementation.
```jsx
using Microsoft.JSInterop;

public class PromptInterop
{
    /// <summary>
    /// Invokes a browser prompt and returns the user's input.
    /// </summary>
    public static Task<string> PromptAsync(string message) {
        return JSRuntime.Current.InvokeAsync<string>("myNamespace.showPrompt",message);
	}
}
```
Since Blazor’s UI process is capable of running on a separate thread from the application _InvokeAsync_ should be used by default.

However, if there is a need to invoke the JavaScript method synchronously, we can provide that functionality by downcasting _JSRuntime_ to _IJSInProcessRuntime_. Adding the _Prompt_ method in addition to _PromptAsync_ provides an alternative API when asynchronous behavior is not available.
```jsx
using Microsoft.JSInterop;

public class PromptInterop
{
    /// <summary>
    /// Invokes a browser prompt and returns the user's input.
    /// </summary>
    public static Task<string> PromptAsync(string message) {
        return JSRuntime.Current.InvokeAsync<string>("myNamespace.showPrompt",message);
	}

    /// <summary>
    /// Syncronously invokes a browser prompt and returns the user's input. Use for in-process-senarios only.
    /// </summary>
    public static string Prompt(string message) {
        return ((IJSInProcessRuntime)JSRuntime.Current).Invoke<string>("myNamespace.showPrompt",message);
	}
}
```
The _ShowPrompt_ method is now available to use within the application. We can call _PromptAsync_ from a Blazor component by calling the method and awaiting a result.

In the following example, we’ll trigger a browser prompt when the user clicks on the component. When the prompt is closed the result is returned to the component’s _Message_ field which is data-bound and rendered to the component. To ensure the new value is updated when data-binding occurs, we’ll call _StateHasChanged_ to instruct Blazor to re-render the component.
```jsx
<div onclick="@HandleClick" class="my-component">
    @Message
</div>

@functions {
    string Message = "Click to change";
    async void HandleClick()
    {
        Message = await PromptInterop.PromptAsync("Type a message");
        StateHasChanged();
    }
}
```
![](https://cdn-images-1.medium.com/max/400/1*aVDRr5sTO7oOnrX1YmnRVg.gif)<figcaption>Blazor JavaScript interop providing a browser prompt</figcaption>

### Conclusion

While Blazor and WebAssembly lack the ability to directly access the Browser’s DOM API, the JavaScript interop provides a means of filling the gap. The interop makes it possible to migrate existing JavaScript libraries to Blazor. Through the interop developers can create abstractions around browser features providing C# methods to add functionality at the application level.

As Blazor gains in popularity, it is reasonable to assume that an ecosystem of interop libraries will emerge. As more interop libraries become available, then Blazor developers may spend less time writing JavaScript and more time in C#.
* * *
### Plug: [LogRocket](https://logrocket.com/signup/), a DVR for web apps

[![](https://cdn-images-1.medium.com/max/1024/1*s_rMyo6NbrAsP-XtvBaXFg.png)](https://logrocket.com/signup/)<figcaption><a href="https://logrocket.com/signup/">https://logrocket.com/signup/</a></figcaption>

[LogRocket](https://logrocket.com/signup/) is a frontend logging tool that lets you replay problems as if they happened in your own browser. Instead of guessing why errors happen, or asking users for screenshots and log dumps, LogRocket lets you replay the session to quickly understand what went wrong. It works perfectly with any app, regardless of framework, and has plugins to log additional context from Redux, Vuex, and @ngrx/store.

In addition to logging Redux actions and state, LogRocket records console logs, JavaScript errors, stacktraces, network requests/responses with headers + bodies, browser metadata, and custom logs. It also instruments the DOM to record the HTML and CSS on the page, recreating pixel-perfect videos of even the most complex single page apps.

[Try it for free.](https://logrocket.com/signup/)
* * *
The post [Working with the Blazor JavaScript Interop](https://blog.logrocket.com/working-with-the-blazor-javascript-interop-3c2a8d0eb56c/) appeared first on [LogRocket Blog](https://blog.logrocket.com).