In Blazor, JavaScript Interop allows C# code to call JavaScript functions and vice versa. This is essential when interacting with browser APIs, accessing localStorage, manipulating the DOM, or working with third-party JS libraries. Blazor provides two main interfaces for this purpose: IJSRuntime and IJSInProcessRuntime.
IJSRuntime – Asynchronous Interop
This is the standard way to call JavaScript from C# in both Blazor Server and Blazor WebAssembly. It uses asynchronous calls to avoid blocking the UI thread.
When to Use:
- The app runs on Blazor Server or needs cross-platform compatibility.
- You are calling long-running or async JavaScript functions.
UI responsiveness is a priority.
@inject IJSRuntime JS
<button @onclick="SaveToLocalStorage">Save</button><button @onclick="ReadFromLocalStorage">Read</button>@code { async Task SaveToLocalStorage() { await JS.InvokeVoidAsync("localStorage.setItem", "title", "Blazor Blog"); } async Task ReadFromLocalStorage() { string value = await JS.InvokeAsync<string>("localStorage.getItem", "title"); Console.WriteLine($"Value from localStorage: {value}"); }
}
IJSInProcessRuntime – Synchronous Interop
This is a more specialized interface for Blazor WebAssembly only. It allows synchronous calls to JavaScript, which can reduce latency in performance-critical scenarios.
When to Use:
- The app runs only on Blazor WebAssembly.
- You need fast, synchronous access to JS (e.g., reading small values).
- The JS function is quick and doesn’t block the UI thread.
@inject IJSRuntime JSRuntime
<button @onclick="ReadSync">Read Sync</button>@code { void ReadSync() { if (JSRuntime is IJSInProcessRuntime jsInProcess) { string title = jsInProcess.Invoke<string>("localStorage.getItem", "title"); Console.WriteLine($"(Sync) Value: {title}"); } }
}
What are the Key Differences IJSRuntime vs IJSInProcessRuntime?
Feature | IJSRuntime (Async) | IJSInProcessRuntime (Sync) |
Available In | Blazor Server & WebAssembly | Blazor WebAssembly only |
Call Type | Asynchronous | Synchronous |
Thread Safety | Non-blocking, UI-safe | Can block UI if misused |
Usage Recommendation | Preferred for most scenarios | Use only for small, fast calls |
Conclusion
Use IJSRuntime for safe, asynchronous JS interop across both hosting models. Only use IJSInProcessRuntime in Blazor WebAssembly when you need fast synchronous access for lightweight operations. Avoid blocking the UI thread and always consider portability and performance when choosing between the two.