Blazor Interop Samples
This section provides practical examples of how to integrate Blazor components with existing ASP.NET Core MVC and Razor Pages applications. We'll explore various techniques to enable seamless communication between the two paradigms.
Overview of Blazor Interop
Blazor allows you to build interactive web UIs using C# instead of JavaScript. However, many existing applications are built with ASP.NET Core MVC or Razor Pages, which are server-side rendering (SSR) focused. Blazor Interop provides the bridge to leverage Blazor's component model within these SSR applications.
Key Concepts
- Hosting Blazor in SSR: Embedding Blazor Server components within your MVC/Razor Pages views.
- Calling .NET from JavaScript: Invoking C# methods from your existing JavaScript code.
- Calling JavaScript from .NET: Executing JavaScript functions from your Blazor components.
- Data Sharing: Techniques for passing data between Blazor components and the surrounding SSR application.
Sample Scenarios
1. Embedding a Blazor Counter Component in a Razor Page
This sample demonstrates how to host a simple Blazor component, like a counter, directly within a Razor Page. This allows you to add interactive elements to specific parts of your page without converting the entire application to Blazor.
Razor Page (.cshtml)
<!DOCTYPE html>
<html>
<head>
<title>Razor Page with Blazor Counter</title>
<base href="~/" />
<link href="~/lib/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet" />
<link href="~/css/site.css" rel="stylesheet" />
</head>
<body>
<h1>My Razor Page</h1>
<p>This is content from the Razor Page.</p>
<!-- Embed the Blazor component here -->
<component type="typeof(Counter)" render-mode="ServerPrerendered" />
<hr />
<p>More content after the Blazor component.</p>
<script src="_framework/blazor.server.js" autostart="false"></script>
<script>
Blazor.start({
// Optional: Blazor configuration
}).then(function () {
Blazor.server.register({
// Register components if needed
});
});
</script>
</body>
</html>
Blazor Component (Counter.razor)
@page "/counter"
<h1>Blazor Counter</h1>
<p>Current count: @currentCount</p>
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
@code {
private int currentCount = 0;
private void IncrementCount()
{
currentCount++;
}
}
Startup.cs
and mapping Blazor endpoints.
2. Calling JavaScript from a Blazor Component
This example shows how a Blazor component can invoke a JavaScript function defined in the host page or a separate JavaScript file.
Blazor Component (.razor)
@inject IJSRuntime JSRuntime
<h3>JavaScript Interop Example</h3>
<button class="btn btn-info" @onclick="CallJavaScriptAlert">Show JavaScript Alert</button>
<p id="js-output"></p>
@code {
private async Task CallJavaScriptAlert()
{
await JSRuntime.InvokeVoidAsync("showAlert", "Hello from Blazor!");
}
}
Host Page (e.g., _Layout.cshtml or a Razor Page)
<script>
function showAlert(message) {
alert(message);
document.getElementById('js-output').innerText = 'JavaScript alert dismissed. Message was: ' + message;
}
</script>
3. Calling .NET from JavaScript
This scenario involves JavaScript code triggering a .NET method within a Blazor component. This is useful for updating UI elements or performing server-side logic based on JavaScript events.
Blazor Component (.razor)
@inject IJSRuntime JSRuntime
@implements IDisposable
<h3>.NET Callback Example</h3>
<p>Last .NET callback time: @lastCallbackTime.ToString("HH:mm:ss")</p>
@code {
private DateTime lastCallbackTime = DateTime.MinValue;
private DotNetObjectReference? dotNetObjectReference;
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
dotNetObjectReference = DotNetObjectReference.Create(this);
await JSRuntime.InvokeVoidAsync("registerDotNetCallback", dotNetObjectReference);
}
}
[JSInvokable]
public void UpdateTime()
{
lastCallbackTime = DateTime.Now;
StateHasChanged(); // Important to re-render the component
}
public void Dispose()
{
dotNetObjectReference?.Dispose();
}
}
Host Page (e.g., _Layout.cshtml or a Razor Page)
let dotnetRef;
function registerDotNetCallback(dotNetObject) {
dotnetRef = dotNetObject;
console.log("DotNet callback handler registered.");
// Example: Call .NET method periodically
setInterval(() => {
if (dotnetRef) {
dotnetRef.invokeMethodAsync('UpdateTime');
}
}, 5000); // Call every 5 seconds
}
IJSRuntime
service is crucial for interop. For calling .NET from JavaScript, you need to expose a reference to the Blazor component using DotNetObjectReference
and mark the target method with the [JSInvokable]
attribute.
Best Practices
- Minimize Interop: Excessive interop can impact performance. Design your components to handle as much logic as possible within Blazor.
- Error Handling: Implement robust error handling for both JavaScript and .NET calls.
- Data Serialization: Ensure data passed between JavaScript and .NET is correctly serialized and deserialized.
- Component Lifecycle: Be mindful of the Blazor component lifecycle when performing interop operations.