C# ASP.NET Web项目如何实现多版本Newtonsoft.Json共存
你当前的配置从思路上就错了:全局程序集绑定重定向根本无法实现两个同名不同版本dll的共存。这种配置会把指定版本区间内所有对该程序集的引用,全部强制指向同一个目标版本,最终要么SignalR因为被强制加载不兼容的13.0版本崩溃,要么新类库因为被强制加载低版本6.0缺失API崩溃。
你之前写的规则oldVersion="0.0.0.0-6.0.0.0" newVersion="13.0.0.0",本质和直接把Web应用的Json.NET升级到13.0没有区别,SignalR的引用也被强制跳转到13.0,必然和直接升级一样崩溃。
核心思路是放弃全局重定向,通过codeBase配置给不同版本的Newtonsoft.Json指定独立的物理加载路径,让CLR在运行时按照程序集声明的版本号,按需加载对应路径下的dll。
步骤1:清理错误配置
首先删除web.config中你之前添加的那段bindingRedirect配置,不要保留任何针对Newtonsoft.Json的全局版本跳转规则。
步骤2:分目录存放两个版本的dll
同名dll不能直接放在bin根目录:一方面构建时两个版本会互相覆盖,另一方面CLR加载时会优先读取根目录下的dll,必然出现版本不匹配的报错。你需要在Web项目的bin目录下新建两个专属子目录,分别存放对应版本的dll:
bin/json/v6/:存放6.0.0.0版本的Newtonsoft.Json.dll,和SignalR v2.1.0依赖的版本完全一致bin/json/v13/:存放13.0.0.0版本的Newtonsoft.Json.dll,和新引入类库依赖的版本完全一致
建议提前把两个版本的dll存放到项目内独立的Libs目录,不要完全依赖NuGet包管理,避免还原时自动覆盖文件。
步骤3:添加版本对应加载配置
在web.config的configuration > runtime > assemblyBinding(注意要声明正确的xml命名空间xmlns="urn:schemas-microsoft-com:asm.v1")节点下,添加如下配置,明确告诉CLR每个版本对应的dll位置:
<dependentAssembly> <assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" /> <!-- 6.0版本从指定子目录加载 --> <codeBase version="6.0.0.0" href="bin/json/v6/Newtonsoft.Json.dll" /> <!-- 13.0版本从指定子目录加载 --> <codeBase version="13.0.0.0" href="bin/json/v13/Newtonsoft.Json.dll" /> </dependentAssembly>
步骤4:处理构建时的覆盖问题
为了避免Visual Studio构建时自动把dll复制到bin根目录、或者不同版本互相覆盖,需要做两个设置:
- 给项目中添加的两个版本Newtonsoft.Json引用,都设置「特定版本=True」、「复制本地=False」
- 在项目属性的「生成事件」中添加后置构建命令,构建完成后自动把两个版本的dll复制到对应的子目录,同时清理根目录下的残留dll:
:: 复制6.0版本dll到对应目录 xcopy /y /i "$(ProjectDir)Libs\Newtonsoft.Json\v6\Newtonsoft.Json.dll" "$(TargetDir)json\v6\" :: 复制13.0版本dll到对应目录 xcopy /y /i "$(ProjectDir)Libs\Newtonsoft.Json\v13\Newtonsoft.Json.dll" "$(TargetDir)json\v13\" :: 删除bin根目录残留的同名dll,避免优先级干扰加载逻辑 if exist "$(TargetDir)Newtonsoft.Json.dll" del /q "$(TargetDir)Newtonsoft.Json.dll"
- 不要反过来写全局重定向(把所有版本跳转到6.0),否则依赖13.0版本的类库会找不到高版本新增的API,抛出
MissingMethodException无法运行 - 不要把两个版本的dll注册到全局程序集缓存(GAC)实现共存,这种方案会大幅提升后续部署、环境迁移的复杂度,Web应用场景下完全没必要
- 发布站点时要确保bin下的两个子目录和对应dll都被正确打包发布,不要漏掉任何一个版本的文件
内容的提问来源于stack exchange,提问作者user3607582

