ASP.NET Core 6.0启用热重载后修改ViewBag出现RuntimeBinderException异常
问题原因
这个问题是ASP.NET Core 6+ 中dotnet watch热重载与Razor运行时编译结合使用时的已知缺陷:
ViewBag是基于DynamicObject的动态类型,Razor视图对ViewBag属性的绑定元数据会在视图首次编译时缓存- 修改控制器代码后,热重载只会增量更新控制器的程序集逻辑,不会同步刷新Razor视图缓存的动态绑定元数据,导致视图读取
ViewBag.test时,动态运行时找不到对应属性定义,抛出RuntimeBinderException - 全量重建解决方案会同时重新编译控制器和所有Razor视图,缓存的元数据同步更新,因此问题自动消失
解决方案
按落地优先级推荐以下三种方案:
- 调整dotnet watch配置,禁用热重载
修改launchSettings.json对应配置,关闭热重载,改为修改代码后自动重启服务重新编译所有组件:
"watch run": { "commandName": "Executable", "executablePath": "dotnet.exe", "workingDirectory": "$(ProjectDir)", "commandLineArgs": "watch run --no-hot-reload", "launchBrowser": true, "dotnetRunMessages": true, "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development", "ASPNETCORE_HOSTINGSTARTUPASSEMBLIES": "Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" }, "applicationUrl": "https://localhost:7033;http://localhost:5033" },
调整后修改控制器代码会触发服务自动重启,不会再出现动态绑定异常。
改用强类型ViewModel传递数据
放弃动态类型的ViewBag,使用强类型视图模型向视图传递数据,绑定逻辑在编译时完成,从根源上避免这类动态运行时异常。临时解决方法
如果不想修改配置,遇到错误时手动刷新一次浏览器,会触发Razor视图重新编译,缓存的绑定元数据会同步更新,错误即可消失,不需要全量重建解决方案。
内容的提问来源于stack exchange,提问作者Christoph
相关产品推荐
相关产品推荐

