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

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++;
    }
}
Ensure your ASP.NET Core application is configured to host Blazor Server components. This typically involves adding Blazor services in 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
}
The 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