升级MS Build Tools 2017后MSBuild替换Newtonsoft.Json.dll为旧版本求助
我之前也遇到过几乎一模一样的问题,升级MSBuild 2017 15.7.2之后,Web Deploy的旧版Newtonsoft.Json.dll总是偷偷覆盖NuGet引入的9.0.1版本,折腾了好一阵子才搞清楚来龙去脉,分享下我的解决方案:
根本原因
问题出在MSBuild 15.7.2新增/调整的Web Deploy相关构建目标上。当你使用MSBuild运行器执行包含Web部署步骤的构建时,MSBuild会自动从Web Deploy的安装目录(就是你提到的C:\Program Files (x86)\IIS\Microsoft Web Deploy V3或C:\Program Files\IIS\Microsoft Web Deploy V3)复制它自身依赖的Newtonsoft.Json.dll到输出目录。
Web Deploy V3内置的这个DLL版本是6.0.4,而且这个复制操作的执行顺序晚于NuGet包的复制步骤,所以就会出现你看到的“版本反复切换,最终旧版本留存”的情况——先复制NuGet的9.0.1,之后Web Deploy的任务又把6.0.4覆盖上去。
正式解决方法
方法一:添加程序集绑定重定向(最稳妥的快速修复)
不管构建时输出目录里有哪个版本,我们可以强制CLR运行时加载9.0.1版本。在Web API项目的web.config(以及单元测试项目的app.config)中添加以下配置:
<configuration> <runtime> <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <dependentAssembly> <assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" /> <bindingRedirect oldVersion="0.0.0.0-9.0.1.0" newVersion="9.0.1.0" /> </dependentAssembly> </assemblyBinding> </runtime> </configuration>
这个配置会告诉运行时:所有版本在0.0.0.0到9.0.1.0之间的Newtonsoft.Json,都替换成9.0.1.0版本,彻底规避版本冲突。
方法二:修改MSBuild目标,阻止Web Deploy复制旧DLL
如果不想依赖运行时重定向,我们可以直接从构建流程里移除Web Deploy的旧DLL复制操作。在你的Web API项目的.csproj文件末尾(</Project>标签之前)添加以下自定义目标:
<Target Name="RemoveOldNewtonsoftFromWebDeploy" BeforeTargets="MSDeployPublish"> <ItemGroup> <MSDeploySourceFiles Remove="@(MSDeploySourceFiles)" Condition="'%(FileName)%(Extension)' == 'Newtonsoft.Json.dll'" /> </ItemGroup> </Target>
这个目标会在执行MSDeployPublish任务前,从Web Deploy要复制的文件列表里移除旧的Newtonsoft.Json.dll,这样就不会覆盖NuGet的版本了。
方法三:升级Web Deploy到最新版本
Web Deploy V3是比较旧的版本了,微软已经推出了Web Deploy V4,它内置的Newtonsoft.Json.dll版本已经更新到了更高的版本(和你的9.0.1兼容甚至更高)。你可以卸载旧的Web Deploy V3,安装最新的Web Deploy版本,这样构建时复制的就是新版本的DLL,自然不会和NuGet版本冲突。
方法四:确认NuGet引用的优先级设置
检查所有项目中Newtonsoft.Json的引用属性,确保:
Specific Version设置为True:强制使用指定的9.0.1版本,而不是自动匹配高版本Copy Local设置为True:确保NuGet包的DLL会被复制到输出目录
你可以在Visual Studio里右键引用→属性修改,或者直接在.csproj文件里确认配置:
<Reference Include="Newtonsoft.Json, Version=9.0.1.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL"> <HintPath>..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll</HintPath> <SpecificVersion>True</SpecificVersion> <Private>True</Private> <!-- 对应Copy Local=True --> </Reference>
内容的提问来源于stack exchange,提问作者Eirik Fauske

