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

Blazor Server调用Action委托抛出NullReferenceException如何解决?

根因定位

抛出NullReferenceException的核心原因是*DownloadFileNameAction*为静态Action变量,调用Invoke时该变量尚未完成赋值,或已被其他用户请求/组件生命周期操作重置为null:

  • 静态变量在Blazor Server应用中是全局共享的,所有用户的组件实例共用同一个静态变量值,多用户同时访问页面时后初始化的组件会覆盖之前的赋值,极端情况下会被重置为null
  • 若JS端调用的时机早于组件OnInitializedAsync方法执行完成,变量还没被赋值就被调用
  • 组件销毁后未清理静态变量,重新加载组件前收到JS调用也会触发空引用

解决方案

1. 临时修复:先加空值判断避免直接抛异常

修改TransferFileName方法,调用前先做非空校验:

[JSInvokable]
public static void TransferFileName(string fileName)
{
    DownloadFileNameAction?.Invoke(fileName);
}

这一步只能避免异常抛出,无法解决多用户回调冲突、回调触发时机不对的核心问题。

2. 永久修复:改用实例方法绑定的JS互操作方案

Blazor官方推荐使用实例绑定的方式处理JS调用C#的场景,避免静态变量的全局共享问题,修改代码如下:

C#侧修改

// 移除静态修饰符,改为实例变量
public Action<string> DownloadFileNameAction;

// 移除静态修饰符,改为实例方法
[JSInvokable]
public void TransferFileName(string fileName)
{
    DownloadFileNameAction?.Invoke(fileName);
}

protected override async Task OnInitializedAsync()
{
    DownloadFileNameAction = TransferFileToUserForDownload;
    // 创建当前组件的实例引用,传递给JS端绑定
    var dotNetRef = DotNetObjectReference.Create(this);
    await JSRuntime.InvokeVoidAsync("registerComponentRef", dotNetRef);
}

// 实现IDisposable接口,组件销毁时清理引用避免内存泄漏
public void Dispose()
{
    DownloadFileNameAction = null;
}

// 把async void改为async Task,避免方法内异常无法被捕获
public async Task TransferFileToUserForDownload(string fileName)
{
   var getFileName = fileName;
   // 此处省略其他代码
}

JS侧修改

// 存储C#组件实例引用
let componentRef = null;
// 供C#侧调用的注册方法
function registerComponentRef(ref) {
    componentRef = ref;
}

// 原来调用C#静态方法的位置,替换为调用实例方法
function triggerFileTransfer(fileName) {
    if(componentRef) {
        componentRef.invokeMethodAsync('TransferFileName', fileName);
    }
}

修改后每个用户的组件实例独立绑定回调,不会出现多用户冲突,也不会因为初始化时机问题抛出空引用异常。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 17:54:02