在混合应用开发、桌面端嵌入网页等场景中,C#代码和JavaScript函数的相互调用是非常常见的需求,不同技术栈下的实现方式存在差异,下面分别介绍主流的实现方案。

C#调用JavaScript函数
桌面端基于WebBrowser控件(WinForms/WPF)
WinForms或WPF中如果使用WebBrowser控件加载网页,可以通过控件的Document.InvokeScript方法调用页面中的JavaScript函数。
首先前端页面需要定义对应的JavaScript函数:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>测试页面</title>
</head>
<body>
<script type="text/javascript">
// 供C#调用的JavaScript函数
function showMessage(msg) {
alert("来自C#的消息:" + msg);
return "JS已收到消息";
}
</script>
</body>
</html>然后C#端调用该函数的代码如下:
// WinForms中WebBrowser控件调用JS函数示例
private void CallJsFunction()
{
// 假设webBrowser1已经加载了上面的HTML页面
if (webBrowser1.Document != null)
{
// 调用名为showMessage的JS函数,传入参数
object result = webBrowser1.Document.InvokeScript("showMessage", new object[] { "Hello from C#" });
// 输出JS函数的返回值
MessageBox.Show("JS返回结果:" + result?.ToString());
}
}Web端基于Blazor框架
Blazor提供了JS互操作服务,可以便捷地调用JavaScript函数。首先在页面中定义JS函数:
<script>
// 供Blazor调用的JS函数
window.blazorJsFunctions = {
showAlert: function (message) {
alert(message);
return "JS处理完成";
},
calculateSum: function (a, b) {
return a + b;
}
};
</script>C#端注入IJSRuntime服务后调用JS函数:
using Microsoft.JSInterop;
using System.Threading.Tasks;
public class JsCallService
{
private readonly IJSRuntime _jsRuntime;
public JsCallService(IJSRuntime jsRuntime)
{
_jsRuntime = jsRuntime;
}
// 调用无返回值的JS函数
public async Task CallAlert()
{
await _jsRuntime.InvokeVoidAsync("blazorJsFunctions.showAlert", "Blazor调用JS成功");
}
// 调用有返回值的JS函数
public async TaskCallCalculate()
{
int result = await _jsRuntime.InvokeAsync("blazorJsFunctions.calculateSum", 10, 20);
return result;
}
} JavaScript调用C#函数
桌面端基于WebBrowser控件
需要将C#的对象暴露给JavaScript环境,通过设置WebBrowser控件的ObjectForScripting属性实现。
首先定义需要暴露给JS的C#类,需要标记ComVisible特性:
using System.Runtime.InteropServices;
using System.Windows.Forms;
[ComVisible(true)] // 必须标记为ComVisible,否则JS无法访问
public class JsBridge
{
// 供JS调用的C#方法
public string HandleJsMessage(string message)
{
MessageBox.Show("收到JS消息:" + message);
return "C#已处理你的消息";
}
public int Add(int a, int b)
{
return a + b;
}
}然后在窗体中设置ObjectForScripting:
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
// 将JsBridge实例暴露给JS环境,JS中可以通过window.external访问
webBrowser1.ObjectForScripting = new JsBridge();
// 加载测试页面
webBrowser1.Navigate("test.html");
}
}前端JavaScript调用C#方法的代码:
// 调用C#暴露的方法
function callCSharp()
{
// window.external对应C#设置的ObjectForScripting实例
var result = window.external.HandleJsMessage("Hello from JS");
alert("C#返回结果:" + result);
var sum = window.external.Add(5, 3);
alert("5+3的结果是:" + sum);
}Web端基于Blazor框架
Blazor中可以让JavaScript调用C#的静态方法或者组件实例方法,需要给方法标记[JSInvokable]特性。
首先定义可被JS调用的C#方法:
using Microsoft.JSInterop;
using System.Threading.Tasks;
public class CSharpFunctions
{
// 标记JSInvokable特性,指定JS中调用的函数名
[JSInvokable("handleJsCall")]
public static string HandleJsCall(string message)
{
return $"C#收到JS的消息:{message},处理完成";
}
[JSInvokable]
public static int Multiply(int a, int b)
{
return a * b;
}
}JavaScript中调用C#方法的代码:
// 调用C#静态方法
async function callCSharpStatic() {
// 调用带指定名称的JSInvokable方法
const result1 = await DotNet.invokeMethodAsync('YourAssemblyName', 'handleJsCall', 'JS调用测试');
alert(result1);
// 调用默认方法名的JSInvokable方法,方法名和C#方法名一致
const result2 = await DotNet.invokeMethodAsync('YourAssemblyName', 'Multiply', 4, 6);
alert('4*6的结果是:' + result2);
}如果是调用Blazor组件实例的方法,需要先给组件实例生成引用,再传递给JS:
@page "/js-call"
@using Microsoft.JSInterop
@implements IDisposable
<button @onclick="TriggerJsCall">触发JS调用C#实例方法</button>
@code {
private DotNetObjectReference<JsCallComponent>? objRef;
[JSInvokable]
public string InstanceMethod(string msg)
{
return $"组件实例收到消息:{msg}";
}
protected override void OnInitialized()
{
objRef = DotNetObjectReference.Create(this);
}
public void Dispose()
{
objRef?.Dispose();
}
// 将组件引用传递给JS
public async Task TriggerJsCall()
{
await JSRuntime.InvokeVoidAsync("callCSharpInstance", objRef);
}
}对应的JS代码:
function callCSharpInstance(dotNetRef) {
// 调用组件实例的JSInvokable方法
dotNetRef.invokeMethodAsync('InstanceMethod', '来自JS的实例调用')
.then(result => alert(result));
}注意事项
- 桌面端WebBrowser控件基于IE内核,对现代JavaScript语法支持有限,如需使用新特性建议更换为WebView2控件,调用方式类似但接口有差异。
- Blazor的JS互操作中,调用异步JS函数时需要使用对应的异步方法,避免阻塞线程。
- 暴露给JavaScript的C#方法需要注意权限控制,避免未授权的调用造成安全问题。
- 跨语言调用时参数类型需要匹配,比如C#的int对应JS的number,string对应JS的string,复杂对象需要序列化和反序列化处理。
C#JavaScript相互调用WebBrowserJS互操作修改时间:2026-06-02 22:03:02