JavaScript 可以通过 JS Interop(JavaScript 互操作) 调用 Blazor 中的 C# 方法,但必须满足一个关键前提:该 C# 方法需被标记为
[JSInvokable],且在 Blazor 组件或服务中定义(推荐放在可注入的服务中,便于复用和测试)。
1. 在 C# 中定义可被 JS 调用的方法
方法必须是 public static(Blazor Server 和 WebAssembly 均要求),并添加
[JSInvokable]特性。方法名可自定义,也可用特性参数指定 JS 端调用名: 不指定名称时,JS 端默认用 C# 方法名(如
GetUserName) 指定名称更安全,避免因 C# 命名规则变化导致 JS 调用失败,例如:
[JSInvokable("get_user_info")]
示例(放在一个静态服务类中):
public static class JsInteropService
{
[JSInvokable]
public static string GetGreeting(string name) => $"Hello, {name}!";
<pre class="brush:php;toolbar:false;">[JSInvokable("calculate_total")]
public static int Add(int a, int b) => a + b;}
立即学习“Java免费学习笔记(深入)”;
2. 在 JavaScript 中调用 C# 方法
使用
DotNet.invokeMethodAsync(WebAssembly)或
DotNet.invokeMethod(同步,仅限 Server 的旧版,不推荐)。现代 Blazor(.NET 6+)统一推荐异步方式: 第一个参数是程序集名称(通常是项目名,如
"MyBlazorApp") 第二个参数是 C# 方法名(或
[JSInvokable]指定的名称) 后续参数按顺序传入 C# 方法所需参数 返回 Promise,需
await或
.then()处理结果
示例:
// JS 中调用
async function callCSharp() {
try {
const greeting = await DotNet.invokeMethodAsync('MyBlazorApp', 'GetGreeting', 'Alice');
console.log(greeting); // "Hello, Alice!"
<pre class="brush:php;toolbar:false;">const sum = await DotNet.invokeMethodAsync('MyBlazorApp', 'calculate_total', 5, 3);
console.log(sum); // 8} catch (err) { console.error('调用失败:', err); } }
3. 注意事项与常见问题
程序集名要准确:不是解决方案名,也不是命名空间,而是项目文件(.csproj)中<assemblyname></assemblyname>的值,默认为项目名;若修改过,需以实际为准 类型兼容性:JS 传参会自动转换基础类型(string/number/boolean),复杂对象需序列化为 JSON 字符串,C# 端用
JsonSerializer.Deserialize<t></t>解析 生命周期与上下文:
[JSInvokable]方法必须是 static,无法直接访问组件实例、依赖注入服务或状态。如需访问服务,应通过 static 方法间接获取(如使用
IServiceProvider全局引用,但需谨慎设计) 错误处理:C# 方法中抛出异常会变成 JS Promise 的 rejection,务必在 JS 端
catch,否则静默失败
4. 进阶:从组件内注册 JS 可调用实例方法(.NET 7+)
如果确实需要调用非静态、带状态的方法(比如访问当前组件的
NavigationManager),可借助
DotNetObjectReference.Create创建对 .NET 对象的引用,并传给 JS: C# 端创建引用并暴露给 JS(通常在
OnAfterRender或初始化时) JS 保存该引用,后续通过
invokeMethodAsync调用其公开方法(这些方法无需
static,但需加
[JSInvokable]) 使用完毕后,JS 应主动调用
dispose避免内存泄漏
这种方式适合回调、事件响应等场景,但增加了管理复杂度,日常简单交互仍优先用 static 方法。
基本上就这些。核心就三点:标记
[JSInvokable]、确保方法是
public static、JS 端用
DotNet.invokeMethodAsync正确传参。不复杂但容易忽略程序集名和异常处理。
