You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Blazor WebAssembly+ReactiveUI MVVM:ViewModel调用JS函数依赖注入问题

How to Call JavaScript Functions from a ReactiveUI ViewModel in Blazor WebAssembly

Great question! The core issue here is that your ReactiveUI ViewModel isn't being managed by Blazor's dependency injection (DI) container. Blazor automatically handles injection for components that inherit from ComponentBase, but it won't inject dependencies into ViewModels you instantiate manually or that are created outside the DI pipeline. Let's walk through the fix step by step.

Step 1: Register Your ViewModel with Blazor's DI Container

First, you need to tell Blazor's DI system to manage your TestViewModel instance. Open your Program.cs and add this line (choose the appropriate lifetime: Scoped, Transient, or Singleton based on your needs):

builder.Services.AddScoped<TestViewModel>();

Step 2: Use Constructor Injection for IJSRuntime

Property injection with the [Inject] attribute only works for Blazor components (classes inheriting ComponentBase). For ViewModels, constructor injection is the reliable approach. Update your ViewModel to accept IJSRuntime via the constructor, and use ReactiveCommand.CreateFromTask since we'll be calling an asynchronous JavaScript method:

using ReactiveUI;
using Microsoft.JSInterop;
using System.Reactive;
using System.Threading.Tasks;

public class TestViewModel : ReactiveObject 
{ 
    private readonly IJSRuntime _jsRuntime;

    public ReactiveCommand<Unit, Unit> AlertCommand { get; } 

    // Inject IJSRuntime via constructor
    public TestViewModel(IJSRuntime jsRuntime) 
    { 
        _jsRuntime = jsRuntime;
        // Use CreateFromTask for async command logic
        AlertCommand = ReactiveCommand.CreateFromTask(ShowAlertMessage); 
    } 

    private async Task ShowAlertMessage() 
    { 
        // Await the async JS invocation to avoid fire-and-forget issues
        await _jsRuntime.InvokeAsync<bool>("showAlert", "Hello World!"); 
    } 
}

Step 3: Inject the ViewModel into Your Blazor Component

Instead of manually instantiating the ViewModel in your component, let Blazor's DI inject it. Here's how your component might look:

@page "/test-alert"
@inject TestViewModel ViewModel

<h3>Test Alert from ViewModel</h3>

<button class="btn btn-primary" @onclick="ExecuteAlertCommand">
    Show Alert
</button>

@code {
    private void ExecuteAlertCommand()
    {
        // Subscribe to the command execution (handle errors if needed)
        ViewModel.AlertCommand.Execute().Subscribe();
    }
}

Why Your Original Approach Failed

  • Manual ViewModel Instantiation: If you were creating the ViewModel with new TestViewModel(), Blazor's DI had no way to inject IJSRuntime into it. The DI container can only inject dependencies into objects it creates itself.
  • Property Injection Limitation: The [Inject] attribute is processed by Blazor's component activation pipeline, which doesn't apply to regular classes like your ViewModel. Constructor injection is the standard way to get dependencies into non-component classes in Blazor.

Key Notes

  • Always await IJSRuntime.InvokeAsync to ensure the JavaScript call completes properly and to handle any potential exceptions.
  • Use ReactiveCommand.CreateFromTask for asynchronous command logic instead of ReactiveCommand.Create, which is meant for synchronous operations.
  • Choose the correct DI lifetime for your ViewModel: Scoped is usually a good fit for Blazor components, as it matches the component's lifecycle.

内容的提问来源于stack exchange,提问作者Rahul

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 08:00:59