Web Forms项目重复添加System.Web.WebPages.Razor.dll版本冲突问题
我手头有个包含遗留Web Forms项目的Visual Studio解决方案,最近碰到个棘手的问题:部署服务器上根本不存在System.Web.WebPages.Razor.dll,但本地每次删除它之后,构建解决方案时它又会自动生成。更麻烦的是,程序要求的是2.0.0.0版本,可本地生成的却是3.x版本,版本冲突直接引发了部署报错。我搜遍了Web.config和项目全文都没找到相关引用,但这dll就是顽固地自动回来——关键服务器上没它也能正常运行,说明它本就不该存在。现在我主要想搞清楚它重复添加的原因,其次是怎么修复版本冲突(有没有对应的NuGet包?)
报错堆栈跟踪:
服务器错误 '/MyApp' 应用程序。无法加载文件或程序集“System.Web.WebPages.Razor, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35”或其依赖项之一。找到的程序集清单定义与程序集引用不匹配。(异常来自 HRESULT:0x80131040)
描述: 当前Web请求执行期间发生未处理异常。请查看堆栈跟踪以获取有关错误及其代码起源的更多信息。
异常详细信息: System.IO.FileLoadException: 无法加载文件或程序集“System.Web.WebPages.Razor, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35”或其依赖项之一。找到的程序集清单定义与程序集引用不匹配。(异常来自 HRESULT:0x80131040)
源错误: 当前Web请求执行期间生成未处理异常。可通过下面的异常堆栈跟踪信息确定异常的来源和位置。
程序集加载跟踪: 以下信息有助于确定为何无法加载程序集“System.Web.WebPages.Razor, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35”。
警告: 程序集绑定日志已关闭。要启用程序集绑定失败日志记录,请将注册表值 [HKLM\Software\Microsoft\Fusion!EnableLog] (DWORD) 设置为1。注意: 程序集绑定失败日志记录会带来一定性能开销。要关闭此功能,请移除注册表值 [HKLM\Software\Microsoft\Fusion!EnableLog]。
堆栈跟踪:
[FileLoadException: 无法加载文件或程序集“System.Web.WebPages.Razor, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35”或其依赖项之一。找到的程序集清单定义与程序集引用不匹配。(异常来自 HRESULT:0x80131040)]
System.Web.Mvc.PreApplicationStartCode.Start() +0[InvalidOperationException: 类型System.Web.Mvc.PreApplicationStartCode的预应用启动初始化方法Start引发异常,错误消息如下: 无法加载文件或程序集“System.Web.WebPages.Razor, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35”或其依赖项之一。找到的程序集清单定义与程序集引用不匹配。(异常来自 HRESULT:0x80131040)。]
System.Web.Compilation.BuildManager.InvokePreStartInitMethodsCore(ICollection1 methods, Func1 setHostingEnvironmentCultures) +850
System.Web.Compilation.BuildManager.InvokePreStartInitMethods(ICollection`1 methods) +162
System.Web.Compilation.BuildManager.CallPreStartInitMethods(String preStartInitListPath, Boolean& isRefAssemblyLoaded) +128
System.Web.Compilation.BuildManager.ExecutePreAppStart() +170
System.Web.Hosting.HostingEnvironment.Initialize(ApplicationManager appManager, IApplicationHost appHost, IConfigMapPathFactory configMapPathFactory, HostingEnvironmentParameters hostingParameters, PolicyLevel policyLevel, Exception appDomainCreationException) +820[HttpException (0x80004005): 类型System.Web.Mvc.PreApplicationStartCode的预应用启动初始化方法Start引发异常,错误消息如下: 无法加载文件或程序集“System.Web.WebPages.Razor, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35”或其依赖项之一。找到的程序集清单定义与程序集引用不匹配。(异常来自 HRESULT:0x80131040)。]
System.Web.HttpRuntime.FirstRequestInit(HttpContext context) +523
System.Web.HttpRuntime.EnsureFirstRequestInit(HttpContext context) +107
System.Web.HttpRuntime.ProcessRequestNotificationPrivate(IIS7WorkerRequest wr, HttpContext context) +688
一、找出dll自动生成的根源
我之前处理过类似的问题,这类自动生成的dll大多是间接依赖或者隐藏配置导致的,你可以按这些步骤排查:
- 检查NuGet依赖包:虽然你没搜到直接引用,但很可能是某个Web相关包(比如
Microsoft.AspNet.Mvc、Microsoft.AspNet.WebPages)的间接依赖。打开NuGet包管理器,查看已安装的包,看看有没有依赖System.Web.WebPages.Razor的项——旧版Mvc通常会绑定2.0版本的Razor,而你本地可能安装了更高版本的依赖,导致版本冲突。 - 编辑项目文件(.csproj):有时候Web.config里没记录,但项目文件里会藏着引用。右键项目→“编辑项目文件”,搜索
System.Web.WebPages.Razor,看看有没有<Reference>节点,或者设置了<CopyLocal>true</CopyLocal>的项。如果有,直接删除这个引用节点,或者把CopyLocal改成false,这样构建时就不会复制到输出目录了。 - 排查构建脚本:检查项目的自定义构建事件,右键项目→“属性”→“生成事件”,看看预生成/后生成命令里有没有复制这个dll的指令,有的话删掉就行。
- 查看传递依赖链:在VS的“依赖项”节点里展开“程序集”,找到
System.Web.WebPages.Razor,右键它→“属性”,就能看到它是哪个父依赖带进来的。找到父依赖后,要么升级父依赖到兼容的版本,要么在NuGet里设置版本约束,阻止它引入旧版本。
二、修复版本冲突问题
针对版本不匹配的问题,有几个实用的解决办法:
- 安装对应版本的NuGet包:确实有专门的
Microsoft.AspNet.WebPages.Razor包,你可以直接安装需要的版本。如果要匹配程序要求的2.0.0.0,打开NuGet包管理器控制台,执行:
如果想统一到3.x版本,就安装3.x的包,同时记得把依赖它的其他包(比如Mvc)也升级到兼容3.x的版本,避免新的冲突。Install-Package Microsoft.AspNet.WebPages.Razor -Version 2.0.30506.0 - 添加程序集绑定重定向:如果不想改动包版本,可以在Web.config的
<runtime>节点里加一段重定向配置,让程序把对2.0.0.0版本的请求转向你本地的3.x版本。示例代码:<runtime> <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <dependentAssembly> <assemblyIdentity name="System.Web.WebPages.Razor" publicKeyToken="31bf3856ad364e35" culture="neutral" /> <bindingRedirect oldVersion="0.0.0.0-3.0.0.0" newVersion="3.0.0.0" /> <!-- 把newVersion改成你本地实际的版本号 --> </dependentAssembly> </assemblyBinding> </runtime> - 清理项目输出目录:有时候旧的dll残存在bin或obj目录里,构建时会被重复复制。右键项目→“清理”,然后手动删除bin和obj文件夹,再重新构建,大概率能解决残留问题。
内容的提问来源于stack exchange,提问作者niico

