升级Visual Studio后,.Net调用JavaScript代码失效问题
问题:VS2022升级至v17.8.2后Blazor组件JS调用失败
原本在Visual Studio 2022 v17.7.6及其他电脑上可正常运行的Blazor组件代码,升级VS至v17.8.2后抛出JS函数未找到的错误,使用.NET Core 6环境,代码位于页面组件中。
后端C#代码
[Inject] IJSRuntime? JSRT { get; set; } DotNetObjectReference<GraphicalUngrouped>? objectReference; protected override async Task OnAfterRenderAsync(bool firstRender) { if (firstRender) await BundleAndSendDotNetHelper(); } private async Task BundleAndSendDotNetHelper() { objectReference = DotNetObjectReference.Create(this); if (JSRT != null) { await JSRT.InvokeAsync<string>("SetDotNetHelper", objectReference); } }
Razor页面代码
<script> function SetDotNetHelper(dotNetHelper) { window.dotNetHelper = dotNetHelper; } </script>
抛出错误
Unhandled exception rendering component: Could not find 'SetDotNetHelper' ('SetDotNetHelper' was undefined).
Error: Could not find 'SetDotNetHelper' ('SetDotNetHelper' was undefined). at https://localhost:7211/_framework/blazor.webassembly.js:1:328 at Array.forEach (<anonymous>)...
问题原因
VS2022 v17.8.x版本对Blazor WebAssembly的组件内脚本加载机制做了调整,组件内嵌的<script>标签不再保证在组件首次渲染(firstRender=true)前完成全局注入。当OnAfterRenderAsync执行时,脚本函数还未注册到window对象,导致调用失败。
解决建议
方案一:将脚本移至全局入口文件
把组件内的<script>内容移到wwwroot/index.html的<body>末尾,确保脚本在Blazor应用初始化前加载完成:
<!-- wwwroot/index.html --> <body> <!-- 其他内容 --> <script src="_framework/blazor.webassembly.js"></script> <script> function SetDotNetHelper(dotNetHelper) { window.dotNetHelper = dotNetHelper; } </script> </body>
方案二:使用ES模块加载脚本
将脚本单独存入wwwroot/js/helpers.js文件,通过IJSRuntime异步加载模块:
// wwwroot/js/helpers.js export function SetDotNetHelper(dotNetHelper) { window.dotNetHelper = dotNetHelper; }
修改后端C#代码,引入模块加载逻辑:
[Inject] IJSRuntime? JSRT { get; set; } DotNetObjectReference<GraphicalUngrouped>? objectReference; private IJSObjectReference? module; protected override async Task OnAfterRenderAsync(bool firstRender) { if (firstRender) { module = await JSRT!.InvokeAsync<IJSObjectReference>("import", "./js/helpers.js"); objectReference = DotNetObjectReference.Create(this); await module.InvokeVoidAsync("SetDotNetHelper", objectReference); } } public async ValueTask DisposeAsync() { if (module != null) { await module.DisposeAsync(); } objectReference?.Dispose(); }
方案三:临时延迟调用(不推荐)
在OnAfterRenderAsync中添加小延迟,等待脚本加载完成(仅应急使用,不适合生产环境):
protected override async Task OnAfterRenderAsync(bool firstRender) { if (firstRender) { await Task.Delay(100); await BundleAndSendDotNetHelper(); } }
内容的提问来源于stack exchange,提问作者Slugsie
相关产品推荐
相关产品推荐

